diff --git a/contrib/bind9/CHANGES b/contrib/bind9/CHANGES index e8383c62baf4..4e3152fd0bb7 100644 --- a/contrib/bind9/CHANGES +++ b/contrib/bind9/CHANGES @@ -1,15 +1,15 @@ - --- 9.8.5-P2 released --- + --- 9.9.3-P2 released --- 3621. [security] Incorrect bounds checking on private type 'keydata' can lead to a remotely triggerable REQUIRE failure (CVE-2013-4854). [RT #34238] - --- 9.8.5-P1 released --- + --- 9.9.3-P1 released --- 3584. [security] Caching data from an incompletely signed zone could trigger an assertion failure in resolver.c [RT #33690] - --- 9.8.5 released --- + --- 9.9.3 released --- 3568. [cleanup] Add a product description line to the version file, to be reported by named -v/-V. [RT #33366] @@ -21,7 +21,7 @@ 3561. [bug] dig: issue a warning if an EDNS query returns FORMERR or NOTIMP. Adjust usage message. [RT #33363] - --- 9.8.5rc1 released --- + --- 9.9.3rc2 released --- 3560. [bug] isc-config.sh did not honor includedir and libdir when set via configure. [RT #33345] @@ -31,6 +31,8 @@ 3558. [bug] IXFR of a DLZ stored zone was broken. [RT #33331] +3557. [bug] Reloading redirect zones was broken. [RT #33292] + 3556. [maint] Added AAAA for D.ROOT-SERVERS.NET. 3555. [bug] Address theoretical race conditions in acache.c @@ -51,9 +53,7 @@ 3547. [bug] Some malformed unknown rdata records were not properly detected and rejected. [RT #33129] -3056. [func] Added support for URI resource record. [RT #23386] - - --- 9.8.5rc1 released --- + --- 9.9.3rc1 released --- 3546. [func] Add EUI48 and EUI64 types. [RT #33082] @@ -64,8 +64,6 @@ 3543. [bug] Update socket structure before attaching to socket manager after accept. [RT #33084] -3542. [bug] masterformat system test was broken. [RT #33086] - 3541. [bug] Parts of libdns were not properly initialized when built in libexport mode. [RT #33028] @@ -94,6 +92,17 @@ 3530. [contrib] Better RTT tracking in queryperf. [RT #30128] +3528. [func] New "dnssec-coverage" command scans the timing + metadata for a set of DNSSEC keys and reports if a + lapse in signing coverage has been scheduled + inadvertently. (Note: This tool depends on python; + it will not be built or installed on systems that + do not have a python interpreter.) [RT #28098] + +3527. [compat] Add a URI to allow applications to explicitly + request a particular XML schema from the statistics + channel, returning 404 if not supported. [RT #32481] + 3526. [cleanup] Set up dependencies for unit tests correctly during build. [RT #32803] @@ -102,7 +111,7 @@ 3520. [bug] 'mctx' was not being referenced counted in some places where it should have been. [RT #32794] - --- 9.8.5b2 released --- + --- 9.9.3b2 released --- 3517. [bug] Reorder destruction to avoid shutdown race. [RT #32777] @@ -114,6 +123,8 @@ to 1024 bits for hmac-sha384 and hmac-sha512. [RT #32753] +3511. [doc] Improve documentation of redirect zones. [RT #32756] + 3509. [cleanup] Added a product line to version file to allow for easy naming of different products (BIND vs BIND ESV, for example). [RT #32755] @@ -121,8 +132,24 @@ 3508. [contrib] queryperf was incorrectly rejecting the -T option. [RT #32338] +3507. [bug] Statistics channel XSL (when built with + --enable-newstats) had a glitch when attempting + to chart query data before any queries had been + received. [RT #32620] + +3505. [bug] When setting "max-cache-size" and "max-acache-size", + larger values than 4 gigabytes could not be set + explicitly, though larger sizes were available + when setting cache size to 0. This has been + corrected; the full range is now available. + [RT #32358] + 3503. [doc] Clarify size_spec syntax. [RT #32449] +3501. [func] zone-statistics now takes three options: full, + terse, and none. "yes" and "no" are retained as + synonyms for full and terse, respectively. [RT #29165] + 3500. [security] Support NAPTR regular expression validation on all platforms without using libregex, which can be vulnerable to memory exhaustion attack @@ -141,6 +168,15 @@ NSIP and NSDNAME checking. --enable-rpz-nsip and --enable-rpz-nsdname are now the default. [RT #32251] +3493. [contrib] Added BDBHPT dynamically-lodable DLZ module, + contributed by Mark Goldfinch. [RT #32549] + +3492. [bug] Fixed a regression in zone loading performance + due to lock contention. [RT #30399] + +3491. [bug] Slave zones using inline-signing must specify a + file name. [RT #31946] + 3489. [bug] --enable-developer now turns on ISC_LIST_CHECKINIT. When cloning a rdataset do not copy the link contents. [RT #32651] @@ -156,8 +192,14 @@ 3485. [cleanup] Only compile openssl_gostlink.c if we support GOST. +3483. [bug] Corrected XSL code in use with --enable-newstats. + [RT #32587] + 3481. [cleanup] Removed use of const const in atf. +3480. [bug] Silence logging noise when setting up zone + statistics. [RT #32525] + 3479. [bug] Address potential memory leaks in gssapi support code. [RT #32405] @@ -167,10 +209,18 @@ 3474. [bug] nsupdate could assert when the local and remote address families didn't match. [RT #22897] +3473. [bug] dnssec-signzone/verify could incorrectly report + an error condition due to an empty node above an + opt-out delegation lacking an NSEC3. [RT #32072] + +3471. [bug] The number of UDP dispatches now defaults to + the number of CPUs even if -n has been set to + a higher value. [RT #30964] + 3470. [bug] Slave zones could fail to dump when successfully refreshing after an initial failure. [RT #31276] - --- 9.8.5b1 released --- + --- 9.9.3b1 released --- 3468. [security] RPZ rules to generate A records (but not AAAA records) could trigger an assertion failure when used in @@ -179,6 +229,9 @@ 3467. [bug] Added checks in dnssec-keygen and dnssec-settime to check for delete date < inactive date. [RT #31719] +3466. [contrib] Corrected the DNS_CLIENTINFOMETHODS_VERSION check + in DLZ example driver. [RT #32275] + 3465. [bug] Handle isolated reserved ports. [RT #31778] 3464. [maint] Updates to PKCS#11 openssl patches, supporting @@ -192,6 +245,8 @@ 3461. [bug] Negative responses could incorrectly have AD=1 set. [RT #32237] +3460. [bug] Only link against readline where needed. [RT #29810] + 3458. [bug] Return FORMERR when presented with a overly long domain named in a request. [RT #29682] @@ -203,6 +258,9 @@ 3454. [port] sparc64: improve atomic support. [RT #25182] +3453. [bug] 'rndc addzone' of a zone with 'inline-signing yes;' + failed. [RT #31960] + 3452. [bug] Accept duplicate singleton records. [RT #32329] 3451. [port] Increase per thread stack size from 64K to 1M. @@ -266,9 +324,19 @@ 3427. [bug] dig +trace incorrectly displayed name server addresses instead of names. [RT #31641] +3426. [bug] dnssec-checkds: Clearer output when records are not + found. [RT #31968] + 3425. [bug] "acacheentry" reference counting was broken resulting in use after free. [RT #31908] +3424. [func] dnssec-dsfromkey now emits the hash without spaces. + [RT #31951] + +3423. [bug] "rndc signing -nsec3param" didn't accept the full + range of possible values. Address portability issues. + [RT #31938] + 3422. [bug] Added a clear error message for when the SOA does not match the referral. [RT #31281] @@ -279,9 +347,22 @@ 3419. [bug] Memory leak on validation cancel. [RT #31869] +3417. [func] Optional new XML schema (version 3.0) for the + statistics channel adds query type statistics at the + zone level, and flattens the XML tree and uses + compressed format to optimize parsing. Includes new XSL + that permits charting via the Google Charts API on + browsers that support javascript in XSL. To enable, + build with "configure --enable-newstats". [RT #30023] + +3416. [bug] Named could die on shutdown if running with 128 UDP + dispatches per interface. [RT #31743] + 3415. [bug] named could die with a REQUIRE failure if a validation was canceled. [RT #31804] +3414. [bug] Address locking issues found by Coverity. [RT #31626] + 3412. [bug] Copy timeval structure from control message data. [RT #31548] @@ -295,6 +376,11 @@ (DNS-based Authentication of Named Entities). [RT #30513] +3408. [bug] Some DNSSEC-related options (update-check-ksk, + dnssec-loadkeys-interval, dnssec-dnskey-kskonly) + are now legal in slave zones as long as + inline-signing is in use. [RT #31078] + 3406. [bug] mem.c: Fix compilation errors when building with ISC_MEM_TRACKLINES or ISC_MEMPOOL_NAMES disabled. Also, ISC_MEM_DEBUG is no longer optional. [RT #31559] @@ -316,6 +402,13 @@ in the "srcid" file in the build tree and normally set to the most recent git hash. [RT #31494] +3399. [port] netbsd: rename 'bool' parameter to avoid namespace + clash. [RT #31515] + +3398. [bug] SOA parameters were not being updated with inline + signed zones if the zone was modified while the + server was offline. [RT #29272] + 3397. [bug] dig crashed when using +nssearch with +tcp. [RT #25298] 3396. [bug] OPT records were incorrectly removed from signed, @@ -348,11 +441,10 @@ 3386. [bug] Address locking violation when generating new NSEC / NSEC3 chains. [RT #31224] -3384. [bug] Improved logging of crypto errors. [RT #30963] +3385. [bug] named-checkconf didn't detect missing master lists + in also-notify clauses. [RT #30810] -3383. [security] A certain combination of records in the RBT could - cause named to hang while populating the additional - section of a response. [RT #31090] +3384. [bug] Improved logging of crypto errors. [RT #30963] 3382. [bug] SOA query from slave used use-v6-udp-ports range, if set, regardless of the address family in use. @@ -370,6 +462,9 @@ 3378. [bug] Handle missing 'managed-keys-directory' better. [RT #30625] +3377. [bug] Removed spurious newline from NSEC3 multiline + output. [RT #31044] + 3376. [bug] Lack of EDNS support was being recorded without a successful response. [RT #30811] @@ -386,19 +481,34 @@ add NS RRsets to the additional section or not. [RT #30479] - --- 9.8.4 released --- +3316. [tuning] Improved locking performance when recursing. + [RT #28836] + +3315. [tuning] Use multiple dispatch objects for sending upstream + queries; this can improve performance on busy + multiprocessor systems by reducing lock contention. + [RT #28605] + + --- 9.9.2 released --- + +3383. [security] A certain combination of records in the RBT could + cause named to hang while populating the additional + section of a response. [RT #31090] 3373. [bug] win32: open raw files in binary mode. [RT #30944] 3364. [security] Named could die on specially crafted record. [RT #30416] - --- 9.8.4rc1 released --- + --- 9.9.2rc1 released --- + +3370. [bug] Address use after free while shutting down. [RT #30241] 3369. [bug] nsupdate terminated unexpectedly in interactive mode if built with readline support. [RT #29550] -3368. [bug] and were not C++ safe. +3368. [bug] , and + were not C++ safe. 3367. [bug] dns_dnsseckey_create() result was not being checked. [RT #30685] @@ -417,6 +527,9 @@ could trigger an assertion failure on startup. [RT #27730] +3361. [bug] "rndc signing -nsec3param" didn't work correctly + when salt was set to '-' (no salt). [RT #30099] + 3360. [bug] 'host -w' could die. [RT #18723] 3359. [bug] An improperly-formed TSIG secret could cause a @@ -428,10 +541,12 @@ approaching their expiry, so they don't remain in caches after expiry. [RT #26429] - --- 9.8.4b1 released --- +3355. [port] Use more portable awk in verify system test. 3354. [func] Improve OpenSSL error logging. [RT #29932] + --- 9.9.2b1 released --- + 3353. [bug] Use a single task for task exclusive operations. [RT #29872] @@ -446,6 +561,8 @@ ISC_MEM_DEBUGCTX memory debugging flag is set. [RT #30240] +3349. [bug] Change #3345 was incomplete. [RT #30233] + 3348. [bug] Prevent RRSIG data from being cached if a negative record matching the covering type exists at a higher trust level. Such data already can't be retrieved from @@ -459,16 +576,42 @@ 3346. [security] Bad-cache data could be used before it was initialized, causing an assert. [RT #30025] +3345. [bug] Addressed race condition when removing the last item + or inserting the first item in an ISC_QUEUE. + [RT #29539] + +3344. [func] New "dnssec-checkds" command checks a zone to + determine which DS records should be published + in the parent zone, or which DLV records should be + published in a DLV zone, and queries the DNS to + ensure that it exists. (Note: This tool depends + on python; it will not be built or installed on + systems that do not have a python interpreter.) + [RT #28099] + 3342. [bug] Change #3314 broke saving of stub zones to disk resulting in excessive cpu usage in some cases. [RT #29952] +3341. [func] New "dnssec-verify" command checks a signed zone + to ensure correctness of signatures and of NSEC/NSEC3 + chains. [RT #23673] + +3339. [func] Allow the maximum supported rsa exponent size to be + specified: "max-rsa-exponent-size ;" [RT #29228] + +3338. [bug] Address race condition in units tests: asyncload_zone + and asyncload_zt. [RT #26100] + 3337. [bug] Change #3294 broke support for the multiple keys in controls. [RT #29694] 3335. [func] nslookup: return a nonzero exit code when unable to get an answer. [RT #29492] +3334. [bug] Hold a zone table reference while performing a + asynchronous load of a zone. [RT #28326] + 3333. [bug] Setting resolver-query-timeout too low can cause named to not recover if it loses connectivity. [RT #29623] @@ -504,7 +647,7 @@ 3317. [func] Add ECDSA support (RFC 6605). [RT #21918] - --- 9.8.3 released --- + --- 9.9.1 released --- 3318. [tuning] Reduce the amount of work performed while holding a bucket lock when finished with a fetch context. @@ -536,6 +679,8 @@ 3304. [bug] Use hmctx, not mctx when freeing rbtdb->heaps. [RT #28571] +3303. [bug] named could die when reloading. [RT #28606] + 3302. [bug] dns_dnssec_findmatchingkeys could fail to find keys if the zone name contained character that required special mappings. [RT #28600] @@ -549,22 +694,15 @@ 3299. [bug] Make SDB handle errors from database drivers better. [RT #28534] -3232. [bug] Zero zone->curmaster before return in - dns_zone_setmasterswithkeys(). [RT #26732] - -3183. [bug] Added RTLD_GLOBAL flag to dlopen call. [RT #26301] - -3197. [bug] Don't try to log the filename and line number when - the config parser can't open a file. [RT #22263] - - --- 9.8.2 released --- - 3298. [bug] Named could dereference a NULL pointer in zmgr_start_xfrin_ifquota if the zone was being removed. [RT #28419] 3297. [bug] Named could die on a malformed master file. [RT #28467] +3296. [bug] Named could die with a INSIST failure in + client.c:exit_check. [RT #28346] + 3295. [bug] Adjust isc_time_secondsastimet range check to be more portable. [RT # 26542] @@ -576,6 +714,16 @@ 3290. [bug] was not being installed. [RT #28169] +3273. [bug] AAAA responses could be returned in the additional + section even when filter-aaaa-on-v4 was in use. + [RT #27292] + + --- 9.9.0 released --- + + --- 9.9.0rc4 released --- + +3289. [bug] 'rndc retransfer' failed for inline zones. [RT #28036] + 3288. [bug] dlz_destroy() function wasn't correctly registered by the DLZ dlopen driver. [RT #28056] @@ -584,7 +732,7 @@ 3286. [bug] Managed key maintenance timer could fail to start after 'rndc reconfig'. [RT #26786] - --- 9.8.2rc2 released --- + --- 9.9.0rc3 released --- 3285. [bug] val-frdataset was incorrectly disassociated in proveunsecure after calling startfinddlvsep. @@ -607,24 +755,34 @@ 3280. [bug] Potential double free of a rdataset on out of memory with DNS64. [RT #27762] +3279. [bug] Hold a internal reference to the zone while performing + a asynchronous load. Address potential memory leak + if the asynchronous is cancelled. [RT #27750] + 3278. [bug] Make sure automatic key maintenance is started when "auto-dnssec maintain" is turned on during "rndc reconfig". [RT #26805] +3277. [bug] win32: isc_socket_dup is not implemented. [RT #27696] + 3276. [bug] win32: ns_os_openfile failed to return NULL on safe_open failure. [RT #27696] -3274. [bug] Log when a zone is not reusable. Only set loadtime - on successful loads. [RT #27650] - -3273. [bug] AAAA responses could be returned in the additional - section even when filter-aaaa-on-v4 was in use. - [RT #27292] +3275. [bug] Corrected rndc -h output; the 'rndc sync -clean' + option had been misspelled as '-clear'. (To avoid + future confusion, both options now work.) [RT #27173] 3271. [port] darwin: mksymtbl is not always stable, loop several times before giving up. mksymtbl was using non portable perl to covert 64 bit hex strings. [RT #27653] + --- 9.9.0rc2 released --- + +3270. [bug] "rndc reload" didn't reuse existing zones correctly + when inline-signing was in use. [RT #27650] + +3269. [port] darwin 11 and later now built threaded by default. + 3268. [bug] Convert RRSIG expiry times to 64 timestamps to work out the earliest expiry time. [RT #23311] @@ -636,14 +794,26 @@ DNSKEY RRset was not being properly computed. [RT #26543] +3265. [bug] Corrected a problem with lock ordering in the + inline-signing code. [RT #27557] + +3264. [bug] Automatic regeneration of signatures in an + inline-signing zone could stall when the server + was restarted. [RT #27344] + +3263. [bug] "rndc sync" did not affect the unsigned side of an + inline-signing zone. [RT #27337] + 3262. [bug] Signed responses were handled incorrectly by RPZ. [RT #27316] - --- 9.8.2rc1 released --- +3261. [func] RRset ordering now defaults to random. [RT #27174] 3260. [bug] "rrset-order cyclic" could appear not to rotate for some query patterns. [RT #27170/27185] + --- 9.9.0rc1 released --- + 3259. [bug] named-compilezone: Suppress "dump zone to " message when writing to stdout. [RT #27109] @@ -655,12 +825,21 @@ 3256. [bug] Disable empty zones for lwresd -C. [RT #27139] +3255. [func] No longer require that a empty zones be explicitly + enabled or that a empty zone is disabled for + RFC 1918 empty zones to be configured. [RT #27139] + 3254. [bug] Set isc_socket_ipv6only() on the IPv6 control channels. [RT #22249] 3253. [bug] Return DNS_R_SYNTAX when the input to a text field is too long. [RT #26956] +3252. [bug] When master zones using inline-signing were + updated while the server was offline, the source + zone could fall out of sync with the signed + copy. They can now resynchronize. [RT #26676] + 3251. [bug] Enforce a upper bound (65535 bytes) on the amount of memory dns_sdlz_putrr() can allocate per record to prevent run away memory consumption on ISC_R_NOSPACE. @@ -680,8 +859,34 @@ 3247. [bug] 'raw' format zones failed to preserve load order breaking 'fixed' sort order. [RT #27087] -3243. [port] netbsd,bsdi: the thread defaults were not being - properly set. +3246. [bug] Named failed to start with a empty also-notify list. + [RT #27087] + +3245. [bug] Don't report a error unchanged serials unless there + were other changes when thawing a zone with + ixfr-fromdifferences. [RT #26845] + +3244. [func] Added readline support to nslookup and nsupdate. + Also simplified nsupdate syntax to make "update" + and "prereq" optional. [RT #24659] + +3243. [port] freebsd,netbsd,bsdi: the thread defaults were not + being properly set. + +3242. [func] Extended the header of raw-format master files to + include the serial number of the zone from which + they were generated, if different (as in the case + of inline-signing zones). This is to be used in + inline-signing zones, to track changes between the + unsigned and signed versions of the zone, which may + have different serial numbers. + + (Note: raw zonefiles generated by this version of + BIND are no longer compatible with prior versions. + To generate a backward-compatible raw zonefile + using dnssec-signzone or named-compilezone, specify + output format "raw=0" instead of simply "raw".) + [RT #26587] 3241. [bug] Address race conditions in the resolver code. [RT #26889] @@ -696,10 +901,21 @@ 3237. [bug] dig -6 didn't work with +trace. [RT #26906] - --- 9.8.2b1 released --- +3236. [bug] Backed out changes #3182 and #3202, related to + EDNS(0) fallback behavior. [RT #26416] + +3235. [func] dns_db_diffx, a extended dns_db_diff which returns + the generated diff and optionally writes it to a + journal. [RT #26386] 3234. [bug] 'make depend' produced invalid makefiles. [RT #26830] +3233. [bug] 'rndc freeze/thaw' didn't work for inline zones. + [RT #26632] + +3232. [bug] Zero zone->curmaster before return in + dns_zone_setmasterswithkeys(). [RT #26732] + 3231. [bug] named could fail to send a incompressible zone. [RT #26796] @@ -717,14 +933,29 @@ 3226. [bug] Address minor resource leakages. [RT #26624] +3225. [bug] Silence spurious "setsockopt(517, IPV6_V6ONLY) failed" + messages. [RT #26507] + +3224. [bug] 'rndc signing' argument parsing was broken. [RT #26684] + +3223. [bug] 'task_test privilege_drop' generated false positives. + [RT #26766] + +3222. [cleanup] Replace dns_journal_{get,set}_bitws with + dns_journal_{get,set}_sourceserial. [RT #26634] + 3221. [bug] Fixed a potential core dump on shutdown due to referencing fetch context after it's been freed. [RT #26720] + --- 9.9.0b2 released --- + 3220. [bug] Change #3186 was incomplete; dns_db_rpz_findips() could fail to set the database version correctly, causing an assertion failure. [RT #26180] +3219. [bug] Disable NOEDNS caching following a timeout. + 3218. [security] Cache lookup could return RRSIG data associated with nonexistent records, leading to an assertion failure. [RT #26590] @@ -733,12 +964,24 @@ 3216. [bug] resolver.c:validated() was not thread-safe. [RT #26478] +3215. [bug] 'rndc recursing' could cause a core dump. [RT #26495] + +3214. [func] Add 'named -U' option to set the number of UDP + listener threads per interface. [RT #26485] + 3213. [doc] Clarify ixfr-from-differences behavior. [RT #25188] 3212. [bug] rbtdb.c: failed to remove a node from the deadnodes list prior to adding a reference to it leading a possible assertion failure. [RT #23219] +3211. [func] dnssec-signzone: "-f -" prints to stdout; "-O full" + option prints in single-line-per-record format. + [RT #20287] + +3210. [bug] Canceling the oldest query due to recursive-client + overload could trigger an assertion failure. [RT #26463] + 3209. [func] Add "dnssec-lookaside 'no'". [RT #24858] 3208. [bug] 'dig -y' handle unknown tsig algorithm better. @@ -748,6 +991,11 @@ 3206. [cleanup] Add ISC information to log at start time. [RT #25484] +3205. [func] Upgrade dig's defaults to better reflect modern + nameserver behavior. Enable "dig +adflag" and + "dig +edns=0" by default. Enable "+dnssec" when + running "dig +trace". [RT #23497] + 3204. [bug] When a master server that has been marked as unreachable sends a NOTIFY, mark it reachable again. [RT #25960] @@ -755,12 +1003,24 @@ 3203. [bug] Increase log level to 'info' for validation failures from expired or not-yet-valid RRSIGs. [RT #21796] +3202. [bug] NOEDNS caching on timeout was too aggressive. + [RT #26416] + +3201. [func] 'rndc querylog' can now be given an on/off parameter + instead of only being used as a toggle. [RT #18351] + 3200. [doc] Some rndc functions were undocumented or were missing from 'rndc -h' output. [RT #25555] +3199. [func] When logging client information, include the name + being queried. [RT #25944] + 3198. [doc] Clarified that dnssec-settime can alter keyfile permissions. [RT #24866] +3197. [bug] Don't try to log the filename and line number when + the config parser can't open a file. [RT #22263] + 3196. [bug] nsupdate: return nonzero exit code when target zone doesn't exist. [RT #25783] @@ -789,10 +1049,50 @@ 3187. [port] win32: support for Visual Studio 2008. [RT #26356] + --- 9.9.0b1 released --- + 3186. [bug] Version/db mis-match in rpz code. [RT #26180] +3185. [func] New 'rndc signing' option for auto-dnssec zones: + - 'rndc signing -list' displays the current + state of signing operations + - 'rndc signing -clear' clears the signing state + records for keys that have fully signed the zone + - 'rndc signing -nsec3param' sets the NSEC3 + parameters for the zone + The 'rndc keydone' syntax is removed. [RT #23729] + +3184. [bug] named had excessive cpu usage when a redirect zone was + configured. [RT #26013] + +3183. [bug] Added RTLD_GLOBAL flag to dlopen call. [RT #26301] + +3182. [bug] Auth servers behind firewalls which block packets + greater than 512 bytes may cause other servers to + perform poorly. Now, adb retains edns information + and caches noedns servers. [RT #23392/24964] + +3181. [func] Inline-signing is now supported for master zones. + [RT #26224] + +3180. [func] Local copies of slave zones are now saved in raw + format by default, to improve startup performance. + 'masterfile-format text;' can be used to override + the default, if desired. [RT #25867] + 3179. [port] kfreebsd: build issues. [RT #26273] +3178. [bug] A race condition introduced by change #3163 could + cause an assertion failure on shutdown. [RT #26271] + +3177. [func] 'rndc keydone', remove the indicator record that + named has finished signing the zone with the + corresponding key. [RT #26206] + +3176. [doc] Corrected example code and added a README to the + sample external DLZ module in contrib/dlz/example. + [RT #26215] + 3175. [bug] Fix how DNSSEC positive wildcard responses from a NSEC3 signed zone are validated. Stop sending a unnecessary NSEC3 record when generating such @@ -803,9 +1103,14 @@ 3173. [port] Correctly validate root DS responses. [RT #25726] +3172. [port] darwin 10.* and freebsd [89] are now built threaded by + default. + 3171. [bug] Exclusively lock the task when adding a zone using 'rndc addzone'. [RT #25600] + --- 9.9.0a3 released --- + 3170. [func] RPZ update: - fix precedence among competing rules - improve ARM text including documenting rule precedence @@ -820,10 +1125,28 @@ 3169. [func] Catch db/version mis-matches when calling dns_db_*(). [RT #26017] +3168. [bug] Nxdomain redirection could trigger an assert with + a ANY query. [RT #26017] + 3167. [bug] Negative answers from forwarders were not being correctly tagged making them appear to not be cached. [RT #25380] +3166. [bug] Upgrading a zone to support inline-signing failed. + [RT #26014] + +3165. [bug] dnssec-signzone could generate new signatures when + resigning, even when valid signatures were already + present. [RT #26025] + +3164. [func] Enable DLZ modules to retrieve client information, + so that responses can be changed depending on the + source address of the query. [RT #25768] + +3163. [bug] Use finer-grained locking in client.c to address + concurrency problems with large numbers of threads. + [RT #26044] + 3162. [test] start.pl: modified to allow for "named.args" in ns*/ subdirectory to override stock arguments to named. Largely from RT#26044, but no separate ticket. @@ -831,24 +1154,52 @@ 3161. [bug] zone.c:del_sigs failed to always reset rdata leading assertion failures. [RT #25880] +3160. [bug] When printing out a NSEC3 record in multiline form + the newline was not being printed causing type codes + to be run together. [RT #25873] + +3159. [bug] On some platforms, named could assert on startup + when running in a chrooted environment without + /proc. [RT #25863] + +3158. [bug] Recursive servers would prefer a particular UDP + socket instead of using all available sockets. + [RT #26038] + 3157. [tuning] Reduce the time spent in "rndc reconfig" by parsing the config file before pausing the server. [RT #21373] +3156. [placeholder] + + --- 9.9.0a2 released --- + 3155. [bug] Fixed a build failure when using contrib DLZ drivers (e.g., mysql, postgresql, etc). [RT #25710] 3154. [bug] Attempting to print an empty rdataset could trigger an assert. [RT #25452] +3153. [func] Extend request-ixfr to zone level and remove the + side effect of forcing an AXFR. [RT #25156] + 3152. [cleanup] Some versions of gcc and clang failed due to incorrect use of __builtin_expect. [RT #25183] 3151. [bug] Queries for type RRSIG or SIG could be handled incorrectly. [RT #21050] +3150. [func] Improved startup and reconfiguration time by + enabling zones to load in multiple threads. [RT #25333] + +3149. [placeholder] + 3148. [bug] Processing of normal queries could be stalled when forwarding a UPDATE message. [RT #24711] +3147. [func] Initial inline signing support. [RT #23657] + + --- 9.9.0a1 released --- + 3146. [test] Fixed gcc4.6.0 errors in ATF. [RT #25598] 3145. [test] Capture output of ATF unit tests in "./atf.out" if @@ -859,29 +1210,31 @@ 3143. [bug] Silence clang compiler warnings. [RT #25174] -3139. [test] Added tests from RFC 6234, RFC 2202, and RFC 1321 - for the hashing algorithms (md5, sha1 - sha512, and - their hmac counterparts). [RT #25067] - - --- 9.8.1 released --- - - --- 9.8.1rc1 released --- +3142. [bug] NAPTR is class agnostic. [RT #25429] 3141. [bug] Silence spurious "zone serial (0) unchanged" messages associated with empty zones. [RT #25079] +3140. [func] New command "rndc flushtree " clears the + specified name from the server cache along with + all names under it. [RT #19970] + +3139. [test] Added tests from RFC 6234, RFC 2202, and RFC 1321 + for the hashing algorithms (md5, sha1 - sha512, and + their hmac counterparts). [RT #25067] + 3138. [bug] Address memory leaks and out-of-order operations when shutting named down. [RT #25210] +3137. [func] Improve hardware scalability by allowing multiple + worker threads to process incoming UDP packets. + This can significantly increase query throughput + on some systems. [RT #22992] + 3136. [func] Add RFC 1918 reverse zones to the list of built-in empty zones switched on by the 'empty-zones-enable' option. [RT #24990] - Note: empty-zones-enable must be "yes;" or a empty - zone needs to be disabled in named.conf for RFC 1918 - zones to be activated. This requirement may be - removed in future releases. - 3135. [port] FreeBSD: workaround broken IPV6_USE_MIN_MTU processing. See http://www.freebsd.org/cgi/query-pr.cgi?pr=158307 [RT #24950] @@ -889,19 +1242,34 @@ 3134. [bug] Improve the accuracy of dnssec-signzone's signing statistics. [RT #16030] - --- 9.8.1b3 released --- - 3133. [bug] Change #3114 was incomplete. [RT #24577] +3132. [placeholder] + 3131. [tuning] Improve scalability by allocating one zone task per 100 zones at startup time, rather than using a fixed-size task table. [RT #24406] +3130. [func] Support alternate methods for managing a dynamic + zone's serial number. Two methods are currently + defined using serial-update-method, "increment" + (default) and "unixtime". [RT #23849] + 3129. [bug] Named could crash on 'rndc reconfig' when allow-new-zones was set to yes and named ACLs were used. [RT #22739] - --- 9.8.1b2 released --- +3128. [func] Inserting an NSEC3PARAM via dynamic update in an + auto-dnssec zone that has not been signed yet + will cause it to be signed with the specified NSEC3 + parameters when keys are activated. The + NSEC3PARAM record will not appear in the zone until + it is signed, but the parameters will be stored. + [RT #23684] + +3127. [bug] 'rndc thaw' will now remove a zone's journal file + if the zone serial number has been changed and + ixfr-from-differences is not in use. [RT #24687] 3126. [security] Using DNAME record to generate replacements caused RPZ to exit with a assertion failure. [RT #24766] @@ -941,6 +1309,12 @@ never-implemented 'auto-dnssec create' option. [RT #24533] +3116. [func] New 'dnssec-update-mode' option controls updates + of DNSSEC records in signed dynamic zones. Set to + 'no-resign' to disable automatic RRSIG regeneration + while retaining the ability to sign new or changed + data. [RT #24533] + 3115. [bug] Named could fail to return requested data when following a CNAME that points into the same zone. [RT #24455] @@ -951,8 +1325,6 @@ 3113. [doc] Document the relationship between serial-query-rate and NOTIFY messages. - --- 9.8.1b1 released --- - 3112. [doc] Add missing descriptions of the update policy name types "ms-self", "ms-subdomain", "krb5-self" and "krb5-subdomain", which allow machines to update @@ -965,9 +1337,23 @@ 3110. [bug] dnssec-signzone: Wrong error message could appear when attempting to sign with no KSK. [RT #24369] +3109. [func] The also-notify option now uses the same syntax + as a zone's masters clause. This means it is + now possible to specify a TSIG key to use when + sending notifies to a given server, or to include + an explicit named masters list in an also-notfiy + statement. [RT #23508] + +3108. [cleanup] dnssec-signzone: Clarified some error and + warning messages; removed #ifdef ALLOW_KSKLESS_ZONES + code (use -P instead). [RT #20852] + 3107. [bug] dnssec-signzone: Report the correct number of ZSKs when using -x. [RT #20852] +3106. [func] When logging client requests, include the name of + the TSIG key if any. [RT #23619] + 3105. [bug] GOST support can be suppressed by "configure --without-gost" [RT #24367] @@ -977,6 +1363,12 @@ instead of in the options statement could trigger an assertion failure in named-checkconf. [RT #24382] +3102. [func] New 'dnssec-loadkeys-interval' option configures + how often, in minutes, to check the key repository + for updates when using automatic key maintenance. + Default is every 60 minutes (formerly hard-coded + to 12 hours). [RT #23744] + 3101. [bug] Zones using automatic key maintenance could fail to check the key repository for updates. [RT #23744] @@ -1012,6 +1404,9 @@ 3090. [func] Make --with-gssapi default [RT #23738] +3089. [func] dnssec-dsfromkey now supports reading keys from + standard input "dnssec-dsfromkey -f -". [RT# 20662] + 3088. [bug] Remove bin/tests/system/logfileconfig/ns1/named.conf and add setup.sh in order to resolve changing named.conf issue. [RT #23687] @@ -1024,6 +1419,17 @@ other change has been specified, using "-P now -A now" as default values. [RT #22474] +3085. [func] New '-R' option in dnssec-signzone forces removal + of signatures which have not yet expired but + were generated by a key that no longer exists. + [RT #22471] + +3084. [func] A new command "rndc sync" dumps pending changes in + a dynamic zone to disk; "rndc sync -clean" also + removes the journal file after syncing. Also, + "rndc freeze" no longer removes journal files. + [RT #22473] + 3083. [bug] NOTIFY messages were not being sent when generating a NSEC3 chain incrementally. [RT #23702] @@ -1044,6 +1450,11 @@ 3077. [bug] zone.c:zone_refreshkeys() incorrectly called dns_zone_attach(), use zone->irefs instead. [RT #23303] +3076. [func] New '-L' option in dnssec-keygen, dnsset-settime, and + dnssec-keyfromlabel sets the default TTL of the + key. When possible, automatic signing will use that + TTL when the key is published. [RT #23304] + 3075. [bug] dns_dnssec_findzonekeys{2} used a inconsistent timestamp when determining which keys are active. [RT #23642] @@ -1076,7 +1487,7 @@ 3066. [func] The DLZ "dlopen" driver is now built by default, no longer requiring a configure option. To disable it, use "configure --without-dlopen". - (Note: driver not supported on win32.) [RT #23467] + Driver also supported on win32. [RT #23467] 3065. [bug] RRSIG could have time stamps too far in the future. [RT #23356] @@ -1086,6 +1497,25 @@ 3063. [contrib] More verbose error reporting from DLZ LDAP. [RT #23402] +3062. [func] Made several changes to enhance human readability + of DNSSEC data in dig output and in generated + zone files: + - DNSKEY record comments are more verbose, no + longer used in multiline mode only + - multiline RRSIG records reformatted + - multiline output mode for NSEC3PARAM records + - "dig +norrcomments" suppresses DNSKEY comments + - "dig +split=X" breaks hex/base64 records into + fields of width X; "dig +nosplit" disables this. + [RT #22820] + +3061. [func] New option "dnssec-signzone -D", only write out + generated DNSSEC records. [RT #22896] + +3060. [func] New option "dnssec-signzone -X " allows + specification of a separate expiration date + for DNSKEY RRSIGs and other RRSIGs. [RT #22141] + 3059. [test] Added a regression test for change #3023. 3058. [bug] Cause named to terminate at startup or rndc reconfig/ @@ -1095,6 +1525,10 @@ 3057. [bug] "rndc secroots" would abort after the first error and so could miss some views. [RT #23488] +3056. [func] Added support for URI resource record. [RT #23386] + +3055. [placeholder] + 3054. [bug] Added elliptic curve support check in GOST OpenSSL engine detection. [RT #23485] @@ -1123,6 +1557,8 @@ 3046. [bug] Use RRSIG original TTL to compute validated RRset and RRSIG TTL. [RT #23332] +3045. [removed] Replaced by change #3050. + 3044. [bug] Hold the socket manager lock while freeing the socket. [RT #23333] @@ -1143,6 +1579,8 @@ with a CNAME existed between the trust anchor and the top of the zone. [RT #23338] +3039. [func] Redirect on NXDOMAIN support. [RT #23146] + 3038. [bug] Install . [RT #23342] 3037. [doc] Update COPYRIGHT to contain all the individual @@ -1180,8 +1618,6 @@ after calling grow_headerspace() and if not re-call grow_headerspace() until we do. [RT #22521] - --- 9.8.0 released --- - 3025. [bug] Fixed a possible deadlock due to zone resigning. [RT #22964] @@ -1203,8 +1639,6 @@ 3019. [test] Test: check apex NSEC3 records after adding DNSKEY record via UPDATE. [RT #23229] - --- 9.8.0rc1 released --- - 3018. [bug] Named failed to check for the "none;" acl when deciding if a zone may need to be re-signed. [RT #23120] @@ -1216,6 +1650,8 @@ 3015. [port] win32: fix IN6_IS_ADDR_LINKLOCAL and IN6_IS_ADDR_SITELOCAL macros. [RT #22724] +3014. [placeholder] + 3013. [bug] The DNS64 ttl was not always being set as expected. [RT #23034] @@ -1223,7 +1659,8 @@ signing records for any remaining DNSKEY changes. [RT #22590] -3011. [func] Allow setting this in named.conf using the new +3011. [func] Change the default query timeout from 30 seconds + to 10. Allow setting this in named.conf using the new 'resolver-query-timeout' option, which specifies a max time in seconds. 0 means 'default' and anything longer than 30 will be silently set to 30. [RT #22852] diff --git a/contrib/bind9/COPYRIGHT b/contrib/bind9/COPYRIGHT index cc19db471b69..525c2228db33 100644 --- a/contrib/bind9/COPYRIGHT +++ b/contrib/bind9/COPYRIGHT @@ -13,7 +13,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -$Id: COPYRIGHT,v 1.17.14.2 2012/01/04 23:46:18 tbox Exp $ +$Id: COPYRIGHT,v 1.19 2012/01/03 23:46:59 tbox Exp $ Portions of this code release fall under one or more of the following Copyright notices. Please see individual source diff --git a/contrib/bind9/HISTORY b/contrib/bind9/HISTORY index e98f9b41460d..9a3b7599965b 100644 --- a/contrib/bind9/HISTORY +++ b/contrib/bind9/HISTORY @@ -1,5 +1,57 @@ Summary of functional enhancements from prior major releases of BIND 9: +BIND 9.8.0 + + BIND 9.8.0 includes a number of changes from BIND 9.7 and earlier + releases. New features include: + + - Built-in trust anchor for the root zone, which can be + switched on via "dnssec-validation auto;" + - Support for DNS64. + - Support for response policy zones (RPZ). + - Support for writable DLZ zones. + - Improved ease of configuration of GSS/TSIG for + interoperability with Active Directory + - Support for GOST signing algorithm for DNSSEC. + - Removed RTT Banding from server selection algorithm. + - New "static-stub" zone type. + - Allow configuration of resolver timeouts via + "resolver-query-timeout" option. + - The DLZ "dlopen" driver is now built by default. + - Added a new include file with function typedefs + for the DLZ "dlopen" driver. + - Made "--with-gssapi" default. + - More verbose error reporting from DLZ LDAP. + +BIND 9.7.0 + + BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier + releases. Most are intended to simplify DNSSEC configuration. + + New features include: + + - Fully automatic signing of zones by "named". + - Simplified configuration of DNSSEC Lookaside Validation (DLV). + - Simplified configuration of Dynamic DNS, using the "ddns-confgen" + command line tool or the "local" update-policy option. (As a side + effect, this also makes it easier to configure automatic zone + re-signing.) + - New named option "attach-cache" that allows multiple views to + share a single cache. + - DNS rebinding attack prevention. + - New default values for dnssec-keygen parameters. + - Support for RFC 5011 automated trust anchor maintenance + - Smart signing: simplified tools for zone signing and key + maintenance. + - The "statistics-channels" option is now available on Windows. + - A new DNSSEC-aware libdns API for use by non-BIND9 applications + - On some platforms, named and other binaries can now print out + a stack backtrace on assertion failure, to aid in debugging. + - A "tools only" installation mode on Windows, which only installs + dig, host, nslookup and nsupdate. + - Improved PKCS#11 support, including Keyper support and explicit + OpenSSL engine selection. + BIND 9.6.0 Full NSEC3 support diff --git a/contrib/bind9/Makefile.in b/contrib/bind9/Makefile.in index 4e41fe509743..7c1d66523fa5 100644 --- a/contrib/bind9/Makefile.in +++ b/contrib/bind9/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.58.250.4 2011/09/06 04:06:11 marka Exp $ +# $Id: Makefile.in,v 1.62 2011/09/06 04:06:37 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/contrib/bind9/README b/contrib/bind9/README index 9d839b49fce8..88d799e4f7cf 100644 --- a/contrib/bind9/README +++ b/contrib/bind9/README @@ -51,119 +51,64 @@ BIND 9 For up-to-date release notes and errata, see http://www.isc.org/software/bind9/releasenotes -BIND 9.8.5 +BIND 9.9.3 - BIND 9.8.5 includes several bug fixes and patches security - flaws described in CVE-2012-5688, CVE-2012-5689 and CVE-2013-2266. + BIND 9.9.3 is a maintenance release and patches the security + flaws described in CVE-2012-5688, CVE-2012-5689 and CVE-2013-2266. -BIND 9.8.4 +BIND 9.9.2 - BIND 9.8.4 includes several bug fixes and patches security - flaws described in CVE-2012-1667, CVE-2012-3817 and CVE-2012-4244. + BIND 9.9.2 is a maintenance release and patches the security + flaw described in CVE-2012-4244. -BIND 9.8.3 +BIND 9.9.1 - BIND 9.8.3 is a maintenance release. + BIND 9.9.1 is a maintenance release. -BIND 9.8.2 +BIND 9.9.0 - BIND 9.8.2 includes a number of bug fixes and prevents a security - problem described in CVE-2011-4313 + BIND 9.9.0 includes a number of changes from BIND 9.8 and earlier + releases. New features include: -BIND 9.8.1 - - BIND 9.8.1 includes a number of bug fixes and enhancements from - BIND 9.8 and earlier releases. New features include: - - - The DLZ "dlopen" driver is now built by default. - - Added a new include file with function typedefs - for the DLZ "dlopen" driver. - - Made "--with-gssapi" default. - - More verbose error reporting from DLZ LDAP. - -BIND 9.8.0 - - BIND 9.8.0 includes a number of changes from BIND 9.7 and earlier - releases. New features include: - - - Built-in trust anchor for the root zone, which can be - switched on via "dnssec-validation auto;" - - Support for DNS64. - - Support for response policy zones (RPZ). - - Support for writable DLZ zones. - - Improved ease of configuration of GSS/TSIG for - interoperability with Active Directory - - Support for GOST signing algorithm for DNSSEC. - - Removed RTT Banding from server selection algorithm. - - New "static-stub" zone type. - - Allow configuration of resolver timeouts via - "resolver-query-timeout" option. - -BIND 9.7.0 - - BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier - releases. Most are intended to simplify DNSSEC configuration. - - New features include: - - - Fully automatic signing of zones by "named". - - Simplified configuration of DNSSEC Lookaside Validation (DLV). - - Simplified configuration of Dynamic DNS, using the "ddns-confgen" - command line tool or the "local" update-policy option. (As a side - effect, this also makes it easier to configure automatic zone - re-signing.) - - New named option "attach-cache" that allows multiple views to - share a single cache. - - DNS rebinding attack prevention. - - New default values for dnssec-keygen parameters. - - Support for RFC 5011 automated trust anchor maintenance - - Smart signing: simplified tools for zone signing and key - maintenance. - - The "statistics-channels" option is now available on Windows. - - A new DNSSEC-aware libdns API for use by non-BIND9 applications - - On some platforms, named and other binaries can now print out - a stack backtrace on assertion failure, to aid in debugging. - - A "tools only" installation mode on Windows, which only installs - dig, host, nslookup and nsupdate. - - Improved PKCS#11 support, including Keyper support and explicit - OpenSSL engine selection. - - Known issues in this release: - - - In rare cases, DNSSEC validation can leak memory. When this - happens, it will cause an assertion failure when named exits, - but is otherwise harmless. A fix exists, but was too late for - this release; it will be included in BIND 9.7.1. - - Compatibility notes: - - - If you had built BIND 9.6 with any of ALLOW_NSEC3PARAM_UPDATE, - ALLOW_SECURE_TO_INSECURE or ALLOW_INSECURE_TO_SECURE defined, then - you should ensure that all changes that are in progress have - completed prior to upgrading to BIND 9.7. BIND 9.7 implements - those features in a way which is not backwards compatible. - - - Prior releases had a bug which caused HMAC-SHA* keys with long - secrets to be used incorrectly. Fixing this bug means that older - versions of BIND 9 may fail to interoperate with this version - when using TSIG keys. If this occurs, the new "isc-hmac-fixup" - tool will convert a key with a long secret into a form that works - correctly with all versions of BIND 9. See the "isc-hmac-fixup" - man page for additional details. - - - Revoking a DNSSEC key with "dnssec-revoke" changes its key ID. - It is possible for the new key ID to collide with that of a - different key. Newly generated keys will not have this problem, - as "dnssec-keygen" looks for potential collisions before - generating keys, but exercise caution if using key revokation - with keys that were generated by older versions of BIND 9. See - the Administrator's Reference Manual, section 4.10 ("Dynamic - Trust Anchor Management") for more details. - - - A bug was fixed in which a key's scheduled inactivity date was - stored incorectly. Users who participated in the 9.7.0 BETA test - and had DNSSEC keys with scheduled inactivity dates will need to - reset those keys' dates using "dnssec-settime -I". + - Inline signing, allowing automatic DNSSEC signing of + master zones without modification of the zonefile, or + "bump in the wire" signing in slaves. + - NXDOMAIN redirection. + - New 'rndc flushtree' command clears all data under a given + name from the DNS cache. + - New 'rndc sync' command dumps pending changes in a dynamic + zone to disk without a freeze/thaw cycle. + - New 'rndc signing' command displays or clears signing status + records in 'auto-dnssec' zones. + - NSEC3 parameters for 'auto-dnssec' zones can now be set prior + to signing, eliminating the need to initially sign with NSEC. + - Startup time improvements on large authoritative servers. + - Slave zones are now saved in raw format by default. + - Several improvements to response policy zones (RPZ). + - Improved hardware scalability by using multiple threads + to listen for queries and using finer-grained client locking + - The 'also-notify' option now takes the same syntax as + 'masters', so it can used named masterlists and TSIG keys. + - 'dnssec-signzone -D' writes an output file containing only DNSSEC + data, which can be included by the primary zone file. + - 'dnssec-signzone -R' forces removal of signatures that are + not expired but were created by a key which no longer exists. + - 'dnssec-signzone -X' allows a separate expiration date to + be specified for DNSKEY signatures from other signatures. + - New '-L' option to dnssec-keygen, dnssec-settime, and + dnssec-keyfromlabel sets the default TTL for the key. + - dnssec-dsfromkey now supports reading from standard input, + to make it easier to convert DNSKEY to DS. + - RFC 1918 reverse zones have been added to the empty-zones + table per RFC 6303. + - Dynamic updates can now optionally set the zone's SOA serial + number to the current UNIX time. + - DLZ modules can now retrieve the source IP address of + the querying client. + - 'request-ixfr' option can now be set at the per-zone level. + - 'dig +rrcomments' turns on comments about DNSKEY records, + indicating their key ID, algorithm and function + - Simplified nsupdate syntax and added readline support Building @@ -193,12 +138,12 @@ Building AIX 4.3, 5L CentOS 4, 4.5, 5 Darwin 9.0.0d1/ARM - Debian 4 - Fedora Core 5, 7 - FreeBSD 6.1 + Debian 4, 5, 6 + Fedora Core 5, 7, 8 + FreeBSD 6, 7, 8 HP-UX 11.23 PA - MacOS X 10.4, 10.5 - Red Hat Enterprise Linux 4, 5 + MacOS X 10.5, 10.6, 10.7 + Red Hat Enterprise Linux 4, 5, 6 SCO OpenServer 5.0.6 Slackware 9, 10 SuSE 9, 10 @@ -219,7 +164,8 @@ Building CFLAGS C compiler flags. Defaults to include -g and/or -O2 - as supported by the compiler. + as supported by the compiler. Please include '-g' + if you need to set CFLAGS. STD_CINCLUDES System header file directories. Can be used to specify @@ -336,6 +282,10 @@ Building libraries. sh-utils-1.16 provides a "printf" which compiles on SunOS 4. +Known limitations + + Linux requires kernel build 2.6.39 or later to get the + performance benefits from using multiple sockets. Documentation diff --git a/contrib/bind9/bin/Makefile.in b/contrib/bind9/bin/Makefile.in index 897c0f37ebb7..87ca5b270562 100644 --- a/contrib/bind9/bin/Makefile.in +++ b/contrib/bind9/bin/Makefile.in @@ -20,7 +20,7 @@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ SUBDIRS = named rndc dig dnssec tools tests nsupdate \ - check confgen @PKCS11_TOOLS@ + check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@ TARGETS = @BIND9_MAKE_RULES@ diff --git a/contrib/bind9/bin/check/check-tool.c b/contrib/bind9/bin/check/check-tool.c index 46cf2bf48a53..1e534071d0c8 100644 --- a/contrib/bind9/bin/check/check-tool.c +++ b/contrib/bind9/bin/check/check-tool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.c,v 1.41 2010/09/07 23:46:59 tbox Exp $ */ +/* $Id: check-tool.c,v 1.44 2011/12/22 07:32:39 each Exp $ */ /*! \file */ @@ -638,7 +638,8 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, /*% dump the zone */ isc_result_t dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, - dns_masterformat_t fileformat, const dns_master_style_t *style) + dns_masterformat_t fileformat, const dns_master_style_t *style, + const isc_uint32_t rawversion) { isc_result_t result; FILE *output = stdout; @@ -664,8 +665,8 @@ dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, } } - result = dns_zone_dumptostream2(zone, output, fileformat, style); - + result = dns_zone_dumptostream3(zone, output, fileformat, style, + rawversion); if (output != stdout) (void)isc_stdio_close(output); diff --git a/contrib/bind9/bin/check/check-tool.h b/contrib/bind9/bin/check/check-tool.h index e988597a740d..0794729ee05f 100644 --- a/contrib/bind9/bin/check/check-tool.h +++ b/contrib/bind9/bin/check/check-tool.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.h,v 1.16 2010/09/07 23:46:59 tbox Exp $ */ +/* $Id: check-tool.h,v 1.18 2011/12/09 23:47:02 tbox Exp $ */ #ifndef CHECK_TOOL_H #define CHECK_TOOL_H @@ -41,7 +41,8 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, isc_result_t dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, - dns_masterformat_t fileformat, const dns_master_style_t *style); + dns_masterformat_t fileformat, const dns_master_style_t *style, + const isc_uint32_t rawversion); #ifdef _WIN32 void InitSockets(void); diff --git a/contrib/bind9/bin/check/named-checkconf.c b/contrib/bind9/bin/check/named-checkconf.c index ef754ff29af9..0b3c508f28c4 100644 --- a/contrib/bind9/bin/check/named-checkconf.c +++ b/contrib/bind9/bin/check/named-checkconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkconf.c,v 1.54.62.2 2011/03/12 04:59:13 tbox Exp $ */ +/* $Id: named-checkconf.c,v 1.56 2011/03/12 04:59:46 tbox Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/check/named-checkzone.8 b/contrib/bind9/bin/check/named-checkzone.8 index b7b8a4c54672..8538ca886c2a 100644 --- a/contrib/bind9/bin/check/named-checkzone.8 +++ b/contrib/bind9/bin/check/named-checkzone.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2007, 2009, 2010, 2013 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2007, 2009-2011, 2013 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2002 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -33,9 +33,9 @@ named\-checkzone, named\-compilezone \- zone file validity checking or converting tool .SH "SYNOPSIS" .HP 16 -\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} +\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} .HP 18 -\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} +\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-T\ \fR\fB\fImode\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} .SH "DESCRIPTION" .PP \fBnamed\-checkzone\fR @@ -139,11 +139,19 @@ Specify the format of the zone file. Possible formats are .PP \-F \fIformat\fR .RS 4 -Specify the format of the output file specified. Possible formats are +Specify the format of the output file specified. For +\fBnamed\-checkzone\fR, this does not cause any effects unless it dumps the zone contents. +.sp +Possible formats are \fB"text"\fR (default) and -\fB"raw"\fR. For -\fBnamed\-checkzone\fR, this does not cause any effects unless it dumps the zone contents. +\fB"raw"\fR +or +\fB"raw=N"\fR, which store the zone in a binary format for rapid loading by +\fBnamed\fR. +\fB"raw=N"\fR +specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of +\fBnamed\fR; if N is 1, the file can be read by release 9.9.0 or higher. The default is 1. .RE .PP \-k \fImode\fR @@ -160,6 +168,11 @@ checks with the specified failure mode. Possible modes are \fB"ignore"\fR. .RE .PP +\-L \fIserial\fR +.RS 4 +When compiling a zone to 'raw' format, set the "source serial" value in the header to the specified serial number. (This is expected to be used primarily for testing purposes.) +.RE +.PP \-m \fImode\fR .RS 4 Specify whether MX records should be checked to see if they are addresses. Possible modes are @@ -289,7 +302,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004\-2007, 2009, 2010, 2013 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2007, 2009\-2011, 2013 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2002 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/check/named-checkzone.c b/contrib/bind9/bin/check/named-checkzone.c index fdc3ddc2caab..7e779c2d17f8 100644 --- a/contrib/bind9/bin/check/named-checkzone.c +++ b/contrib/bind9/bin/check/named-checkzone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkzone.c,v 1.61.62.2 2011/12/22 23:45:54 tbox Exp $ */ +/* $Id: named-checkzone.c,v 1.65 2011/12/22 17:29:22 each Exp $ */ /*! \file */ @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -112,8 +113,12 @@ main(int argc, char **argv) { const char *outputformatstr = NULL; dns_masterformat_t inputformat = dns_masterformat_text; dns_masterformat_t outputformat = dns_masterformat_text; + dns_masterrawheader_t header; + isc_uint32_t rawversion = 1, serialnum = 0; + isc_boolean_t snset = ISC_FALSE; isc_boolean_t logdump = ISC_FALSE; FILE *errout = stdout; + char *endp; outputstyle = &dns_master_style_full; @@ -159,7 +164,7 @@ main(int argc, char **argv) { isc_commandline_errprint = ISC_FALSE; while ((c = isc_commandline_parse(argc, argv, - "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:T:W:")) + "c:df:hi:jk:L:m:n:qr:s:t:o:vw:DF:M:S:T:W:")) != EOF) { switch (c) { case 'c': @@ -237,6 +242,17 @@ main(int argc, char **argv) { } break; + case 'L': + snset = ISC_TRUE; + endp = NULL; + serialnum = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fprintf(stderr, "source serial number " + "must be numeric"); + exit(1); + } + break; + case 'n': if (ARGCMP("ignore")) { zone_options &= ~(DNS_ZONEOPT_CHECKNS| @@ -413,7 +429,11 @@ main(int argc, char **argv) { inputformat = dns_masterformat_text; else if (strcasecmp(inputformatstr, "raw") == 0) inputformat = dns_masterformat_raw; - else { + else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { + inputformat = dns_masterformat_raw; + fprintf(stderr, + "WARNING: input format raw, version ignored\n"); + } else { fprintf(stderr, "unknown file format: %s\n", inputformatstr); exit(1); @@ -421,11 +441,22 @@ main(int argc, char **argv) { } if (outputformatstr != NULL) { - if (strcasecmp(outputformatstr, "text") == 0) + if (strcasecmp(outputformatstr, "text") == 0) { outputformat = dns_masterformat_text; - else if (strcasecmp(outputformatstr, "raw") == 0) + } else if (strcasecmp(outputformatstr, "raw") == 0) { outputformat = dns_masterformat_raw; - else { + } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { + char *end; + + outputformat = dns_masterformat_raw; + rawversion = strtol(outputformatstr + 4, &end, 10); + if (end == outputformatstr + 4 || *end != '\0' || + rawversion > 1U) { + fprintf(stderr, + "unknown raw format version\n"); + exit(1); + } + } else { fprintf(stderr, "unknown file format: %s\n", outputformatstr); exit(1); @@ -480,13 +511,20 @@ main(int argc, char **argv) { result = load_zone(mctx, origin, filename, inputformat, classname, &zone); + if (snset) { + dns_master_initrawheader(&header); + header.flags = DNS_MASTERRAW_SOURCESERIALSET; + header.sourceserial = serialnum; + dns_zone_setrawdata(zone, &header); + } + if (result == ISC_R_SUCCESS && dumpzone) { if (logdump) { fprintf(errout, "dump zone to %s...", output_filename); fflush(errout); } result = dump_zone(origin, zone, output_filename, - outputformat, outputstyle); + outputformat, outputstyle, rawversion); if (logdump) fprintf(errout, "done\n"); } diff --git a/contrib/bind9/bin/check/named-checkzone.docbook b/contrib/bind9/bin/check/named-checkzone.docbook index c25dd1eaf2e2..ea37fa2b57f9 100644 --- a/contrib/bind9/bin/check/named-checkzone.docbook +++ b/contrib/bind9/bin/check/named-checkzone.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + June 13, 2000 @@ -38,6 +38,7 @@ 2007 2009 2010 + 2011 2013 Internet Systems Consortium, Inc. ("ISC") @@ -71,6 +72,7 @@ + @@ -97,6 +99,7 @@ + @@ -250,12 +253,20 @@ Specify the format of the output file specified. - Possible formats are "text" (default) - and "raw". For named-checkzone, this does not cause any effects unless it dumps the zone contents. + + Possible formats are "text" (default) + and "raw" or "raw=N", + which store the zone in a binary format for rapid loading + by named. "raw=N" + specifies the format version of the raw zone file: if N + is 0, the raw file can be read by any version of + named; if N is 1, the file can be read + by release 9.9.0 or higher. The default is 1. + @@ -274,6 +285,17 @@ + + -L serial + + + When compiling a zone to 'raw' format, set the "source serial" + value in the header to the specified serial number. (This is + expected to be used primarily for testing purposes.) + + + + -m mode diff --git a/contrib/bind9/bin/check/named-checkzone.html b/contrib/bind9/bin/check/named-checkzone.html index ab9c8efc50da..6941326996cc 100644 --- a/contrib/bind9/bin/check/named-checkzone.html +++ b/contrib/bind9/bin/check/named-checkzone.html @@ -1,5 +1,5 @@ - + @@ -45,6 +45,7 @@ 2008 2009 2010 + 2011 2013 Internet Systems Consortium, Inc. ("ISC") @@ -467,7 +468,8 @@ policy of the server. AD=1 indicates that all records have been validated as secure and the answer is not from a OPT-OUT range. AD=0 indicate that some part - of the answer was insecure or not validated. + of the answer was insecure or not validated. This + bit is set by default. @@ -504,19 +506,17 @@ - - - Toggle the setting of the RD (recursion desired) bit in the - query. - This bit is set by default, which means dig - normally sends recursive queries. Recursion is automatically - disabled - when the +nssearch or - +trace query options are - used. - - - + + + Toggle the setting of the RD (recursion desired) bit + in the query. This bit is set by default, which means + dig normally sends recursive + queries. Recursion is automatically disabled when + the +nssearch or + +trace query options are used. + + + @@ -536,20 +536,21 @@ - - Toggle tracing of the delegation path from the root name servers - for - the name being looked up. Tracing is disabled by default. When - tracing is enabled, dig makes - iterative queries to - resolve the name being looked up. It will follow referrals from - the - root servers, showing the answer from each server that was used - to - resolve the lookup. - - - + + Toggle tracing of the delegation path from the root + name servers for the name being looked up. Tracing + is disabled by default. When tracing is enabled, + dig makes iterative queries to + resolve the name being looked up. It will follow + referrals from the root servers, showing the answer + from each server that was used to resolve the lookup. + + + +dnssec is also set when +trace is + set to better emulate the default queries from a nameserver. + + + @@ -594,8 +595,35 @@ Toggle the display of comment lines in the output. The default - is to - print comments. + is to print comments. + + + + + + + + + Toggle the display of per-record comments in the output (for + example, human-readable key information about DNSKEY records). + The default is not to print record comments unless multiline + mode is active. + + + + + + + + + Split long hex- or base64-formatted fields in resource + records into chunks of W characters + (where W is rounded up to the nearest + multiple of 4). + +nosplit or + +split=0 causes fields not to be + split at all. The default is 56 characters, or 44 characters + when multiline mode is active. @@ -755,9 +783,10 @@ Specify the EDNS version to query with. Valid values - are 0 to 255. Setting the EDNS version will cause a - EDNS query to be sent. clears the - remembered EDNS version. + are 0 to 255. Setting the EDNS version will cause + a EDNS query to be sent. + clears the remembered EDNS version. EDNS is set to + 0 by default. diff --git a/contrib/bind9/bin/dig/dig.html b/contrib/bind9/bin/dig/dig.html index a1cd5cf52daf..768582e37bb1 100644 --- a/contrib/bind9/bin/dig/dig.html +++ b/contrib/bind9/bin/dig/dig.html @@ -1,5 +1,5 @@ - + August 26, 2009 @@ -39,6 +39,7 @@ 2008 2009 2010 + 2011 2012 Internet Systems Consortium, Inc. ("ISC") @@ -52,6 +53,7 @@ + keyfile @@ -64,6 +66,7 @@ + @@ -114,6 +117,15 @@ + + -T TTL + + + Specifies the TTL of the DS records. + + + + -K directory @@ -134,6 +146,15 @@ from . If the zone name is the same as , then it may be omitted. + + If is set to "-", then + the zone data is read from the standard input. This makes it + possible to use the output of the dig + command as input, as in: + + + dig dnskey example.com | dnssec-dsfromkey -f - example.com + diff --git a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html index 24bc0c133896..50d4d7802bd4 100644 --- a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html +++ b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html @@ -1,5 +1,5 @@ - + February 8, 2008 @@ -60,6 +60,7 @@ + @@ -236,6 +237,20 @@ + + -L ttl + + + Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. + + + + -p protocol diff --git a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html index 0fa3affa277b..f0e2c5c3b86e 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html +++ b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html @@ -28,10 +28,10 @@

Synopsis

-

dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-k] [-K directory] [-n nametype] [-P date/offset] [-p protocol] [-R date/offset] [-t type] [-v level] [-y] {name}

+

dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-k] [-K directory] [-L ttl] [-n nametype] [-P date/offset] [-p protocol] [-R date/offset] [-t type] [-v level] [-y] {name}

-

DESCRIPTION

+

DESCRIPTION

dnssec-keyfromlabel gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 @@ -44,7 +44,7 @@

-

OPTIONS

+

OPTIONS

-a algorithm
@@ -135,6 +135,15 @@

Generate KEY records rather than DNSKEY records.

+
-L ttl
+

+ Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. +

-p protocol

Sets the protocol value for the key. The protocol @@ -164,7 +173,7 @@

-

TIMING OPTIONS

+

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as @@ -211,7 +220,7 @@

-

GENERATED KEY FILES

+

GENERATED KEY FILES

When dnssec-keyfromlabel completes successfully, @@ -250,7 +259,7 @@

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -258,7 +267,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.8 b/contrib/bind9/bin/dnssec/dnssec-keygen.8 index 689f23df4edb..90daddd15690 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.8 +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004, 2005, 2007-2010, 2012 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004, 2005, 2007-2012 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -33,7 +33,7 @@ dnssec\-keygen \- DNSSEC key generation tool .SH "SYNOPSIS" .HP 14 -\fBdnssec\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-3\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-C\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-q\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] {name} +\fBdnssec\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-3\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-C\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-k\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-q\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keygen\fR @@ -103,11 +103,6 @@ Indicates that the DNS record containing the key should have the specified class Uses a crypto hardware (OpenSSL engine) for random number and, when supported, key generation. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. .RE .PP -\-e -.RS 4 -If generating an RSAMD5/RSASHA1 key, use a large exponent. -.RE -.PP \-f \fIflag\fR .RS 4 Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. @@ -139,6 +134,15 @@ Sets the directory in which the key files are to be written. Deprecated in favor of \-T KEY. .RE .PP +\-L \fIttl\fR +.RS 4 +Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. Setting the default TTL to +0 +or +none +removes it. +.RE +.PP \-p \fIprotocol\fR .RS 4 Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. @@ -298,7 +302,7 @@ RFC 4034. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004, 2005, 2007\-2010, 2012 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004, 2005, 2007\-2012 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2003 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.c b/contrib/bind9/bin/dnssec/dnssec-keygen.c index 3d22f997cc2d..1e61ca392e86 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.c +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.c @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keygen.c,v 1.115.14.4 2011/11/30 00:51:38 marka Exp $ */ +/* $Id: dnssec-keygen.c,v 1.120 2011/11/30 00:48:51 marka Exp $ */ /*! \file */ @@ -124,11 +124,12 @@ usage(void) { #else fprintf(stderr, " -E \n"); #endif - fprintf(stderr, " -e: use large exponent (RSAMD5/RSASHA1 only)\n"); fprintf(stderr, " -f : KSK | REVOKE\n"); fprintf(stderr, " -g : use specified generator " "(DH only)\n"); + fprintf(stderr, " -L : default key TTL\n"); fprintf(stderr, " -p : (default: 3 [dnssec])\n"); + fprintf(stderr, " -r : a file containing random data\n"); fprintf(stderr, " -s : strength value this key signs DNS " "records with (default: 0)\n"); fprintf(stderr, " -T : DNSKEY | KEY (default: DNSKEY; " @@ -137,8 +138,6 @@ usage(void) { fprintf(stderr, " -t : " "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " "(default: AUTHCONF)\n"); - fprintf(stderr, " -r : a file containing random data\n"); - fprintf(stderr, " -h: print usage and exit\n"); fprintf(stderr, " -m :\n"); fprintf(stderr, " usage | trace | record | size | mctx\n"); @@ -212,7 +211,7 @@ main(int argc, char **argv) { isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE; isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; - int ch, rsa_exp = 0, generator = 0, param = 0; + int ch, generator = 0, param = 0; int protocol = -1, size = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; @@ -231,6 +230,7 @@ main(int argc, char **argv) { dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; int dbits = 0; + dns_ttl_t ttl = 0; isc_boolean_t use_default = ISC_FALSE, use_nsec3 = ISC_FALSE; isc_stdtime_t publish = 0, activate = 0, revoke = 0; isc_stdtime_t inactive = 0, delete = 0; @@ -238,7 +238,7 @@ main(int argc, char **argv) { int prepub = -1; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; - isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE; isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; isc_boolean_t unsetdel = ISC_FALSE; @@ -257,7 +257,7 @@ main(int argc, char **argv) { /* * Process memory debugging argument first. */ -#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:km:n:P:p:qR:r:S:s:T:t:v:" +#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:kL:m:n:P:p:qR:r:S:s:T:t:v:" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'm': @@ -310,7 +310,9 @@ main(int argc, char **argv) { engine = isc_commandline_argument; break; case 'e': - rsa_exp = 1; + fprintf(stderr, + "phased-out option -e " + "(was 'use (RSA) large exponent)\n"); break; case 'f': c = (unsigned char)(isc_commandline_argument[0]); @@ -340,6 +342,13 @@ main(int argc, char **argv) { "To generate a key-signing key, use -f KSK.\n" "To generate a key with TYPE=KEY, use -T KEY.\n"); break; + case 'L': + if (strcmp(isc_commandline_argument, "none") == 0) + ttl = 0; + else + ttl = strtottl(isc_commandline_argument); + setttl = ISC_TRUE; + break; case 'n': nametype = isc_commandline_argument; break; @@ -782,13 +791,6 @@ main(int argc, char **argv) { break; } - if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1 || - alg == DNS_KEYALG_NSEC3RSASHA1 || alg == DNS_KEYALG_RSASHA256 || - alg == DNS_KEYALG_RSASHA512 || alg == DST_ALG_ECCGOST || - alg == DST_ALG_ECDSA256 || alg == DST_ALG_ECDSA384) && - rsa_exp != 0) - fatal("specified RSA exponent for a non-RSA key"); - if (alg != DNS_KEYALG_DH && generator != 0) fatal("specified DH generator for a non-DH key"); @@ -848,7 +850,6 @@ main(int argc, char **argv) { case DNS_KEYALG_NSEC3RSASHA1: case DNS_KEYALG_RSASHA256: case DNS_KEYALG_RSASHA512: - param = rsa_exp; show_progress = ISC_TRUE; break; @@ -983,6 +984,10 @@ main(int argc, char **argv) { dst_key_setprivateformat(key, 1, 2); } + /* Set the default key TTL */ + if (setttl) + dst_key_setttl(key, ttl); + /* * Do not overwrite an existing key, or create a key * if there is a risk of ID collision due to this key diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.docbook b/contrib/bind9/bin/dnssec/dnssec-keygen.docbook index 0a1926bd839a..bc50c0226da2 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + June 30, 2000 @@ -43,6 +43,7 @@ 2008 2009 2010 + 2011 2012 Internet Systems Consortium, Inc. ("ISC") @@ -67,7 +68,6 @@ - @@ -75,6 +75,7 @@ + @@ -231,15 +232,6 @@
- - -e - - - If generating an RSAMD5/RSASHA1 key, use a large exponent. - - - - -f flag @@ -300,6 +292,20 @@ + + -L ttl + + + Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. + + + + -p protocol diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.html b/contrib/bind9/bin/dnssec/dnssec-keygen.html index 3bdfa0739f2c..ecf512b165f8 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.html +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.html @@ -1,5 +1,5 @@ - + June 1, 2009 diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.8 b/contrib/bind9/bin/dnssec/dnssec-settime.8 index 8a5e2e789005..7c0c3b289285 100644 --- a/contrib/bind9/bin/dnssec/dnssec-settime.8 +++ b/contrib/bind9/bin/dnssec/dnssec-settime.8 @@ -32,7 +32,7 @@ dnssec\-settime \- Set the key timing metadata for a DNSSEC key .SH "SYNOPSIS" .HP 15 -\fBdnssec\-settime\fR [\fB\-f\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] {keyfile} +\fBdnssec\-settime\fR [\fB\-f\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-L\ \fR\fB\fIttl\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] {keyfile} .SH "DESCRIPTION" .PP \fBdnssec\-settime\fR @@ -67,6 +67,15 @@ will fail when attempting to update a legacy key. With this option, the key will Sets the directory in which the key files are to reside. .RE .PP +\-L \fIttl\fR +.RS 4 +Sets the default TTL to use for this key when it is converted into a DNSKEY RR. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence. Setting the default TTL to +0 +or +none +removes it. +.RE +.PP \-h .RS 4 Emit usage message and exit. diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.c b/contrib/bind9/bin/dnssec/dnssec-settime.c index a7fbed3bcbdb..4c88a07ac455 100644 --- a/contrib/bind9/bin/dnssec/dnssec-settime.c +++ b/contrib/bind9/bin/dnssec/dnssec-settime.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-settime.c,v 1.28.16.3 2011/06/02 20:24:11 each Exp $ */ +/* $Id: dnssec-settime.c,v 1.32 2011/06/02 20:24:45 each Exp $ */ /*! \file */ @@ -66,6 +66,7 @@ usage(void) { fprintf(stderr, " -f: force update of old-style " "keys\n"); fprintf(stderr, " -K directory: set key file location\n"); + fprintf(stderr, " -L ttl: set default key TTL\n"); fprintf(stderr, " -v level: set level of verbosity\n"); fprintf(stderr, " -h: help\n"); fprintf(stderr, "Timing options:\n"); @@ -137,12 +138,13 @@ main(int argc, char **argv) { unsigned int size = 0; isc_uint16_t flags = 0; int prepub = -1; + dns_ttl_t ttl = 0; isc_stdtime_t now; isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; - isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE; isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; isc_boolean_t unsetdel = ISC_FALSE; @@ -169,7 +171,7 @@ main(int argc, char **argv) { isc_stdtime_get(&now); -#define CMDLINE_FLAGS "A:D:E:fhI:i:K:P:p:R:S:uv:" +#define CMDLINE_FLAGS "A:D:E:fhI:i:K:L:P:p:R:S:uv:" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case 'E': @@ -233,6 +235,13 @@ main(int argc, char **argv) { "directory"); } break; + case 'L': + if (strcmp(isc_commandline_argument, "none") == 0) + ttl = 0; + else + ttl = strtottl(isc_commandline_argument); + setttl = ISC_TRUE; + break; case 'v': verbose = strtol(isc_commandline_argument, &endp, 0); if (*endp != '\0') @@ -535,6 +544,9 @@ main(int argc, char **argv) { else if (unsetdel) dst_key_unsettime(key, DST_TIME_DELETE); + if (setttl) + dst_key_setttl(key, ttl); + /* * No metadata changes were made but we're forcing an upgrade * to the new format anyway: use "-P now -A now" as the default @@ -545,6 +557,9 @@ main(int argc, char **argv) { changed = ISC_TRUE; } + if (!changed && setttl) + changed = ISC_TRUE; + /* * Print out time values, if -p was used. */ diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.docbook b/contrib/bind9/bin/dnssec/dnssec-settime.docbook index 3d89b651b473..bc6870b13212 100644 --- a/contrib/bind9/bin/dnssec/dnssec-settime.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-settime.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + July 15, 2009 @@ -48,6 +48,7 @@ dnssec-settime + @@ -116,6 +117,20 @@ + + -L ttl + + + Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. + + + + -h diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.html b/contrib/bind9/bin/dnssec/dnssec-settime.html index 0ac82bcbd3da..7b022658c058 100644 --- a/contrib/bind9/bin/dnssec/dnssec-settime.html +++ b/contrib/bind9/bin/dnssec/dnssec-settime.html @@ -28,10 +28,10 @@

Synopsis

-

dnssec-settime [-f] [-K directory] [-P date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-h] [-v level] [-E engine] {keyfile}

+

dnssec-settime [-f] [-K directory] [-L ttl] [-P date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-h] [-v level] [-E engine] {keyfile}

-

DESCRIPTION

+

DESCRIPTION

dnssec-settime reads a DNSSEC private key file and sets the key timing metadata as specified by the -P, -A, @@ -57,7 +57,7 @@

-

OPTIONS

+

OPTIONS

-f

@@ -74,6 +74,15 @@

Sets the directory in which the key files are to reside.

+
-L ttl
+

+ Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. +

-h

Emit usage message and exit. @@ -90,7 +99,7 @@

-

TIMING OPTIONS

+

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as @@ -169,7 +178,7 @@

-

PRINTING OPTIONS

+

PRINTING OPTIONS

dnssec-settime can also be used to print the timing metadata associated with a key. @@ -195,7 +204,7 @@

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -203,7 +212,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.8 b/contrib/bind9/bin/dnssec/dnssec-signzone.8 index 028068803cdb..c91749569a50 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.8 +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -33,7 +33,7 @@ dnssec\-signzone \- DNSSEC zone signing tool .SH "SYNOPSIS" .HP 16 -\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-p\fR] [\fB\-P\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-t\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-x\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] +\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-L\ \fR\fB\fIserial\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-P\fR] [\fB\-p\fR] [\fB\-R\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-t\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-X\ \fR\fB\fIextended\ end\-time\fR\fR] [\fB\-x\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] .SH "DESCRIPTION" .PP \fBdnssec\-signzone\fR @@ -72,6 +72,15 @@ files in \fBdirectory\fR. .RE .PP +\-D +.RS 4 +Output only those record types automatically managed by +\fBdnssec\-signzone\fR, i.e. RRSIG, NSEC, NSEC3 and NSEC3PARAM records. If smart signing (\fB\-S\fR) is used, DNSKEY records are also included. The resulting file can be included in the original zone file with +\fB$INCLUDE\fR. This option cannot be combined with +\fB\-O raw\fR +or serial number updating. +.RE +.PP \-E \fIengine\fR .RS 4 Uses a crypto hardware (OpenSSL engine) for the crypto operations it supports, for instance signing with private keys from a secure key store. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. @@ -119,11 +128,29 @@ must be later than \fBstart\-time\fR. .RE .PP +\-X \fIextended end\-time\fR +.RS 4 +Specify the date and time when the generated RRSIG records for the DNSKEY RRset will expire. This is to be used in cases when the DNSKEY signatures need to persist longer than signatures on other records; e.g., when the private component of the KSK is kept offline and the KSK signature is to be refreshed manually. +.sp +As with +\fBstart\-time\fR, an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no +\fBextended end\-time\fR +is specified, the value of +\fBend\-time\fR +is used as the default. (\fBend\-time\fR, in turn, defaults to 30 days from the start time.) +\fBextended end\-time\fR +must be later than +\fBstart\-time\fR. +.RE +.PP \-f \fIoutput\-file\fR .RS 4 The name of the output file containing the signed zone. The default is to append \fI.signed\fR -to the input filename. +to the input filename. If +\fBoutput\-file\fR +is set to +"\-", then the signed zone is written to the standard output, with a default output format of "full". .RE .PP \-h @@ -164,6 +191,11 @@ option specifies a jitter window that will be used to randomize the signature ex Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i.e. if large numbers of RRSIGs don't expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time. .RE .PP +\-L \fIserial\fR +.RS 4 +When writing a signed zone to 'raw' format, set the "source serial" value in the header to the specified serial number. (This is expected to be used primarily for testing purposes.) +.RE +.PP \-n \fIncpus\fR .RS 4 Specifies the number of threads to use. By default, one thread is started for each detected CPU. @@ -205,8 +237,15 @@ The zone origin. If not specified, the name of the zone file is assumed to be th .RS 4 The format of the output file containing the signed zone. Possible formats are \fB"text"\fR -(default) and -\fB"raw"\fR. +(default) +\fB"full"\fR, which is text output in a format suitable for processing by external scripts, and +\fB"raw"\fR +or +\fB"raw=N"\fR, which store the zone in a binary format for rapid loading by +\fBnamed\fR. +\fB"raw=N"\fR +specifies the format version of the raw zone file: if N is 0, the raw file can be read by any version of +\fBnamed\fR; if N is 1, the file can be read by release 9.9.0 or higher. The default is 1. .RE .PP \-p @@ -221,6 +260,17 @@ Disable post sign verification tests. The post sign verification test ensures that for each algorithm in use there is at least one non revoked self signed KSK key, that all revoked KSK keys are self signed, and that all records in the zone are signed by the algorithm. This option skips these tests. .RE .PP +\-R +.RS 4 +Remove signatures from keys that no longer exist. +.sp +Normally, when a previously\-signed zone is passed as input to the signer, and a DNSKEY record has been removed and replaced with a new one, signatures from the old key that are still within their validity period are retained. This allows the zone to continue to validate with cached copies of the old DNSKEY RRset. The +\fB\-R\fR +forces +\fBdnssec\-signzone\fR +to remove all orphaned signatures. +.RE +.PP \-r \fIrandomdev\fR .RS 4 Specifies the source of randomness. If the operating system does not provide a @@ -265,8 +315,8 @@ If either of the key's unpublication or deletion dates are set and in the past, .PP \-T \fIttl\fR .RS 4 -Specifies the TTL to be used for new DNSKEY records imported into the zone from the key repository. If not specified, the default is the minimum TTL value from the zone's SOA record. This option is ignored when signing without -\fB\-S\fR, since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre\-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match them. +Specifies a TTL to be used for new DNSKEY records imported into the zone from the key repository. If not specified, the default is the TTL value from the zone's SOA record. This option is ignored when signing without +\fB\-S\fR, since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre\-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match them, or if any of the imported DNSKEY records had a default TTL value. In the event of a a conflict between TTL values in imported keys, the shortest one is used. .RE .PP \-t @@ -378,7 +428,7 @@ RFC 4033. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004\-2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2009, 2011 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2003 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.c b/contrib/bind9/bin/dnssec/dnssec-signzone.c index 86c3aee7095e..83456a7db7d7 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.c +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.262.110.9 2011/07/19 23:47:12 tbox Exp $ */ +/* $Id: dnssec-signzone.c,v 1.285 2011/12/22 07:32:39 each Exp $ */ /*! \file */ @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -124,7 +125,7 @@ struct signer_event { static dns_dnsseckeylist_t keylist; static unsigned int keycount = 0; isc_rwlock_t keylist_lock; -static isc_stdtime_t starttime = 0, endtime = 0, now; +static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now; static int cycle = -1; static int jitter = 0; static isc_boolean_t tryverify = ISC_FALSE; @@ -133,11 +134,13 @@ static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; static dns_ttl_t zone_soa_min_ttl; static dns_ttl_t soa_ttl; -static FILE *fp; +static FILE *fp = NULL; static char *tempfile = NULL; static const dns_master_style_t *masterstyle; static dns_masterformat_t inputformat = dns_masterformat_text; static dns_masterformat_t outputformat = dns_masterformat_text; +static isc_uint32_t rawversion = 1, serialnum = 0; +static isc_boolean_t snset = ISC_FALSE; static unsigned int nsigned = 0, nretained = 0, ndropped = 0; static unsigned int nverified = 0, nverifyfailed = 0; static const char *directory = NULL, *dsdir = NULL; @@ -171,6 +174,10 @@ static isc_boolean_t disable_zone_check = ISC_FALSE; static isc_boolean_t update_chain = ISC_FALSE; static isc_boolean_t set_keyttl = ISC_FALSE; static dns_ttl_t keyttl; +static isc_boolean_t smartsign = ISC_FALSE; +static isc_boolean_t remove_orphans = ISC_FALSE; +static isc_boolean_t output_dnssec_only = ISC_FALSE; +static isc_boolean_t output_stdout = ISC_FALSE; #define INCSTAT(counter) \ if (printstats) { \ @@ -182,19 +189,71 @@ static dns_ttl_t keyttl; static void sign(isc_task_t *task, isc_event_t *event); -#define check_dns_dbiterator_current(result) \ - check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \ - "dns_dbiterator_current()") - static void dumpnode(dns_name_t *name, dns_dbnode_t *node) { + dns_rdataset_t rds; + dns_rdatasetiter_t *iter = NULL; + isc_buffer_t *buffer = NULL; + isc_region_t r; isc_result_t result; + unsigned bufsize = 4096; if (outputformat != dns_masterformat_text) return; - result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name, - masterstyle, fp); - check_result(result, "dns_master_dumpnodetostream"); + + if (!output_dnssec_only) { + result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, + name, masterstyle, fp); + check_result(result, "dns_master_dumpnodetostream"); + return; + } + + result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter); + check_result(result, "dns_db_allrdatasets"); + + dns_rdataset_init(&rds); + + result = isc_buffer_allocate(mctx, &buffer, bufsize); + check_result(result, "isc_buffer_allocate"); + + for (result = dns_rdatasetiter_first(iter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(iter)) { + + dns_rdatasetiter_current(iter, &rds); + + if (rds.type != dns_rdatatype_rrsig && + rds.type != dns_rdatatype_nsec && + rds.type != dns_rdatatype_nsec3 && + rds.type != dns_rdatatype_nsec3param && + (!smartsign || rds.type != dns_rdatatype_dnskey)) { + dns_rdataset_disassociate(&rds); + continue; + } + + for (;;) { + result = dns_master_rdatasettotext(name, &rds, + masterstyle, buffer); + if (result != ISC_R_NOSPACE) + break; + + bufsize <<= 1; + isc_buffer_free(&buffer); + result = isc_buffer_allocate(mctx, &buffer, bufsize); + check_result(result, "isc_buffer_allocate"); + } + check_result(result, "dns_master_rdatasettotext"); + + isc_buffer_usedregion(buffer, &r); + result = isc_stdio_write(r.base, 1, r.length, fp, NULL); + check_result(result, "isc_stdio_write"); + isc_buffer_clear(buffer); + + dns_rdataset_disassociate(&rds); + } + + isc_buffer_free(&buffer); + dns_rdatasetiter_destroy(&iter); } /*% @@ -206,7 +265,7 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) { isc_result_t result; - isc_stdtime_t jendtime; + isc_stdtime_t jendtime, expiry; char keystr[DST_KEY_FORMATSIZE]; dns_rdata_t trdata = DNS_RDATA_INIT; unsigned char array[BUFSIZE]; @@ -216,7 +275,12 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, dst_key_format(key, keystr, sizeof(keystr)); vbprintf(1, "\t%s %s\n", logmsg, keystr); - jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime; + if (rdataset->type == dns_rdatatype_dnskey) + expiry = dnskey_endtime; + else + expiry = endtime; + + jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry; isc_buffer_init(&b, array, sizeof(array)); result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime, mctx, &b, &trdata); @@ -253,6 +317,12 @@ issigningkey(dns_dnsseckey_t *key) { return (key->force_sign || key->hint_sign); } +static inline isc_boolean_t +ispublishedkey(dns_dnsseckey_t *key) { + return ((key->force_publish || key->hint_publish) && + !key->hint_remove); +} + static inline isc_boolean_t iszonekey(dns_dnsseckey_t *key) { return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) && @@ -334,13 +404,16 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { directory, mctx, &privkey); if (result == ISC_R_SUCCESS) { dst_key_free(&pubkey); - dns_dnsseckey_create(mctx, &privkey, &key); - } else { - dns_dnsseckey_create(mctx, &pubkey, &key); + result = dns_dnsseckey_create(mctx, &privkey, &key); + } else + result = dns_dnsseckey_create(mctx, &pubkey, &key); + + if (result == ISC_R_SUCCESS) { + key->force_publish = ISC_FALSE; + key->force_sign = ISC_FALSE; + key->index = keycount++; + ISC_LIST_APPEND(keylist, key, link); } - key->force_publish = ISC_FALSE; - key->force_sign = ISC_FALSE; - ISC_LIST_APPEND(keylist, key, link); isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); return (key); @@ -481,38 +554,38 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, "private dnskey not found\n", sigstr); } else if (key == NULL || future) { + keep = (!expired && !remove_orphans); vbprintf(2, "\trrsig by %s %s - dnskey not found\n", - expired ? "retained" : "dropped", sigstr); - if (!expired) - keep = ISC_TRUE; + keep ? "retained" : "dropped", sigstr); } else if (issigningkey(key)) { + wassignedby[key->index] = ISC_TRUE; + if (!expired && rrsig.originalttl == set->ttl && setverifies(name, set, key->key, &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; - wassignedby[key->index] = ISC_TRUE; - nowsignedby[key->index] = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : rrsig.originalttl != set->ttl ? "ttl change" : "failed to verify"); - wassignedby[key->index] = ISC_TRUE; resign = ISC_TRUE; } + } else if (!ispublishedkey(key) && remove_orphans) { + vbprintf(2, "\trrsig by %s dropped - dnskey removed\n", + sigstr); } else if (iszonekey(key)) { + wassignedby[key->index] = ISC_TRUE; + if (!expired && rrsig.originalttl == set->ttl && setverifies(name, set, key->key, &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; - wassignedby[key->index] = ISC_TRUE; - nowsignedby[key->index] = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : rrsig.originalttl != set->ttl ? "ttl change" : "failed to verify"); - wassignedby[key->index] = ISC_TRUE; } } else if (!expired) { vbprintf(2, "\trrsig by %s retained\n", sigstr); @@ -545,6 +618,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, } } else { tuple = NULL; + vbprintf(2, "removing signature by %s\n", sigstr); result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL, name, sigset.ttl, &sigrdata, &tuple); @@ -921,26 +995,6 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { return (result); } -static isc_boolean_t -delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) { - dns_rdataset_t nsset; - isc_result_t result; - - if (dns_name_equal(name, gorigin)) - return (ISC_FALSE); - - dns_rdataset_init(&nsset); - result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns, - 0, 0, &nsset, NULL); - if (dns_rdataset_isassociated(&nsset)) { - if (ttlp != NULL) - *ttlp = nsset.ttl; - dns_rdataset_disassociate(&nsset); - } - - return (ISC_TF(result == ISC_R_SUCCESS)); -} - static isc_boolean_t secure(dns_name_t *name, dns_dbnode_t *node) { dns_rdataset_t dsset; @@ -976,7 +1030,7 @@ signname(dns_dbnode_t *node, dns_name_t *name) { /* * Determine if this is a delegation point. */ - if (delegation(name, node, NULL)) + if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) isdelegation = ISC_TRUE; /* @@ -1309,485 +1363,6 @@ postsign(void) { dns_dbiterator_destroy(&gdbiter); } -static isc_boolean_t -goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset, - dns_rdataset_t *rdataset) -{ - dns_rdata_dnskey_t key; - dns_rdata_rrsig_t sig; - dst_key_t *dstkey = NULL; - isc_result_t result; - - dns_rdata_tostruct(sigrdata, &sig, NULL); - - for (result = dns_rdataset_first(keyrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(keyrdataset)) { - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_current(keyrdataset, &rdata); - dns_rdata_tostruct(&rdata, &key, NULL); - result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx, - &dstkey); - if (result != ISC_R_SUCCESS) - return (ISC_FALSE); - if (sig.algorithm != key.algorithm || - sig.keyid != dst_key_id(dstkey) || - !dns_name_equal(&sig.signer, gorigin)) { - dst_key_free(&dstkey); - continue; - } - result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE, - mctx, sigrdata); - dst_key_free(&dstkey); - if (result == ISC_R_SUCCESS) - return(ISC_TRUE); - } - return (ISC_FALSE); -} - -static void -verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node, - dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms, - unsigned char *bad_algorithms) -{ - unsigned char set_algorithms[256]; - char namebuf[DNS_NAME_FORMATSIZE]; - char algbuf[80]; - char typebuf[80]; - dns_rdataset_t sigrdataset; - dns_rdatasetiter_t *rdsiter = NULL; - isc_result_t result; - int i; - - dns_rdataset_init(&sigrdataset); - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); - check_result(result, "dns_db_allrdatasets()"); - for (result = dns_rdatasetiter_first(rdsiter); - result == ISC_R_SUCCESS; - result = dns_rdatasetiter_next(rdsiter)) { - dns_rdatasetiter_current(rdsiter, &sigrdataset); - if (sigrdataset.type == dns_rdatatype_rrsig && - sigrdataset.covers == rdataset->type) - break; - dns_rdataset_disassociate(&sigrdataset); - } - if (result != ISC_R_SUCCESS) { - dns_name_format(name, namebuf, sizeof(namebuf)); - type_format(rdataset->type, typebuf, sizeof(typebuf)); - fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf); - for (i = 0; i < 256; i++) - if (ksk_algorithms[i] != 0) - bad_algorithms[i] = 1; - return; - } - - memset(set_algorithms, 0, sizeof(set_algorithms)); - for (result = dns_rdataset_first(&sigrdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&sigrdataset)) { - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_rrsig_t sig; - - dns_rdataset_current(&sigrdataset, &rdata); - dns_rdata_tostruct(&rdata, &sig, NULL); - if (rdataset->ttl != sig.originalttl) { - dns_name_format(name, namebuf, sizeof(namebuf)); - type_format(rdataset->type, typebuf, sizeof(typebuf)); - fprintf(stderr, "TTL mismatch for %s %s keytag %u\n", - namebuf, typebuf, sig.keyid); - continue; - } - if ((set_algorithms[sig.algorithm] != 0) || - (ksk_algorithms[sig.algorithm] == 0)) - continue; - if (goodsig(&rdata, name, keyrdataset, rdataset)) - set_algorithms[sig.algorithm] = 1; - } - dns_rdatasetiter_destroy(&rdsiter); - if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) { - dns_name_format(name, namebuf, sizeof(namebuf)); - type_format(rdataset->type, typebuf, sizeof(typebuf)); - for (i = 0; i < 256; i++) - if ((ksk_algorithms[i] != 0) && - (set_algorithms[i] == 0)) { - dns_secalg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Missing %s signature for " - "%s %s\n", algbuf, namebuf, typebuf); - bad_algorithms[i] = 1; - } - } - dns_rdataset_disassociate(&sigrdataset); -} - -static void -verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation, - dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms, - unsigned char *bad_algorithms) -{ - dns_rdataset_t rdataset; - dns_rdatasetiter_t *rdsiter = NULL; - isc_result_t result; - - result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); - check_result(result, "dns_db_allrdatasets()"); - result = dns_rdatasetiter_first(rdsiter); - dns_rdataset_init(&rdataset); - while (result == ISC_R_SUCCESS) { - dns_rdatasetiter_current(rdsiter, &rdataset); - if (rdataset.type != dns_rdatatype_rrsig && - rdataset.type != dns_rdatatype_dnskey && - (!delegation || rdataset.type == dns_rdatatype_ds || - rdataset.type == dns_rdatatype_nsec)) { - verifyset(&rdataset, name, node, keyrdataset, - ksk_algorithms, bad_algorithms); - } - dns_rdataset_disassociate(&rdataset); - result = dns_rdatasetiter_next(rdsiter); - } - if (result != ISC_R_NOMORE) - fatal("rdataset iteration failed: %s", - isc_result_totext(result)); - dns_rdatasetiter_destroy(&rdsiter); -} - -/*% - * Verify that certain things are sane: - * - * The apex has a DNSKEY RRset with at least one KSK, and at least - * one ZSK if the -x flag was not used. - * - * The DNSKEY record was signed with at least one of the KSKs in - * the DNSKEY RRset. - * - * The rest of the zone was signed with at least one of the ZSKs - * present in the DNSKEY RRset. - */ -static void -verifyzone(void) { - char algbuf[80]; - dns_dbiterator_t *dbiter = NULL; - dns_dbnode_t *node = NULL, *nextnode = NULL; - dns_fixedname_t fname, fnextname, fzonecut; - dns_name_t *name, *nextname, *zonecut; - dns_rdata_dnskey_t dnskey; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_t keyset, soaset; - dns_rdataset_t keysigs, soasigs; - int i; - isc_boolean_t done = ISC_FALSE; - isc_boolean_t first = ISC_TRUE; - isc_boolean_t goodksk = ISC_FALSE; - isc_result_t result; - unsigned char revoked_ksk[256]; - unsigned char revoked_zsk[256]; - unsigned char standby_ksk[256]; - unsigned char standby_zsk[256]; - unsigned char ksk_algorithms[256]; - unsigned char zsk_algorithms[256]; - unsigned char bad_algorithms[256]; -#ifdef ALLOW_KSKLESS_ZONES - isc_boolean_t allzsksigned = ISC_TRUE; - unsigned char self_algorithms[256]; -#endif - - if (disable_zone_check) - return; - - result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node); - if (result != ISC_R_SUCCESS) - fatal("failed to find the zone's origin: %s", - isc_result_totext(result)); - - dns_rdataset_init(&keyset); - dns_rdataset_init(&keysigs); - dns_rdataset_init(&soaset); - dns_rdataset_init(&soasigs); - - result = dns_db_findrdataset(gdb, node, gversion, - dns_rdatatype_dnskey, - 0, 0, &keyset, &keysigs); - if (result != ISC_R_SUCCESS) - fatal("cannot find DNSKEY rrset\n"); - - result = dns_db_findrdataset(gdb, node, gversion, - dns_rdatatype_soa, - 0, 0, &soaset, &soasigs); - dns_db_detachnode(gdb, &node); - if (result != ISC_R_SUCCESS) - fatal("cannot find SOA rrset\n"); - - if (!dns_rdataset_isassociated(&keysigs)) - fatal("cannot find DNSKEY RRSIGs\n"); - - if (!dns_rdataset_isassociated(&soasigs)) - fatal("cannot find SOA RRSIGs\n"); - - memset(revoked_ksk, 0, sizeof(revoked_ksk)); - memset(revoked_zsk, 0, sizeof(revoked_zsk)); - memset(standby_ksk, 0, sizeof(standby_ksk)); - memset(standby_zsk, 0, sizeof(standby_zsk)); - memset(ksk_algorithms, 0, sizeof(ksk_algorithms)); - memset(zsk_algorithms, 0, sizeof(zsk_algorithms)); - memset(bad_algorithms, 0, sizeof(bad_algorithms)); -#ifdef ALLOW_KSKLESS_ZONES - memset(self_algorithms, 0, sizeof(self_algorithms)); -#endif - - /* - * Check that the DNSKEY RR has at least one self signing KSK - * and one ZSK per algorithm in it (or, if -x was used, one - * self-signing KSK). - */ - for (result = dns_rdataset_first(&keyset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&keyset)) { - dns_rdataset_current(&keyset, &rdata); - result = dns_rdata_tostruct(&rdata, &dnskey, NULL); - check_result(result, "dns_rdata_tostruct"); - - if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0) - ; - else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) { - if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && - !dns_dnssec_selfsigns(&rdata, gorigin, &keyset, - &keysigs, ISC_FALSE, - mctx)) { - char namebuf[DNS_NAME_FORMATSIZE]; - char buffer[1024]; - isc_buffer_t buf; - - dns_name_format(gorigin, namebuf, - sizeof(namebuf)); - isc_buffer_init(&buf, buffer, sizeof(buffer)); - result = dns_rdata_totext(&rdata, NULL, &buf); - check_result(result, "dns_rdata_totext"); - fatal("revoked KSK is not self signed:\n" - "%s DNSKEY %.*s", namebuf, - (int)isc_buffer_usedlength(&buf), buffer); - } - if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && - revoked_ksk[dnskey.algorithm] != 255) - revoked_ksk[dnskey.algorithm]++; - else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && - revoked_zsk[dnskey.algorithm] != 255) - revoked_zsk[dnskey.algorithm]++; - } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) { - if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset, - &keysigs, ISC_FALSE, mctx)) { - if (ksk_algorithms[dnskey.algorithm] != 255) - ksk_algorithms[dnskey.algorithm]++; - goodksk = ISC_TRUE; - } else { - if (standby_ksk[dnskey.algorithm] != 255) - standby_ksk[dnskey.algorithm]++; - } - } else if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset, - &keysigs, ISC_FALSE, - mctx)) { -#ifdef ALLOW_KSKLESS_ZONES - if (self_algorithms[dnskey.algorithm] != 255) - self_algorithms[dnskey.algorithm]++; -#endif - if (zsk_algorithms[dnskey.algorithm] != 255) - zsk_algorithms[dnskey.algorithm]++; - } else if (dns_dnssec_signs(&rdata, gorigin, &soaset, - &soasigs, ISC_FALSE, mctx)) { - if (zsk_algorithms[dnskey.algorithm] != 255) - zsk_algorithms[dnskey.algorithm]++; - } else { - if (standby_zsk[dnskey.algorithm] != 255) - standby_zsk[dnskey.algorithm]++; -#ifdef ALLOW_KSKLESS_ZONES - allzsksigned = ISC_FALSE; -#endif - } - dns_rdata_freestruct(&dnskey); - dns_rdata_reset(&rdata); - } - dns_rdataset_disassociate(&keysigs); - dns_rdataset_disassociate(&soaset); - dns_rdataset_disassociate(&soasigs); - -#ifdef ALLOW_KSKLESS_ZONES - if (!goodksk) { - if (!ignore_kskflag) - fprintf(stderr, "No self signing KSK found. Using " - "self signed ZSK's for active " - "algorithm list.\n"); - memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms)); - if (!allzsksigned) - fprintf(stderr, "warning: not all ZSK's are self " - "signed.\n"); - } -#else - if (!goodksk) { - fatal("No self signed KSK's found"); - } -#endif - - fprintf(stderr, "Verifying the zone using the following algorithms:"); - for (i = 0; i < 256; i++) { -#ifdef ALLOW_KSKLESS_ZONES - if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0) -#else - if (ksk_algorithms[i] != 0) -#endif - { - dns_secalg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, " %s", algbuf); - } - } - fprintf(stderr, ".\n"); - - if (!ignore_kskflag && !keyset_kskonly) { - for (i = 0; i < 256; i++) { - /* - * The counts should both be zero or both be non-zero. - * Mark the algorithm as bad if this is not met. - */ - if ((ksk_algorithms[i] != 0) == - (zsk_algorithms[i] != 0)) - continue; - dns_secalg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Missing %s for algorithm %s\n", - (ksk_algorithms[i] != 0) - ? "ZSK" - : "self signing KSK", - algbuf); - bad_algorithms[i] = 1; - } - } - - /* - * Check that all the other records were signed by keys that are - * present in the DNSKEY RRSET. - */ - - dns_fixedname_init(&fname); - name = dns_fixedname_name(&fname); - dns_fixedname_init(&fnextname); - nextname = dns_fixedname_name(&fnextname); - dns_fixedname_init(&fzonecut); - zonecut = NULL; - - result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); - check_result(result, "dns_db_createiterator()"); - - result = dns_dbiterator_first(dbiter); - check_result(result, "dns_dbiterator_first()"); - - while (!done) { - isc_boolean_t isdelegation = ISC_FALSE; - - result = dns_dbiterator_current(dbiter, &node, name); - check_dns_dbiterator_current(result); - if (!dns_name_issubdomain(name, gorigin)) { - dns_db_detachnode(gdb, &node); - result = dns_dbiterator_next(dbiter); - if (result == ISC_R_NOMORE) - done = ISC_TRUE; - else - check_result(result, "dns_dbiterator_next()"); - continue; - } - if (delegation(name, node, NULL)) { - zonecut = dns_fixedname_name(&fzonecut); - dns_name_copy(name, zonecut, NULL); - isdelegation = ISC_TRUE; - } - verifynode(name, node, isdelegation, &keyset, - ksk_algorithms, bad_algorithms); - result = dns_dbiterator_next(dbiter); - nextnode = NULL; - while (result == ISC_R_SUCCESS) { - result = dns_dbiterator_current(dbiter, &nextnode, - nextname); - check_dns_dbiterator_current(result); - if (!dns_name_issubdomain(nextname, gorigin) || - (zonecut != NULL && - dns_name_issubdomain(nextname, zonecut))) - { - dns_db_detachnode(gdb, &nextnode); - result = dns_dbiterator_next(dbiter); - continue; - } - dns_db_detachnode(gdb, &nextnode); - break; - } - if (result == ISC_R_NOMORE) { - done = ISC_TRUE; - } else if (result != ISC_R_SUCCESS) - fatal("iterating through the database failed: %s", - isc_result_totext(result)); - dns_db_detachnode(gdb, &node); - } - - dns_dbiterator_destroy(&dbiter); - - result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); - check_result(result, "dns_db_createiterator()"); - - for (result = dns_dbiterator_first(dbiter); - result == ISC_R_SUCCESS; - result = dns_dbiterator_next(dbiter) ) { - result = dns_dbiterator_current(dbiter, &node, name); - check_dns_dbiterator_current(result); - verifynode(name, node, ISC_FALSE, &keyset, - ksk_algorithms, bad_algorithms); - dns_db_detachnode(gdb, &node); - } - dns_dbiterator_destroy(&dbiter); - - dns_rdataset_disassociate(&keyset); - - /* - * If we made it this far, we have what we consider a properly signed - * zone. Set the good flag. - */ - for (i = 0; i < 256; i++) { - if (bad_algorithms[i] != 0) { - if (first) - fprintf(stderr, "The zone is not fully signed " - "for the following algorithms:"); - dns_secalg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, " %s", algbuf); - first = ISC_FALSE; - } - } - if (!first) { - fprintf(stderr, ".\n"); - fatal("DNSSEC completeness test failed."); - } - - if (goodksk || ignore_kskflag) { - /* - * Print the success summary. - */ - fprintf(stderr, "Zone signing complete:\n"); - for (i = 0; i < 256; i++) { - if ((ksk_algorithms[i] != 0) || - (standby_ksk[i] != 0) || - (revoked_zsk[i] != 0) || - (zsk_algorithms[i] != 0) || - (standby_zsk[i] != 0) || - (revoked_zsk[i] != 0)) { - dns_secalg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Algorithm: %s: KSKs: " - "%u active, %u stand-by, %u revoked\n", - algbuf, ksk_algorithms[i], - standby_ksk[i], revoked_ksk[i]); - fprintf(stderr, "%*sZSKs: " - "%u active, %u %s, %u revoked\n", - (int) strlen(algbuf) + 13, "", - zsk_algorithms[i], - standby_zsk[i], - keyset_kskonly ? "present" : "stand-by", - revoked_zsk[i]); - } - } - } -} - /*% * Sign the apex of the zone. * Note the origin may not be the first node if there are out of zone @@ -1885,7 +1460,7 @@ assignwork(isc_task_t *task, isc_task_t *worker) { if (dns_name_issubdomain(name, gorigin) && (zonecut == NULL || !dns_name_issubdomain(name, zonecut))) { - if (delegation(name, node, NULL)) { + if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) { dns_fixedname_init(&fzonecut); zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); @@ -2181,7 +1756,7 @@ nsecify(void) { remove_records(node, dns_rdatatype_nsec3param, ISC_TRUE); - if (delegation(name, node, &nsttl)) { + if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); remove_sigs(node, 0); @@ -2622,7 +2197,9 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, result = dns_dbiterator_next(dbiter); continue; } - if (delegation(nextname, nextnode, &nsttl)) { + if (is_delegation(gdb, gversion, gorigin, + nextname, nextnode, &nsttl)) + { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(nextname, zonecut, NULL); remove_sigs(nextnode, 0); @@ -2751,7 +2328,9 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, result = dns_dbiterator_next(dbiter); continue; } - if (delegation(nextname, nextnode, NULL)) { + if (is_delegation(gdb, gversion, gorigin, + nextname, nextnode, NULL)) + { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(nextname, zonecut, NULL); if (OPTOUT(nsec3flags) && @@ -3324,10 +2903,16 @@ usage(void) { fprintf(stderr, "update DS records based on child zones' " "dsset-* files\n"); fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n"); - fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n"); + fprintf(stderr, "\t\tRRSIG start time " + "- absolute|offset (now - 1 hour)\n"); fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); - fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now " + fprintf(stderr, "\t\tRRSIG end time " + "- absolute|from start|from now " "(now + 30 days)\n"); + fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); + fprintf(stderr, "\t\tDNSKEY RRSIG end " + "- absolute|from start|from now " + "(matches -e)\n"); fprintf(stderr, "\t-i interval:\n"); fprintf(stderr, "\t\tcycle interval - resign " "if < interval from end ( (end-start)/4 )\n"); @@ -3345,6 +2930,8 @@ usage(void) { fprintf(stderr, "\t\tfile format of signed zone file (text)\n"); fprintf(stderr, "\t-N format:\n"); fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n"); + fprintf(stderr, "\t-D:\n"); + fprintf(stderr, "\t\toutput only DNSSEC-related records\n"); fprintf(stderr, "\t-r randomdev:\n"); fprintf(stderr, "\t\ta file containing random data\n"); fprintf(stderr, "\t-a:\t"); @@ -3361,6 +2948,8 @@ usage(void) { fprintf(stderr, "use pseudorandom data (faster but less secure)\n"); fprintf(stderr, "\t-P:\t"); fprintf(stderr, "disable post-sign verification\n"); + fprintf(stderr, "\t-R:\t"); + fprintf(stderr, "remove signatures from keys that no longer exist\n"); fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); fprintf(stderr, "\t-t:\t"); fprintf(stderr, "print statistics\n"); @@ -3398,36 +2987,39 @@ print_stats(isc_time_t *timer_start, isc_time_t *timer_finish, isc_uint64_t time_us; /* Time in microseconds */ isc_uint64_t time_ms; /* Time in milliseconds */ isc_uint64_t sig_ms; /* Signatures per millisecond */ + FILE *out = output_stdout ? stderr : stdout; - printf("Signatures generated: %10d\n", nsigned); - printf("Signatures retained: %10d\n", nretained); - printf("Signatures dropped: %10d\n", ndropped); - printf("Signatures successfully verified: %10d\n", nverified); - printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed); + fprintf(out, "Signatures generated: %10d\n", nsigned); + fprintf(out, "Signatures retained: %10d\n", nretained); + fprintf(out, "Signatures dropped: %10d\n", ndropped); + fprintf(out, "Signatures successfully verified: %10d\n", nverified); + fprintf(out, "Signatures unsuccessfully " + "verified: %10d\n", nverifyfailed); time_us = isc_time_microdiff(sign_finish, sign_start); time_ms = time_us / 1000; - printf("Signing time in seconds: %7u.%03u\n", - (unsigned int) (time_ms / 1000), - (unsigned int) (time_ms % 1000)); + fprintf(out, "Signing time in seconds: %7u.%03u\n", + (unsigned int) (time_ms / 1000), + (unsigned int) (time_ms % 1000)); if (time_us > 0) { sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us; - printf("Signatures per second: %7u.%03u\n", - (unsigned int) sig_ms / 1000, - (unsigned int) sig_ms % 1000); + fprintf(out, "Signatures per second: %7u.%03u\n", + (unsigned int) sig_ms / 1000, + (unsigned int) sig_ms % 1000); } time_us = isc_time_microdiff(timer_finish, timer_start); time_ms = time_us / 1000; - printf("Runtime in seconds: %7u.%03u\n", - (unsigned int) (time_ms / 1000), - (unsigned int) (time_ms % 1000)); + fprintf(out, "Runtime in seconds: %7u.%03u\n", + (unsigned int) (time_ms / 1000), + (unsigned int) (time_ms % 1000)); } int main(int argc, char *argv[]) { int i, ch; char *startstr = NULL, *endstr = NULL, *classname = NULL; + char *dnskey_endstr = NULL; char *origin = NULL, *file = NULL, *output = NULL; char *inputformatstr = NULL, *outputformatstr = NULL; char *serialformatstr = NULL; @@ -3447,20 +3039,20 @@ main(int argc, char *argv[]) { #endif unsigned int eflags; isc_boolean_t free_output = ISC_FALSE; - int tempfilelen; + int tempfilelen = 0; dns_rdataclass_t rdclass; isc_task_t **tasks = NULL; isc_buffer_t b; int len; hashlist_t hashlist; - isc_boolean_t smartsign = ISC_FALSE; isc_boolean_t make_keyset = ISC_FALSE; isc_boolean_t set_salt = ISC_FALSE; isc_boolean_t set_optout = ISC_FALSE; isc_boolean_t set_iter = ISC_FALSE; + isc_boolean_t nonsecify = ISC_FALSE; #define CMDLINE_FLAGS \ - "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz" + "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpRr:s:ST:tuUv:X:xzZ:" /* * Process memory debugging argument first. @@ -3546,6 +3138,10 @@ main(int argc, char *argv[]) { dsdir, isc_result_totext(result)); break; + case 'D': + output_dnssec_only = ISC_TRUE; + break; + case 'E': engine = isc_commandline_argument; break; @@ -3556,6 +3152,8 @@ main(int argc, char *argv[]) { case 'f': output = isc_commandline_argument; + if (strcmp(output, "-") == 0) + output_stdout = ISC_TRUE; break; case 'g': @@ -3604,6 +3202,17 @@ main(int argc, char *argv[]) { dskeyfile[ndskeys++] = isc_commandline_argument; break; + case 'L': + snset = ISC_TRUE; + endp = NULL; + serialnum = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fprintf(stderr, "source serial number " + "must be numeric"); + exit(1); + } + break; + case 'l': len = strlen(isc_commandline_argument); isc_buffer_init(&b, isc_commandline_argument, len); @@ -3646,6 +3255,10 @@ main(int argc, char *argv[]) { pseudorandom = ISC_TRUE; break; + case 'R': + remove_orphans = ISC_TRUE; + break; + case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; @@ -3683,6 +3296,10 @@ main(int argc, char *argv[]) { fatal("verbose level must be numeric"); break; + case 'X': + dnskey_endstr = isc_commandline_argument; + break; + case 'x': keyset_kskonly = ISC_TRUE; break; @@ -3705,6 +3322,10 @@ main(int argc, char *argv[]) { fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); + case 'Z': /* Undocumented test options */ + if (!strcmp(isc_commandline_argument, "nonsecify")) + nonsecify = ISC_TRUE; + break; } } @@ -3730,11 +3351,19 @@ main(int argc, char *argv[]) { } else starttime = now - 3600; /* Allow for some clock skew. */ - if (endstr != NULL) { + if (endstr != NULL) endtime = strtotime(endstr, now, starttime); - } else + else endtime = starttime + (30 * 24 * 60 * 60); + if (dnskey_endstr != NULL) { + dnskey_endtime = strtotime(dnskey_endstr, now, starttime); + if (endstr != NULL && dnskey_endtime == endtime) + fprintf(stderr, "WARNING: -e and -X were both set, " + "but have identical values.\n"); + } else + dnskey_endtime = endtime; + if (cycle == -1) cycle = (endtime - starttime) / 4; @@ -3777,16 +3406,36 @@ main(int argc, char *argv[]) { inputformat = dns_masterformat_text; else if (strcasecmp(inputformatstr, "raw") == 0) inputformat = dns_masterformat_raw; - else - fatal("unknown file format: %s\n", inputformatstr); + else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { + inputformat = dns_masterformat_raw; + fprintf(stderr, + "WARNING: input format version ignored\n"); + } else + fatal("unknown file format: %s", inputformatstr); + } if (outputformatstr != NULL) { - if (strcasecmp(outputformatstr, "text") == 0) + if (strcasecmp(outputformatstr, "text") == 0) { outputformat = dns_masterformat_text; - else if (strcasecmp(outputformatstr, "raw") == 0) + } else if (strcasecmp(outputformatstr, "full") == 0) { + outputformat = dns_masterformat_text; + masterstyle = &dns_master_style_full; + } else if (strcasecmp(outputformatstr, "raw") == 0) { outputformat = dns_masterformat_raw; - else + } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { + char *end; + outputformat = dns_masterformat_raw; + + outputformat = dns_masterformat_raw; + rawversion = strtol(outputformatstr + 4, &end, 10); + if (end == outputformatstr + 4 || *end != '\0' || + rawversion > 1U) { + fprintf(stderr, + "unknown raw format version\n"); + exit(1); + } + } else fatal("unknown file format: %s\n", outputformatstr); } @@ -3803,6 +3452,12 @@ main(int argc, char *argv[]) { serialformatstr); } + if (output_dnssec_only && outputformat != dns_masterformat_text) + fatal("option -D can only be used with \"-O text\"\n"); + + if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP) + fatal("option -D can only be used with \"-N keep\"\n"); + result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL, 0, 24, 0, 0, 0, 8, mctx); check_result(result, "dns_master_stylecreate"); @@ -3826,18 +3481,6 @@ main(int argc, char *argv[]) { else set_nsec3params(update_chain, set_salt, set_optout, set_iter); - if (IS_NSEC3) { - isc_boolean_t answer; - hash_length = dns_nsec3_hashlength(dns_hash_sha1); - hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2, - hash_length); - result = dns_nsec_nseconly(gdb, gversion, &answer); - check_result(result, "dns_nsec_nseconly"); - if (answer) - fatal("NSEC3 generation requested with " - "NSEC only DNSKEY"); - } - /* * We need to do this early on, as we start messing with the list * of keys rather early. @@ -3890,6 +3533,22 @@ main(int argc, char *argv[]) { if (IS_NSEC3) { unsigned int max; + isc_boolean_t answer; + + hash_length = dns_nsec3_hashlength(dns_hash_sha1); + hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2, + hash_length); + result = dns_nsec_nseconly(gdb, gversion, &answer); + if (result == ISC_R_NOTFOUND) + fprintf(stderr, "%s: warning: NSEC3 generation " + "requested with no DNSKEY; ignoring\n", + program); + else if (result != ISC_R_SUCCESS) + check_result(result, "dns_nsec_nseconly"); + else if (answer) + fatal("NSEC3 generation requested with " + "NSEC-only DNSKEY"); + result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max); check_result(result, "dns_nsec3_maxiterations()"); if (nsec3iter > max) @@ -3916,11 +3575,13 @@ main(int argc, char *argv[]) { remove_duplicates(); - if (IS_NSEC3) - nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length, - &hashlist); - else - nsecify(); + if (!nonsecify) { + if (IS_NSEC3) + nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length, + &hashlist); + else + nsecify(); + } if (!nokeys) { writeset("dsset-", dns_rdatatype_ds); @@ -3931,24 +3592,29 @@ main(int argc, char *argv[]) { } } - tempfilelen = strlen(output) + 20; - tempfile = isc_mem_get(mctx, tempfilelen); - if (tempfile == NULL) - fatal("out of memory"); + if (output_stdout) { + fp = stdout; + if (outputformatstr == NULL) + masterstyle = &dns_master_style_full; + } else { + tempfilelen = strlen(output) + 20; + tempfile = isc_mem_get(mctx, tempfilelen); + if (tempfile == NULL) + fatal("out of memory"); - result = isc_file_mktemplate(output, tempfile, tempfilelen); - check_result(result, "isc_file_mktemplate"); + result = isc_file_mktemplate(output, tempfile, tempfilelen); + check_result(result, "isc_file_mktemplate"); - fp = NULL; - if (outputformat == dns_masterformat_text) - result = isc_file_openunique(tempfile, &fp); - else - result = isc_file_bopenunique(tempfile, &fp); - if (result != ISC_R_SUCCESS) - fatal("failed to open temporary output file: %s", - isc_result_totext(result)); - removefile = ISC_TRUE; - setfatalcallback(&removetempfile); + if (outputformat == dns_masterformat_text) + result = isc_file_openunique(tempfile, &fp); + else + result = isc_file_bopenunique(tempfile, &fp); + if (result != ISC_R_SUCCESS) + fatal("failed to open temporary output file: %s", + isc_result_totext(result)); + removefile = ISC_TRUE; + setfatalcallback(&removetempfile); + } print_time(fp); print_version(fp); @@ -4005,29 +3671,42 @@ main(int argc, char *argv[]) { isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *)); postsign(); TIME_NOW(&sign_finish); - verifyzone(); + + if (!disable_zone_check) + verifyzone(gdb, gversion, gorigin, mctx, + ignore_kskflag, keyset_kskonly); if (outputformat != dns_masterformat_text) { - result = dns_master_dumptostream2(mctx, gdb, gversion, + dns_masterrawheader_t header; + dns_master_initrawheader(&header); + if (rawversion == 0U) + header.flags = DNS_MASTERRAW_COMPAT; + else if (snset) { + header.flags = DNS_MASTERRAW_SOURCESERIALSET; + header.sourceserial = serialnum; + } + result = dns_master_dumptostream3(mctx, gdb, gversion, masterstyle, outputformat, - fp); - check_result(result, "dns_master_dumptostream2"); + &header, fp); + check_result(result, "dns_master_dumptostream3"); } - result = isc_stdio_close(fp); - check_result(result, "isc_stdio_close"); - removefile = ISC_FALSE; - - result = isc_file_rename(tempfile, output); - if (result != ISC_R_SUCCESS) - fatal("failed to rename temp file to %s: %s\n", - output, isc_result_totext(result)); - DESTROYLOCK(&namelock); if (printstats) DESTROYLOCK(&statslock); - printf("%s\n", output); + if (!output_stdout) { + result = isc_stdio_close(fp); + check_result(result, "isc_stdio_close"); + removefile = ISC_FALSE; + + result = isc_file_rename(tempfile, output); + if (result != ISC_R_SUCCESS) + fatal("failed to rename temp file to %s: %s\n", + output, isc_result_totext(result)); + + printf("%s\n", output); + } dns_db_closeversion(gdb, &gversion, ISC_FALSE); dns_db_detach(&gdb); @@ -4038,7 +3717,8 @@ main(int argc, char *argv[]) { dns_dnsseckey_destroy(mctx, &key); } - isc_mem_put(mctx, tempfile, tempfilelen); + if (tempfilelen != 0) + isc_mem_put(mctx, tempfile, tempfilelen); if (free_output) isc_mem_free(mctx, output); diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.docbook b/contrib/bind9/bin/dnssec/dnssec-signzone.docbook index 128ebe96341b..e427fc1266bc 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + June 05, 2009 @@ -43,6 +43,7 @@ 2007 2008 2009 + 2011 Internet Systems Consortium, Inc. ("ISC") @@ -60,6 +61,7 @@ + @@ -67,6 +69,7 @@ + @@ -74,8 +77,9 @@ - + + @@ -83,6 +87,7 @@ + @@ -151,6 +156,22 @@
+ + -D + + + Output only those record types automatically managed by + dnssec-signzone, i.e. RRSIG, NSEC, + NSEC3 and NSEC3PARAM records. If smart signing + () is used, DNSKEY records are also + included. The resulting file can be included in the original + zone file with $INCLUDE. This option + cannot be combined with or serial + number updating. + + + + -E engine @@ -237,14 +258,41 @@ + + -X extended end-time + + + Specify the date and time when the generated RRSIG records + for the DNSKEY RRset will expire. This is to be used in cases + when the DNSKEY signatures need to persist longer than + signatures on other records; e.g., when the private component + of the KSK is kept offline and the KSK signature is to be + refreshed manually. + + + As with , an absolute + time is indicated in YYYYMMDDHHMMSS notation. A time relative + to the start time is indicated with +N, which is N seconds from + the start time. A time relative to the current time is + indicated with now+N. If no is + specified, the value of is used as + the default. (, in turn, defaults to + 30 days from the start time.) + must be later than . + + + + -f output-file The name of the output file containing the signed zone. The default is to append .signed to - the - input filename. + the input filename. If is + set to "-", then the signed zone is + written to the standard output, with a default output + format of "full". @@ -324,6 +372,17 @@ + + -L serial + + + When writing a signed zone to 'raw' format, set the "source serial" + value in the header to the specified serial number. (This is + expected to be used primarily for testing purposes.) + + + + -n ncpus @@ -388,7 +447,15 @@ The format of the output file containing the signed zone. Possible formats are "text" (default) - and "raw". + "full", which is text output in a + format suitable for processing by external scripts, + and "raw" or "raw=N", + which store the zone in a binary format for rapid loading + by named. "raw=N" + specifies the format version of the raw zone file: if N + is 0, the raw file can be read by any version of + named; if N is 1, the file can be + read by release 9.9.0 or higher. The default is 1. @@ -421,6 +488,24 @@ + + -R + + + Remove signatures from keys that no longer exist. + + + Normally, when a previously-signed zone is passed as input + to the signer, and a DNSKEY record has been removed and + replaced with a new one, signatures from the old key + that are still within their validity period are retained. + This allows the zone to continue to validate with cached + copies of the old DNSKEY RRset. The forces + dnssec-signzone to remove all orphaned + signatures. + + + -r randomdev @@ -508,15 +593,17 @@ -T ttl - Specifies the TTL to be used for new DNSKEY records imported - into the zone from the key repository. If not specified, - the default is the minimum TTL value from the zone's SOA + Specifies a TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not + specified, the default is the TTL value from the zone's SOA record. This option is ignored when signing without , since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match - them. + them, or if any of the imported DNSKEY records had a default + TTL value. In the event of a a conflict between TTL values in + imported keys, the shortest one is used. diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.html b/contrib/bind9/bin/dnssec/dnssec-signzone.html index 82185c6477d5..37994539b605 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.html +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.html @@ -1,5 +1,5 @@ + + + + + April 12, 2012 + + + + dnssec-verify + 8 + BIND9 + + + + dnssec-verify + DNSSEC zone verification tool + + + + + 2012 + Internet Systems Consortium, Inc. ("ISC") + + + + + + dnssec-verify + + + + + + + + zonefile + + + + + DESCRIPTION + dnssec-verify + verifies that a zone is fully signed for each algorithm found + in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 + chains are complete. + + + + + OPTIONS + + + + -c class + + + Specifies the DNS class of the zone. + + + + + + -I input-format + + + The format of the input zone file. + Possible formats are "text" (default) + and "raw". + This option is primarily intended to be used for dynamic + signed zones so that the dumped zone file in a non-text + format containing updates can be verified independently. + The use of this option does not make much sense for + non-dynamic zones. + + + + + + -o origin + + + The zone origin. If not specified, the name of the zone file + is assumed to be the origin. + + + + + + -v level + + + Sets the debugging level. + + + + + + -x + + + Only verify that the DNSKEY RRset is signed with key-signing + keys. Without this flag, it is assumed that the DNSKEY RRset + will be signed by all active keys. When this flag is set, + it will not be an error if the DNSKEY RRset is not signed + by zone-signing keys. This corresponds to the + option in dnssec-signzone. + + + + + + -z + + + Ignore the KSK flag on the keys when determining whether + the zone if correctly signed. Without this flag it is + assumed that there will be a non-revoked, self-signed + DNSKEY with the KSK flag set for each algorithm and + that RRsets other than DNSKEY RRset will be signed with + a different DNSKEY without the KSK flag set. + + + With this flag set, we only require that for each algorithm, + there will be at least one non-revoked, self-signed DNSKEY, + regardless of the KSK flag state, and that other RRsets + will be signed by a non-revoked key for the same algorithm + that includes the self-signed key; the same key may be used + for both purposes. This corresponds to the + option in dnssec-signzone. + + + + + + zonefile + + + The file containing the zone to be signed. + + + + + + + + + SEE ALSO + + + dnssec-signzone8 + , + BIND 9 Administrator Reference Manual, + RFC 4033. + + + + + AUTHOR + Internet Systems Consortium + + + + diff --git a/contrib/bind9/bin/dnssec/dnssec-verify.html b/contrib/bind9/bin/dnssec/dnssec-verify.html new file mode 100644 index 000000000000..135556f51001 --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-verify.html @@ -0,0 +1,117 @@ + + + + + +dnssec-verify + + +
+
+
+

Name

+

dnssec-verify — DNSSEC zone verification tool

+
+
+

Synopsis

+

dnssec-verify [-c class] [-E engine] [-I input-format] [-o origin] [-v level] [-x] [-z] {zonefile}

+
+
+

DESCRIPTION

+

dnssec-verify + verifies that a zone is fully signed for each algorithm found + in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 + chains are complete. +

+
+
+

OPTIONS

+
+
-c class
+

+ Specifies the DNS class of the zone. +

+
-I input-format
+

+ The format of the input zone file. + Possible formats are "text" (default) + and "raw". + This option is primarily intended to be used for dynamic + signed zones so that the dumped zone file in a non-text + format containing updates can be verified independently. + The use of this option does not make much sense for + non-dynamic zones. +

+
-o origin
+

+ The zone origin. If not specified, the name of the zone file + is assumed to be the origin. +

+
-v level
+

+ Sets the debugging level. +

+
-x
+

+ Only verify that the DNSKEY RRset is signed with key-signing + keys. Without this flag, it is assumed that the DNSKEY RRset + will be signed by all active keys. When this flag is set, + it will not be an error if the DNSKEY RRset is not signed + by zone-signing keys. This corresponds to the -x + option in dnssec-signzone. +

+
-z
+
+

+ Ignore the KSK flag on the keys when determining whether + the zone if correctly signed. Without this flag it is + assumed that there will be a non-revoked, self-signed + DNSKEY with the KSK flag set for each algorithm and + that RRsets other than DNSKEY RRset will be signed with + a different DNSKEY without the KSK flag set. +

+

+ With this flag set, we only require that for each algorithm, + there will be at least one non-revoked, self-signed DNSKEY, + regardless of the KSK flag state, and that other RRsets + will be signed by a non-revoked key for the same algorithm + that includes the self-signed key; the same key may be used + for both purposes. This corresponds to the -z + option in dnssec-signzone. +

+
+
zonefile
+

+ The file containing the zone to be signed. +

+
+
+
+

SEE ALSO

+

+ dnssec-signzone(8), + BIND 9 Administrator Reference Manual, + RFC 4033. +

+
+
+

AUTHOR

+

Internet Systems Consortium +

+
+
+ diff --git a/contrib/bind9/bin/dnssec/dnssectool.c b/contrib/bind9/bin/dnssec/dnssectool.c index 882b042f1b8e..7c8c6ce2254a 100644 --- a/contrib/bind9/bin/dnssec/dnssectool.c +++ b/contrib/bind9/bin/dnssec/dnssectool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.c,v 1.60.162.3 2011/10/21 03:56:32 marka Exp $ */ +/* $Id: dnssectool.c,v 1.63 2011/10/21 03:55:33 marka Exp $ */ /*! \file */ @@ -27,9 +27,11 @@ #include +#include #include #include #include +#include #include #include #include @@ -37,12 +39,19 @@ #include #include +#include +#include #include +#include #include #include #include +#include +#include #include #include +#include +#include #include #include #include @@ -50,6 +59,18 @@ #include "dnssectool.h" +static isc_heap_t *expected_chains, *found_chains; + +struct nsec3_chain_fixed { + isc_uint8_t hash; + isc_uint8_t salt_length; + isc_uint8_t next_length; + isc_uint16_t iterations; + /* unsigned char salt[0]; */ + /* unsigned char owner[0]; */ + /* unsigned char next[0]; */ +}; + extern int verbose; extern const char *program; @@ -467,3 +488,1314 @@ key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, return (conflict); } + +isc_boolean_t +is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) +{ + dns_rdataset_t nsset; + isc_result_t result; + + if (dns_name_equal(name, origin)) + return (ISC_FALSE); + + dns_rdataset_init(&nsset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns, + 0, 0, &nsset, NULL); + if (dns_rdataset_isassociated(&nsset)) { + if (ttlp != NULL) + *ttlp = nsset.ttl; + dns_rdataset_disassociate(&nsset); + } + + return (ISC_TF(result == ISC_R_SUCCESS)); +} + +static isc_boolean_t +goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name, + dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx) +{ + dns_rdata_dnskey_t key; + dns_rdata_rrsig_t sig; + dst_key_t *dstkey = NULL; + isc_result_t result; + + result = dns_rdata_tostruct(sigrdata, &sig, NULL); + check_result(result, "dns_rdata_tostruct()"); + + for (result = dns_rdataset_first(keyrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(keyrdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(keyrdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &key, NULL); + check_result(result, "dns_rdata_tostruct()"); + result = dns_dnssec_keyfromrdata(origin, &rdata, mctx, + &dstkey); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + if (sig.algorithm != key.algorithm || + sig.keyid != dst_key_id(dstkey) || + !dns_name_equal(&sig.signer, origin)) { + dst_key_free(&dstkey); + continue; + } + result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE, + mctx, sigrdata); + dst_key_free(&dstkey); + if (result == ISC_R_SUCCESS) + return(ISC_TRUE); + } + return (ISC_FALSE); +} + +static isc_result_t +verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_dbnode_t *node, dns_name_t *nextname) +{ + unsigned char buffer[DNS_NSEC_BUFFERSIZE]; + char namebuf[DNS_NAME_FORMATSIZE]; + char nextbuf[DNS_NAME_FORMATSIZE]; + char found[DNS_NAME_FORMATSIZE]; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t tmprdata = DNS_RDATA_INIT; + dns_rdata_nsec_t nsec; + isc_result_t result; + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) { + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "Missing NSEC record for %s\n", namebuf); + goto failure; + } + + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first()"); + + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec, NULL); + check_result(result, "dns_rdata_tostruct()"); + /* Check bit next name is consistent */ + if (!dns_name_equal(&nsec.next, nextname)) { + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_name_format(nextname, nextbuf, sizeof(nextbuf)); + dns_name_format(&nsec.next, found, sizeof(found)); + fprintf(stderr, "Bad NSEC record for %s, next name " + "mismatch (expected:%s, found:%s)\n", namebuf, + nextbuf, found); + goto failure; + } + /* Check bit map is consistent */ + result = dns_nsec_buildrdata(db, ver, node, nextname, buffer, + &tmprdata); + check_result(result, "dns_nsec_buildrdata()"); + if (dns_rdata_compare(&rdata, &tmprdata) != 0) { + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "Bad NSEC record for %s, bit map " + "mismatch\n", namebuf); + goto failure; + } + result = dns_rdataset_next(&rdataset); + if (result != ISC_R_NOMORE) { + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "Multipe NSEC records for %s\n", namebuf); + goto failure; + + } + dns_rdataset_disassociate(&rdataset); + return (ISC_R_SUCCESS); + failure: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + return (ISC_R_FAILURE); +} + +static void +check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset, + dns_name_t *name, dns_dbnode_t *node) +{ + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[80]; + dns_rdataset_t sigrdataset; + dns_rdatasetiter_t *rdsiter = NULL; + isc_result_t result; + + dns_rdataset_init(&sigrdataset); + result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, &sigrdataset); + if (sigrdataset.type == dns_rdatatype_rrsig && + sigrdataset.covers == rdataset->type) + break; + dns_rdataset_disassociate(&sigrdataset); + } + if (result == ISC_R_SUCCESS) { + dns_name_format(name, namebuf, sizeof(namebuf)); + type_format(rdataset->type, typebuf, sizeof(typebuf)); + fprintf(stderr, "Warning: Found unexpected signatures for " + "%s/%s\n", namebuf, typebuf); + } + if (dns_rdataset_isassociated(&sigrdataset)) + dns_rdataset_disassociate(&sigrdataset); + dns_rdatasetiter_destroy(&rdsiter); +} + +static isc_boolean_t +chain_compare(void *arg1, void *arg2) { + struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2; + size_t len; + + /* + * Do each element in turn to get a stable sort. + */ + if (e1->hash < e2->hash) + return (ISC_TRUE); + if (e1->hash > e2->hash) + return (ISC_FALSE); + if (e1->iterations < e2->iterations) + return (ISC_TRUE); + if (e1->iterations > e2->iterations) + return (ISC_FALSE); + if (e1->salt_length < e2->salt_length) + return (ISC_TRUE); + if (e1->salt_length > e2->salt_length) + return (ISC_FALSE); + if (e1->next_length < e2->next_length) + return (ISC_TRUE); + if (e1->next_length > e2->next_length) + return (ISC_FALSE); + len = e1->salt_length + 2 * e1->next_length; + if (memcmp(e1 + 1, e2 + 1, len) < 0) + return (ISC_TRUE); + return (ISC_FALSE); +} + +static isc_boolean_t +chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) { + size_t len; + + if (e1->hash != e2->hash) + return (ISC_FALSE); + if (e1->iterations != e2->iterations) + return (ISC_FALSE); + if (e1->salt_length != e2->salt_length) + return (ISC_FALSE); + if (e1->next_length != e2->next_length) + return (ISC_FALSE); + len = e1->salt_length + 2 * e1->next_length; + if (memcmp(e1 + 1, e2 + 1, len) != 0) + return (ISC_FALSE); + return (ISC_TRUE); +} + +static isc_result_t +record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3, + isc_mem_t *mctx, isc_heap_t *chains) +{ + struct nsec3_chain_fixed *element; + size_t len; + unsigned char *cp; + isc_result_t result; + + len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length; + + element = isc_mem_get(mctx, len); + if (element == NULL) + return (ISC_R_NOMEMORY); + memset(element, 0, len); + element->hash = nsec3->hash; + element->salt_length = nsec3->salt_length; + element->next_length = nsec3->next_length; + element->iterations = nsec3->iterations; + cp = (unsigned char *)(element + 1); + memcpy(cp, nsec3->salt, nsec3->salt_length); + cp += nsec3->salt_length; + memcpy(cp, rawhash, nsec3->next_length); + cp += nsec3->next_length; + memcpy(cp, nsec3->next, nsec3->next_length); + result = isc_heap_insert(chains, element); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "isc_heap_insert failed: %s\n", + isc_result_totext(result)); + isc_mem_put(mctx, element, len); + } + return (result); +} + +static isc_result_t +match_nsec3(dns_name_t *name, isc_mem_t *mctx, + dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset, + unsigned char types[8192], unsigned int maxtype, + unsigned char *rawhash, size_t rhsize) +{ + unsigned char cbm[8244]; + char namebuf[DNS_NAME_FORMATSIZE]; + dns_rdata_nsec3_t nsec3; + isc_result_t result; + unsigned int len; + + /* + * Find matching NSEC3 record. + */ + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct()"); + if (nsec3.hash == nsec3param->hash && + nsec3.next_length == rhsize && + nsec3.iterations == nsec3param->iterations && + nsec3.salt_length == nsec3param->salt_length && + memcmp(nsec3.salt, nsec3param->salt, + nsec3param->salt_length) == 0) + break; + } + if (result != ISC_R_SUCCESS) { + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf); + return (result); + } + + /* + * Check the type list. + */ + len = dns_nsec_compressbitmap(cbm, types, maxtype); + if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) { + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "Bad NSEC3 record for %s, bit map " + "mismatch\n", namebuf); + return (ISC_R_FAILURE); + } + + /* + * Record chain. + */ + result = record_nsec3(rawhash, &nsec3, mctx, expected_chains); + check_result(result, "record_nsec3()"); + + /* + * Make sure there is only one NSEC3 record with this set of + * parameters. + */ + for (result = dns_rdataset_next(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct()"); + if (nsec3.hash == nsec3param->hash && + nsec3.iterations == nsec3param->iterations && + nsec3.salt_length == nsec3param->salt_length && + memcmp(nsec3.salt, nsec3param->salt, + nsec3.salt_length) == 0) { + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "Multiple NSEC3 records with the " + "same parameter set for %s", namebuf); + result = DNS_R_DUPLICATE; + break; + } + } + if (result != ISC_R_NOMORE) + return (result); + + result = ISC_R_SUCCESS; + return (result); +} + +static isc_boolean_t +innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) { + dns_rdata_nsec3param_t nsec3param; + isc_result_t result; + + for (result = dns_rdataset_first(nsec3paramset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(nsec3paramset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(nsec3paramset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); + check_result(result, "dns_rdata_tostruct()"); + if (nsec3param.flags == 0 && + nsec3param.hash == nsec3->hash && + nsec3param.iterations == nsec3->iterations && + nsec3param.salt_length == nsec3->salt_length && + memcmp(nsec3param.salt, nsec3->salt, + nsec3->salt_length) == 0) + return (ISC_TRUE); + } + return (ISC_FALSE); +} + +static isc_result_t +record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, + dns_name_t *name, dns_dbnode_t *node, + dns_rdataset_t *nsec3paramset) +{ + unsigned char owner[NSEC3_MAX_HASH_LENGTH]; + dns_rdata_nsec3_t nsec3; + dns_rdataset_t rdataset; + dns_label_t hashlabel; + isc_buffer_t b; + isc_result_t result; + + if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset)) + return (ISC_R_SUCCESS); + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + return (ISC_R_SUCCESS); + + dns_name_getlabel(name, 0, &hashlabel); + isc_region_consume(&hashlabel, 1); + isc_buffer_init(&b, owner, sizeof(owner)); + result = isc_base32hex_decoderegion(&hashlabel, &b); + if (result != ISC_R_SUCCESS) + goto cleanup; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct()"); + if (nsec3.next_length != isc_buffer_usedlength(&b)) + continue; + /* + * We only care about NSEC3 records that match a NSEC3PARAM + * record. + */ + if (!innsec3params(&nsec3, nsec3paramset)) + continue; + + /* + * Record chain. + */ + result = record_nsec3(owner, &nsec3, mctx, found_chains); + check_result(result, "record_nsec3()"); + } + + cleanup: + dns_rdataset_disassociate(&rdataset); + return (ISC_R_SUCCESS); +} + +static isc_boolean_t +isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + dns_rdata_t *nsec3rdata) +{ + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3_t nsec3; + dns_rdata_nsec3param_t nsec3param; + dns_fixedname_t fixed; + dns_name_t *hashname; + isc_result_t result; + dns_dbnode_t *node = NULL; + unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; + size_t rhsize = sizeof(rawhash); + isc_boolean_t ret; + + result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL); + check_result(result, "dns_rdata_tostruct()"); + + dns_fixedname_init(&fixed); + result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin, + nsec3param.hash, nsec3param.iterations, + nsec3param.salt, nsec3param.salt_length); + check_result(result, "dns_nsec3_hashname()"); + + dns_rdataset_init(&rdataset); + hashname = dns_fixedname_name(&fixed); + result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node); + if (result == ISC_R_SUCCESS) + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first()"); + + dns_rdataset_current(&rdataset, &rdata); + + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + if (result != ISC_R_SUCCESS) + ret = ISC_FALSE; + else + ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); + + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + + return (ret); +} + +static isc_result_t +verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata, + isc_boolean_t delegation, isc_boolean_t empty, + unsigned char types[8192], unsigned int maxtype) +{ + char namebuf[DNS_NAME_FORMATSIZE]; + char hashbuf[DNS_NAME_FORMATSIZE]; + dns_rdataset_t rdataset; + dns_rdata_nsec3param_t nsec3param; + dns_fixedname_t fixed; + dns_name_t *hashname; + isc_result_t result; + dns_dbnode_t *node = NULL; + unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; + size_t rhsize = sizeof(rawhash); + isc_boolean_t optout; + + result = dns_rdata_tostruct(rdata, &nsec3param, NULL); + check_result(result, "dns_rdata_tostruct()"); + + if (nsec3param.flags != 0) + return (ISC_R_SUCCESS); + + if (!dns_nsec3_supportedhash(nsec3param.hash)) + return (ISC_R_SUCCESS); + + optout = isoptout(db, ver, origin, rdata); + + dns_fixedname_init(&fixed); + result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin, + nsec3param.hash, nsec3param.iterations, + nsec3param.salt, nsec3param.salt_length); + check_result(result, "dns_nsec3_hashname()"); + + /* + * We don't use dns_db_find() here as it works with the choosen + * nsec3 chain and we may also be called with uncommitted data + * from dnssec-signzone so the secure status of the zone may not + * be up to date. + */ + dns_rdataset_init(&rdataset); + hashname = dns_fixedname_name(&fixed); + result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node); + if (result == ISC_R_SUCCESS) + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS && + (!delegation || (empty && !optout) || + (!empty && dns_nsec_isset(types, dns_rdatatype_ds)))) + { + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_name_format(hashname, hashbuf, sizeof(hashbuf)); + fprintf(stderr, "Missing NSEC3 record for %s (%s)\n", + namebuf, hashbuf); + } else if (result == ISC_R_NOTFOUND && + delegation && (!empty || optout)) + { + result = ISC_R_SUCCESS; + } else if (result == ISC_R_SUCCESS) { + result = match_nsec3(name, mctx, &nsec3param, &rdataset, + types, maxtype, rawhash, rhsize); + } + + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + + return (result); +} + +static isc_result_t +verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset, + isc_boolean_t delegation, isc_boolean_t empty, + unsigned char types[8192], unsigned int maxtype) +{ + isc_result_t result; + + for (result = dns_rdataset_first(nsec3paramset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(nsec3paramset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(nsec3paramset, &rdata); + result = verifynsec3(db, ver, origin, mctx, name, &rdata, + delegation, empty, types, maxtype); + if (result != ISC_R_SUCCESS) + break; + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + return (result); +} + +static void +verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name, + dns_dbnode_t *node, dns_rdataset_t *keyrdataset, + unsigned char *act_algorithms, unsigned char *bad_algorithms) +{ + unsigned char set_algorithms[256]; + char namebuf[DNS_NAME_FORMATSIZE]; + char algbuf[80]; + char typebuf[80]; + dns_rdataset_t sigrdataset; + dns_rdatasetiter_t *rdsiter = NULL; + isc_result_t result; + int i; + + dns_rdataset_init(&sigrdataset); + result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, &sigrdataset); + if (sigrdataset.type == dns_rdatatype_rrsig && + sigrdataset.covers == rdataset->type) + break; + dns_rdataset_disassociate(&sigrdataset); + } + if (result != ISC_R_SUCCESS) { + dns_name_format(name, namebuf, sizeof(namebuf)); + type_format(rdataset->type, typebuf, sizeof(typebuf)); + fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf); + for (i = 0; i < 256; i++) + if (act_algorithms[i] != 0) + bad_algorithms[i] = 1; + dns_rdatasetiter_destroy(&rdsiter); + return; + } + + memset(set_algorithms, 0, sizeof(set_algorithms)); + for (result = dns_rdataset_first(&sigrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&sigrdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_rrsig_t sig; + + dns_rdataset_current(&sigrdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &sig, NULL); + check_result(result, "dns_rdata_tostruct()"); + if (rdataset->ttl != sig.originalttl) { + dns_name_format(name, namebuf, sizeof(namebuf)); + type_format(rdataset->type, typebuf, sizeof(typebuf)); + fprintf(stderr, "TTL mismatch for %s %s keytag %u\n", + namebuf, typebuf, sig.keyid); + continue; + } + if ((set_algorithms[sig.algorithm] != 0) || + (act_algorithms[sig.algorithm] == 0)) + continue; + if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx)) + set_algorithms[sig.algorithm] = 1; + } + dns_rdatasetiter_destroy(&rdsiter); + if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) { + dns_name_format(name, namebuf, sizeof(namebuf)); + type_format(rdataset->type, typebuf, sizeof(typebuf)); + for (i = 0; i < 256; i++) + if ((act_algorithms[i] != 0) && + (set_algorithms[i] == 0)) { + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "No correct %s signature for " + "%s %s\n", algbuf, namebuf, typebuf); + bad_algorithms[i] = 1; + } + } + dns_rdataset_disassociate(&sigrdataset); +} + +static isc_result_t +verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node, + isc_boolean_t delegation, dns_rdataset_t *keyrdataset, + unsigned char *act_algorithms, unsigned char *bad_algorithms, + dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset, + dns_name_t *nextname) +{ + unsigned char types[8192]; + unsigned int maxtype = 0; + dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL; + isc_result_t result, tresult; + + memset(types, 0, sizeof(types)); + result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + result = dns_rdatasetiter_first(rdsiter); + dns_rdataset_init(&rdataset); + while (result == ISC_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, &rdataset); + /* + * If we are not at a delegation then everything should be + * signed. If we are at a delegation then only the DS set + * is signed. The NS set is not signed at a delegation but + * its existance is recorded in the bit map. Anything else + * other than NSEC and DS is not signed at a delegation. + */ + if (rdataset.type != dns_rdatatype_rrsig && + rdataset.type != dns_rdatatype_dnskey && + (!delegation || rdataset.type == dns_rdatatype_ds || + rdataset.type == dns_rdatatype_nsec)) { + verifyset(db, ver, origin, mctx, &rdataset, + name, node, keyrdataset, + act_algorithms, bad_algorithms); + dns_nsec_setbit(types, rdataset.type, 1); + if (rdataset.type > maxtype) + maxtype = rdataset.type; + } else if (rdataset.type != dns_rdatatype_rrsig && + rdataset.type != dns_rdatatype_dnskey) { + if (rdataset.type == dns_rdatatype_ns) + dns_nsec_setbit(types, rdataset.type, 1); + check_no_rrsig(db, ver, &rdataset, name, node); + } else + dns_nsec_setbit(types, rdataset.type, 1); + dns_rdataset_disassociate(&rdataset); + result = dns_rdatasetiter_next(rdsiter); + } + if (result != ISC_R_NOMORE) + fatal("rdataset iteration failed: %s", + isc_result_totext(result)); + dns_rdatasetiter_destroy(&rdsiter); + + result = ISC_R_SUCCESS; + + if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) + result = verifynsec(db, ver, name, node, nextname); + + if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) { + tresult = verifynsec3s(db, ver, origin, mctx, name, + nsec3paramset, delegation, ISC_FALSE, + types, maxtype); + if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) + result = tresult; + } + return (result); +} + +static isc_boolean_t +is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) { + dns_rdatasetiter_t *rdsiter = NULL; + isc_result_t result; + + result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + result = dns_rdatasetiter_first(rdsiter); + dns_rdatasetiter_destroy(&rdsiter); + if (result == ISC_R_NOMORE) + return (ISC_TRUE); + return (ISC_FALSE); +} + +static void +check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db, + dns_dbversion_t *ver) +{ + dns_rdataset_t rdataset; + isc_result_t result; + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, + 0, 0, &rdataset, NULL); + if (result != ISC_R_NOTFOUND) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namebuf, sizeof(namebuf)); + fatal("unexpected NSEC RRset at %s\n", namebuf); + } + + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); +} + +static isc_boolean_t +newchain(const struct nsec3_chain_fixed *first, + const struct nsec3_chain_fixed *e) +{ + if (first->hash != e->hash || + first->iterations != e->iterations || + first->salt_length != e->salt_length || + first->next_length != e->next_length || + memcmp(first + 1, e + 1, first->salt_length) != 0) + return (ISC_TRUE); + return (ISC_FALSE); +} + +static void +free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) { + size_t len; + + len = sizeof(*e) + e->salt_length + 2 * e->next_length; + isc_mem_put(mctx, e, len); +} + +static isc_boolean_t +checknext(const struct nsec3_chain_fixed *first, + const struct nsec3_chain_fixed *e) +{ + char buf[512]; + const unsigned char *d1 = (const unsigned char *)(first + 1); + const unsigned char *d2 = (const unsigned char *)(e + 1); + isc_buffer_t b; + isc_region_t sr; + + d1 += first->salt_length + first->next_length; + d2 += e->salt_length; + + if (memcmp(d1, d2, first->next_length) == 0) + return (ISC_TRUE); + + DE_CONST(d1 - first->next_length, sr.base); + sr.length = first->next_length; + isc_buffer_init(&b, buf, sizeof(buf)); + isc_base32hex_totext(&sr, 1, "", &b); + fprintf(stderr, "Break in NSEC3 chain at: %.*s\n", + (int) isc_buffer_usedlength(&b), buf); + + DE_CONST(d1, sr.base); + sr.length = first->next_length; + isc_buffer_init(&b, buf, sizeof(buf)); + isc_base32hex_totext(&sr, 1, "", &b); + fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b), + buf); + + DE_CONST(d2, sr.base); + sr.length = first->next_length; + isc_buffer_init(&b, buf, sizeof(buf)); + isc_base32hex_totext(&sr, 1, "", &b); + fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf); + + return (ISC_FALSE); +} + +#define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n" + +static isc_result_t +verify_nsec3_chains(isc_mem_t *mctx) { + isc_result_t result = ISC_R_SUCCESS; + struct nsec3_chain_fixed *e, *f = NULL; + struct nsec3_chain_fixed *first = NULL, *prev = NULL; + + while ((e = isc_heap_element(expected_chains, 1)) != NULL) { + isc_heap_delete(expected_chains, 1); + if (f == NULL) + f = isc_heap_element(found_chains, 1); + if (f != NULL) { + isc_heap_delete(found_chains, 1); + + /* + * Check that they match. + */ + if (chain_equal(e, f)) { + free_element(mctx, f); + f = NULL; + } else { + if (result == ISC_R_SUCCESS) + fprintf(stderr, EXPECTEDANDFOUND); + result = ISC_R_FAILURE; + /* + * Attempt to resync found_chain. + */ + while (f != NULL && !chain_compare(e, f)) { + free_element(mctx, f); + f = isc_heap_element(found_chains, 1); + if (f != NULL) + isc_heap_delete(found_chains, 1); + if (f != NULL && chain_equal(e, f)) { + free_element(mctx, f); + f = NULL; + break; + } + } + } + } else if (result == ISC_R_SUCCESS) { + fprintf(stderr, EXPECTEDANDFOUND); + result = ISC_R_FAILURE; + } + if (first == NULL || newchain(first, e)) { + if (prev != NULL) { + if (!checknext(prev, first)) + result = ISC_R_FAILURE; + if (prev != first) + free_element(mctx, prev); + } + if (first != NULL) + free_element(mctx, first); + prev = first = e; + continue; + } + if (!checknext(prev, e)) + result = ISC_R_FAILURE; + if (prev != first) + free_element(mctx, prev); + prev = e; + } + if (prev != NULL) { + if (!checknext(prev, first)) + result = ISC_R_FAILURE; + if (prev != first) + free_element(mctx, prev); + } + if (first != NULL) + free_element(mctx, first); + do { + if (f != NULL) { + if (result == ISC_R_SUCCESS) { + fprintf(stderr, EXPECTEDANDFOUND); + result = ISC_R_FAILURE; + } + free_element(mctx, f); + } + f = isc_heap_element(found_chains, 1); + if (f != NULL) + isc_heap_delete(found_chains, 1); + } while (f != NULL); + + return (result); +} + +static isc_result_t +verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname, + isc_boolean_t isdelegation, dns_rdataset_t *nsec3paramset) +{ + dns_namereln_t reln; + int order; + unsigned int labels, nlabels, i; + dns_name_t suffix; + isc_result_t result = ISC_R_SUCCESS, tresult; + + reln = dns_name_fullcompare(prevname, name, &order, &labels); + if (order >= 0) + return (result); + + nlabels = dns_name_countlabels(name); + + if (reln == dns_namereln_commonancestor || + reln == dns_namereln_contains) { + dns_name_init(&suffix, NULL); + for (i = labels + 1; i < nlabels; i++) { + dns_name_getlabelsequence(name, nlabels - i, i, + &suffix); + if (nsec3paramset != NULL && + dns_rdataset_isassociated(nsec3paramset)) { + tresult = verifynsec3s(db, ver, origin, mctx, + &suffix, nsec3paramset, + isdelegation, ISC_TRUE, + NULL, 0); + if (result == ISC_R_SUCCESS && + tresult != ISC_R_SUCCESS) + result = tresult; + } + } + } + return (result); +} + +/*% + * Verify that certain things are sane: + * + * The apex has a DNSKEY record with at least one KSK, and at least + * one ZSK if the -x flag was not used. + * + * The DNSKEY record was signed with at least one of the KSKs in this + * set. + * + * The rest of the zone was signed with at least one of the ZSKs + * present in the DNSKEY RRSET. + */ +void +verifyzone(dns_db_t *db, dns_dbversion_t *ver, + dns_name_t *origin, isc_mem_t *mctx, + isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly) +{ + char algbuf[80]; + dns_dbiterator_t *dbiter = NULL; + dns_dbnode_t *node = NULL, *nextnode = NULL; + dns_fixedname_t fname, fnextname, fprevname, fzonecut; + dns_name_t *name, *nextname, *prevname, *zonecut; + dns_rdata_dnskey_t dnskey; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t keyset, soaset; + dns_rdataset_t keysigs, soasigs; + dns_rdataset_t nsecset, nsecsigs; + dns_rdataset_t nsec3paramset, nsec3paramsigs; + int i; + isc_boolean_t done = ISC_FALSE; + isc_boolean_t first = ISC_TRUE; + isc_boolean_t goodksk = ISC_FALSE; + isc_boolean_t goodzsk = ISC_FALSE; + isc_result_t result, vresult = ISC_R_UNSET; + unsigned char revoked_ksk[256]; + unsigned char revoked_zsk[256]; + unsigned char standby_ksk[256]; + unsigned char standby_zsk[256]; + unsigned char ksk_algorithms[256]; + unsigned char zsk_algorithms[256]; + unsigned char bad_algorithms[256]; + unsigned char act_algorithms[256]; + + result = isc_heap_create(mctx, chain_compare, NULL, 1024, + &expected_chains); + check_result(result, "isc_heap_create()"); + result = isc_heap_create(mctx, chain_compare, NULL, 1024, + &found_chains); + check_result(result, "isc_heap_create()"); + + result = dns_db_findnode(db, origin, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + fatal("failed to find the zone's origin: %s", + isc_result_totext(result)); + + dns_rdataset_init(&keyset); + dns_rdataset_init(&keysigs); + dns_rdataset_init(&soaset); + dns_rdataset_init(&soasigs); + dns_rdataset_init(&nsecset); + dns_rdataset_init(&nsecsigs); + dns_rdataset_init(&nsec3paramset); + dns_rdataset_init(&nsec3paramsigs); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, + 0, 0, &keyset, &keysigs); + if (result != ISC_R_SUCCESS) + fatal("Zone contains no DNSSEC keys\n"); + + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, + 0, 0, &soaset, &soasigs); + if (result != ISC_R_SUCCESS) + fatal("Zone contains no SOA record\n"); + + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, + 0, 0, &nsecset, &nsecsigs); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + fatal("NSEC lookup failed\n"); + + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, + 0, 0, &nsec3paramset, &nsec3paramsigs); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + fatal("NSEC3PARAM lookup failed\n"); + + if (!dns_rdataset_isassociated(&keysigs)) + fatal("DNSKEY is not signed (keys offline or inactive?)\n"); + + if (!dns_rdataset_isassociated(&soasigs)) + fatal("SOA is not signed (keys offline or inactive?)\n"); + + if (dns_rdataset_isassociated(&nsecset) && + !dns_rdataset_isassociated(&nsecsigs)) + fatal("NSEC is not signed (keys offline or inactive?)\n"); + + if (dns_rdataset_isassociated(&nsec3paramset) && + !dns_rdataset_isassociated(&nsec3paramsigs)) + fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n"); + + if (!dns_rdataset_isassociated(&nsecset) && + !dns_rdataset_isassociated(&nsec3paramset)) + fatal("No valid NSEC/NSEC3 chain for testing\n"); + + dns_db_detachnode(db, &node); + + memset(revoked_ksk, 0, sizeof(revoked_ksk)); + memset(revoked_zsk, 0, sizeof(revoked_zsk)); + memset(standby_ksk, 0, sizeof(standby_ksk)); + memset(standby_zsk, 0, sizeof(standby_zsk)); + memset(ksk_algorithms, 0, sizeof(ksk_algorithms)); + memset(zsk_algorithms, 0, sizeof(zsk_algorithms)); + memset(bad_algorithms, 0, sizeof(bad_algorithms)); + memset(act_algorithms, 0, sizeof(act_algorithms)); + + /* + * Check that the DNSKEY RR has at least one self signing KSK + * and one ZSK per algorithm in it (or, if -x was used, one + * self-signing KSK). + */ + for (result = dns_rdataset_first(&keyset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&keyset)) { + dns_rdataset_current(&keyset, &rdata); + result = dns_rdata_tostruct(&rdata, &dnskey, NULL); + check_result(result, "dns_rdata_tostruct"); + + if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0) + ; + else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) { + if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && + !dns_dnssec_selfsigns(&rdata, origin, &keyset, + &keysigs, ISC_FALSE, + mctx)) { + char namebuf[DNS_NAME_FORMATSIZE]; + char buffer[1024]; + isc_buffer_t buf; + + dns_name_format(origin, namebuf, + sizeof(namebuf)); + isc_buffer_init(&buf, buffer, sizeof(buffer)); + result = dns_rdata_totext(&rdata, NULL, &buf); + check_result(result, "dns_rdata_totext"); + fatal("revoked KSK is not self signed:\n" + "%s DNSKEY %.*s", namebuf, + (int)isc_buffer_usedlength(&buf), buffer); + } + if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && + revoked_ksk[dnskey.algorithm] != 255) + revoked_ksk[dnskey.algorithm]++; + else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && + revoked_zsk[dnskey.algorithm] != 255) + revoked_zsk[dnskey.algorithm]++; + } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) { + if (dns_dnssec_selfsigns(&rdata, origin, &keyset, + &keysigs, ISC_FALSE, mctx)) { + if (ksk_algorithms[dnskey.algorithm] != 255) + ksk_algorithms[dnskey.algorithm]++; + goodksk = ISC_TRUE; + } else { + if (standby_ksk[dnskey.algorithm] != 255) + standby_ksk[dnskey.algorithm]++; + } + } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset, + &keysigs, ISC_FALSE, mctx)) { + if (zsk_algorithms[dnskey.algorithm] != 255) + zsk_algorithms[dnskey.algorithm]++; + goodzsk = ISC_TRUE; + } else if (dns_dnssec_signs(&rdata, origin, &soaset, + &soasigs, ISC_FALSE, mctx)) { + if (zsk_algorithms[dnskey.algorithm] != 255) + zsk_algorithms[dnskey.algorithm]++; + } else { + if (standby_zsk[dnskey.algorithm] != 255) + standby_zsk[dnskey.algorithm]++; + } + dns_rdata_freestruct(&dnskey); + dns_rdata_reset(&rdata); + } + dns_rdataset_disassociate(&keysigs); + dns_rdataset_disassociate(&soaset); + dns_rdataset_disassociate(&soasigs); + if (dns_rdataset_isassociated(&nsecsigs)) + dns_rdataset_disassociate(&nsecsigs); + if (dns_rdataset_isassociated(&nsec3paramsigs)) + dns_rdataset_disassociate(&nsec3paramsigs); + + if (ignore_kskflag ) { + if (!goodksk && !goodzsk) + fatal("No self-signed DNSKEY found."); + } else if (!goodksk) + fatal("No self-signed KSK DNSKEY found. Supply an active\n" + "key with the KSK flag set, or use '-P'."); + + fprintf(stderr, "Verifying the zone using the following algorithms:"); + for (i = 0; i < 256; i++) { + if (ignore_kskflag) + act_algorithms[i] = (ksk_algorithms[i] != 0 || + zsk_algorithms[i] != 0) ? 1 : 0; + else + act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0; + if (act_algorithms[i] != 0) { + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, " %s", algbuf); + } + } + fprintf(stderr, ".\n"); + + if (!ignore_kskflag && !keyset_kskonly) { + for (i = 0; i < 256; i++) { + /* + * The counts should both be zero or both be non-zero. + * Mark the algorithm as bad if this is not met. + */ + if ((ksk_algorithms[i] != 0) == + (zsk_algorithms[i] != 0)) + continue; + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "Missing %s for algorithm %s\n", + (ksk_algorithms[i] != 0) + ? "ZSK" + : "self-signed KSK", + algbuf); + bad_algorithms[i] = 1; + } + } + + /* + * Check that all the other records were signed by keys that are + * present in the DNSKEY RRSET. + */ + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_fixedname_init(&fnextname); + nextname = dns_fixedname_name(&fnextname); + dns_fixedname_init(&fprevname); + prevname = NULL; + dns_fixedname_init(&fzonecut); + zonecut = NULL; + + result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter); + check_result(result, "dns_db_createiterator()"); + + result = dns_dbiterator_first(dbiter); + check_result(result, "dns_dbiterator_first()"); + + while (!done) { + isc_boolean_t isdelegation = ISC_FALSE; + + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + if (!dns_name_issubdomain(name, origin)) { + check_no_nsec(name, node, db, ver); + dns_db_detachnode(db, &node); + result = dns_dbiterator_next(dbiter); + if (result == ISC_R_NOMORE) + done = ISC_TRUE; + else + check_result(result, "dns_dbiterator_next()"); + continue; + } + if (is_delegation(db, ver, origin, name, node, NULL)) { + zonecut = dns_fixedname_name(&fzonecut); + dns_name_copy(name, zonecut, NULL); + isdelegation = ISC_TRUE; + } + nextnode = NULL; + result = dns_dbiterator_next(dbiter); + while (result == ISC_R_SUCCESS) { + result = dns_dbiterator_current(dbiter, &nextnode, + nextname); + check_dns_dbiterator_current(result); + if (!dns_name_issubdomain(nextname, origin) || + (zonecut != NULL && + dns_name_issubdomain(nextname, zonecut))) + { + check_no_nsec(nextname, nextnode, db, ver); + dns_db_detachnode(db, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + if (is_empty(db, ver, nextnode)) { + dns_db_detachnode(db, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + dns_db_detachnode(db, &nextnode); + break; + } + if (result == ISC_R_NOMORE) { + done = ISC_TRUE; + nextname = origin; + } else if (result != ISC_R_SUCCESS) + fatal("iterating through the database failed: %s", + isc_result_totext(result)); + result = verifynode(db, ver, origin, mctx, name, node, + isdelegation, &keyset, act_algorithms, + bad_algorithms, &nsecset, &nsec3paramset, + nextname); + if (vresult == ISC_R_UNSET) + vresult = ISC_R_SUCCESS; + if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS) + vresult = result; + if (prevname != NULL) { + result = verifyemptynodes(db, ver, origin, mctx, name, + prevname, isdelegation, + &nsec3paramset); + } else + prevname = dns_fixedname_name(&fprevname); + dns_name_copy(name, prevname, NULL); + if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS) + vresult = result; + dns_db_detachnode(db, &node); + } + + dns_dbiterator_destroy(&dbiter); + + result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter); + check_result(result, "dns_db_createiterator()"); + + for (result = dns_dbiterator_first(dbiter); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiter) ) { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + result = verifynode(db, ver, origin, mctx, name, node, + ISC_FALSE, &keyset, act_algorithms, + bad_algorithms, NULL, NULL, NULL); + check_result(result, "verifynode"); + record_found(db, ver, mctx, name, node, &nsec3paramset); + dns_db_detachnode(db, &node); + } + dns_dbiterator_destroy(&dbiter); + + dns_rdataset_disassociate(&keyset); + if (dns_rdataset_isassociated(&nsecset)) + dns_rdataset_disassociate(&nsecset); + if (dns_rdataset_isassociated(&nsec3paramset)) + dns_rdataset_disassociate(&nsec3paramset); + + result = verify_nsec3_chains(mctx); + if (vresult == ISC_R_UNSET) + vresult = ISC_R_SUCCESS; + if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) + vresult = result; + isc_heap_destroy(&expected_chains); + isc_heap_destroy(&found_chains); + + /* + * If we made it this far, we have what we consider a properly signed + * zone. Set the good flag. + */ + for (i = 0; i < 256; i++) { + if (bad_algorithms[i] != 0) { + if (first) + fprintf(stderr, "The zone is not fully signed " + "for the following algorithms:"); + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, " %s", algbuf); + first = ISC_FALSE; + } + } + if (!first) { + fprintf(stderr, ".\n"); + fatal("DNSSEC completeness test failed."); + } + + if (vresult != ISC_R_SUCCESS) + fatal("DNSSEC completeness test failed (%s).", + dns_result_totext(vresult)); + + if (goodksk || ignore_kskflag) { + /* + * Print the success summary. + */ + fprintf(stderr, "Zone fully signed:\n"); + for (i = 0; i < 256; i++) { + if ((ksk_algorithms[i] != 0) || + (standby_ksk[i] != 0) || + (revoked_zsk[i] != 0) || + (zsk_algorithms[i] != 0) || + (standby_zsk[i] != 0) || + (revoked_zsk[i] != 0)) { + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "Algorithm: %s: KSKs: " + "%u active, %u stand-by, %u revoked\n", + algbuf, ksk_algorithms[i], + standby_ksk[i], revoked_ksk[i]); + fprintf(stderr, "%*sZSKs: " + "%u active, %u %s, %u revoked\n", + (int) strlen(algbuf) + 13, "", + zsk_algorithms[i], + standby_zsk[i], + keyset_kskonly ? "present" : "stand-by", + revoked_zsk[i]); + } + } + } +} diff --git a/contrib/bind9/bin/dnssec/dnssectool.h b/contrib/bind9/bin/dnssec/dnssectool.h index e6dfe51aeed3..09b4fb103b13 100644 --- a/contrib/bind9/bin/dnssec/dnssectool.h +++ b/contrib/bind9/bin/dnssec/dnssectool.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007-2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.h,v 1.31.162.2 2011/10/20 23:46:27 tbox Exp $ */ +/* $Id: dnssectool.h,v 1.33 2011/10/20 23:46:51 tbox Exp $ */ #ifndef DNSSECTOOL_H #define DNSSECTOOL_H 1 @@ -25,6 +25,11 @@ #include #include +#define check_dns_dbiterator_current(result) \ + check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \ + "dns_dbiterator_current()") + + typedef void (fatalcallback_t)(void); ISC_PLATFORM_NORETURN_PRE void @@ -81,4 +86,12 @@ isc_boolean_t key_collision(dst_key_t *key, dns_name_t *name, const char *dir, isc_mem_t *mctx, isc_boolean_t *exact); +isc_boolean_t +is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp); + +void +verifyzone(dns_db_t *db, dns_dbversion_t *ver, + dns_name_t *origin, isc_mem_t *mctx, + isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly); #endif /* DNSSEC_DNSSECTOOL_H */ diff --git a/contrib/bind9/bin/named/Makefile.in b/contrib/bind9/bin/named/Makefile.in index e3ce3bd1547b..689413570378 100644 --- a/contrib/bind9/bin/named/Makefile.in +++ b/contrib/bind9/bin/named/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.114.14.2 2011/03/10 23:47:25 tbox Exp $ +# $Id: Makefile.in,v 1.116 2011/03/10 23:47:49 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -161,8 +161,11 @@ maintainer-clean:: bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h -depend: bind9.xsl.h -statschannel.@O@: bind9.xsl.h +bind9.ver3.xsl.h: bind9.ver3.xsl ${srcdir}/convertxsl.pl + ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.ver3.xsl > bind9.ver3.xsl.h + +depend: bind9.xsl.h bind9.ver3.xsl.h +statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} diff --git a/contrib/bind9/bin/named/bind9.ver3.xsl b/contrib/bind9/bin/named/bind9.ver3.xsl new file mode 100644 index 000000000000..22e5c45fbef4 --- /dev/null +++ b/contrib/bind9/bin/named/bind9.ver3.xsl @@ -0,0 +1,738 @@ + + + + + + + + + + + + + + + + + ISC BIND 9 Statistics + + +
+

ISC Bind 9 Configuration and Statistics

+
+
+

Server Times

+ + + + + + + + + +
Boot time: + +
Sample time: + +
+
+

Incoming Requests

+ + +
[no incoming requests]
+
+ + + + + + + + + + + + +
+ + + +
Total: + +
+
+

Incoming Queries by Type

+ + +
[no incoming queries]
+
+ + + + + + even + odd + + + + + + + + + + + +
+ + + +
Total: + +
+
+

Outgoing Queries per view

+ +

View

+ + + + + + +
+ + + + + + + even + odd + + + + + + + +
+ + + +
+
+ +

Server Statistics

+ + + +
+ + + + + + + even + odd + + + + + + + +
+ + + +
+
+

Zone Maintenance Statistics

+ + + +
+ + + + + + + even + odd + + + + + + + +
+ + + +
+

Resolver Statistics (Common)

+ + + + + + even + odd + + + + + + + +
+ + + +
+ +

Resolver Statistics for View

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+

Cache DB RRsets for View

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+

Socket I/O Statistics

+ + + + + even + odd + + + + + + + +
+ + + +
+
+
+

Response Codes per view/zone

+ +

View

+ + + + + +

Zone

+ + + + + + +
+ + + + + + + even + odd + + + + + + + +
+ + + +
+ + + +

Received QTYPES per view/zone

+ +

View

+ + + + + +

Zone

+ + + + + + +
+ + + + + + + even + odd + + + + + + + +
+ + + +
+ + + +

Network Status

+ + + + + + + + + + + + + + + even + odd + + + + + + + + + + + + +
IDNameTypeReferencesLocalAddressPeerAddressState
+ + + + + + + + + + + + + + + +
+
+

Task Manager Configuration

+ + + + + + + + + + + + + + + + + +
Thread-Model + +
Worker Threads + +
Default Quantum + +
Tasks Running + +
+
+

Tasks

+ + + + + + + + + + + + + even + odd + + + + + + + + + + +
IDNameReferencesStateQuantum
+ + + + + + + + + +
+
+

Memory Usage Summary

+ + + + + even + odd + + + + + + + +
+ + + +
+
+

Memory Contexts

+ + + + + + + + + + + + + + + + + + even + odd + + + + + + + + + + + + + + + +
IDNameReferencesTotalUseInUseMaxUseBlockSizePoolsHiWaterLoWater
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + + diff --git a/contrib/bind9/bin/named/bind9.ver3.xsl.h b/contrib/bind9/bin/named/bind9.ver3.xsl.h new file mode 100644 index 000000000000..c55714a6fb7b --- /dev/null +++ b/contrib/bind9/bin/named/bind9.ver3.xsl.h @@ -0,0 +1,740 @@ +/* + * Generated by convertxsl.pl 1.14 2008/07/17 23:43:26 jinmei Exp + * From \n" + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " ISC BIND 9 Statistics\n" + " \n" + " \n" + "
\n" + "

ISC Bind 9 Configuration and Statistics

\n" + "
\n" + "
\n" + "

Server Times

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
Boot time:\n" + " \n" + "
Sample time:\n" + " \n" + "
\n" + "
\n" + "

Incoming Requests

\n" + " \n" + " \n" + "
[graph incoming requests]
\n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
Total:\n" + " \n" + "
\n" + "
\n" + "

Incoming Queries by Type

\n" + " \n" + " \n" + "
[graph incoming qtypes]
\n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
Total:\n" + " \n" + "
\n" + "
\n" + "

Outgoing Queries per view

\n" + " \n" + "

View

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + " \n" + "

Server Statistics

\n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "

Zone Maintenance Statistics

\n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "

Resolver Statistics (Common)

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + " \n" + "

Resolver Statistics for View

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "

Cache DB RRsets for View

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "
\n" + "

Socket I/O Statistics

\n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "
\n" + "

Response Codes per view/zone

\n" + " \n" + "

View

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "

Zone

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "

Received QTYPES per view/zone

\n" + " \n" + "

View

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "

Zone

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "

Network Status

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
IDNameTypeReferencesLocalAddressPeerAddressState
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "

Task Manager Configuration

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
Thread-Model\n" + " \n" + "
Worker Threads\n" + " \n" + "
Default Quantum\n" + " \n" + "
Tasks Running\n" + " \n" + "
\n" + "
\n" + "

Tasks

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
IDNameReferencesStateQuantum
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "

Memory Usage Summary

\n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "

Memory Contexts

\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " even\n" + " odd\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
IDNameReferencesTotalUseInUseMaxUseBlockSizePoolsHiWaterLoWater
\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + "
\n" + "

Internet Systems Consortium Inc.
http://www.isc.org

\n" + " \n" + " \n" + " \n" + "\n"; diff --git a/contrib/bind9/bin/named/builtin.c b/contrib/bind9/bin/named/builtin.c index 14204cd295c6..4604cb3ce07e 100644 --- a/contrib/bind9/bin/named/builtin.c +++ b/contrib/bind9/bin/named/builtin.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: builtin.c,v 1.20.14.3 2012/01/11 20:19:40 ckb Exp $ */ +/* $Id: builtin.c,v 1.26 2012/01/21 19:44:18 each Exp $ */ /*! \file * \brief @@ -281,11 +281,14 @@ dns64_cname(const dns_name_t *zone, const dns_name_t *name, static isc_result_t builtin_lookup(const char *zone, const char *name, void *dbdata, - dns_sdblookup_t *lookup) + dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { builtin_t *b = (builtin_t *) dbdata; UNUSED(zone); + UNUSED(methods); + UNUSED(clientinfo); if (strcmp(name, "@") == 0) return (b->do_lookup(lookup)); @@ -295,10 +298,14 @@ builtin_lookup(const char *zone, const char *name, void *dbdata, static isc_result_t dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata, - dns_sdblookup_t *lookup) + dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { builtin_t *b = (builtin_t *) dbdata; + UNUSED(methods); + UNUSED(clientinfo); + if (name->labels == 0 && name->length == 0) return (b->do_lookup(lookup)); else @@ -353,6 +360,8 @@ do_authors_lookup(dns_sdblookup_t *lookup) { "Curtis Blackburn", "James Brister", "Ben Cottrell", + "John H. DuBois III", + "Francis Dupont", "Michael Graff", "Andreas Gustafsson", "Bob Halley", diff --git a/contrib/bind9/bin/named/client.c b/contrib/bind9/bin/named/client.c index ff4ab691c184..933abc7631e2 100644 --- a/contrib/bind9/bin/named/client.c +++ b/contrib/bind9/bin/named/client.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.271.10.4 2012/01/31 23:46:39 tbox Exp $ */ +/* $Id$ */ #include @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -116,15 +117,26 @@ struct ns_clientmgr { /* Unlocked. */ unsigned int magic; + + /* The queue object has its own locks */ + client_queue_t inactive; /*%< To be recycled */ + isc_mem_t * mctx; isc_taskmgr_t * taskmgr; isc_timermgr_t * timermgr; + + /* Lock covers manager state. */ isc_mutex_t lock; - /* Locked by lock. */ isc_boolean_t exiting; - client_list_t active; /*%< Active clients */ - client_list_t recursing; /*%< Recursing clients */ - client_list_t inactive; /*%< To be recycled */ + + /* Lock covers the clients list */ + isc_mutex_t listlock; + client_list_t clients; /*%< All active clients */ + + /* Lock covers the recursing list */ + isc_mutex_t reclock; + client_list_t recursing; /*%< Recursing clients */ + #if NMCTXS > 0 /*%< mctx pool for clients. */ unsigned int nextmctx; @@ -188,6 +200,12 @@ struct ns_clientmgr { * recursion quota, and an outstanding write request. */ +#define NS_CLIENTSTATE_RECURSING 5 +/*%< + * The client object is recursing. It will be on the 'recursing' + * list. + */ + #define NS_CLIENTSTATE_MAX 9 /*%< * Sentinel value used to indicate "no state". When client->newstate @@ -210,20 +228,21 @@ static void client_udprecv(ns_client_t *client); static void clientmgr_destroy(ns_clientmgr_t *manager); static isc_boolean_t exit_check(ns_client_t *client); static void ns_client_endrequest(ns_client_t *client); -static void ns_client_checkactive(ns_client_t *client); static void client_start(isc_task_t *task, isc_event_t *event); static void client_request(isc_task_t *task, isc_event_t *event); static void ns_client_dumpmessage(ns_client_t *client, const char *reason); +static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + dns_dispatch_t *disp, isc_boolean_t tcp); void ns_client_recursing(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(client->state == NS_CLIENTSTATE_WORKING); - LOCK(&client->manager->lock); - ISC_LIST_UNLINK(*client->list, client, link); - ISC_LIST_APPEND(client->manager->recursing, client, link); - client->list = &client->manager->recursing; - UNLOCK(&client->manager->lock); + LOCK(&client->manager->reclock); + client->newstate = client->state = NS_CLIENTSTATE_RECURSING; + ISC_LIST_APPEND(client->manager->recursing, client, rlink); + UNLOCK(&client->manager->reclock); } void @@ -231,15 +250,14 @@ ns_client_killoldestquery(ns_client_t *client) { ns_client_t *oldest; REQUIRE(NS_CLIENT_VALID(client)); - LOCK(&client->manager->lock); + LOCK(&client->manager->reclock); oldest = ISC_LIST_HEAD(client->manager->recursing); if (oldest != NULL) { + ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink); + UNLOCK(&client->manager->reclock); ns_query_cancel(oldest); - ISC_LIST_UNLINK(*oldest->list, oldest, link); - ISC_LIST_APPEND(client->manager->active, oldest, link); - oldest->list = &client->manager->active; - } - UNLOCK(&client->manager->lock); + } else + UNLOCK(&client->manager->reclock); } void @@ -268,15 +286,16 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) { */ static isc_boolean_t exit_check(ns_client_t *client) { - ns_clientmgr_t *locked_manager = NULL; - ns_clientmgr_t *destroy_manager = NULL; + isc_boolean_t destroy_manager = ISC_FALSE; + ns_clientmgr_t *manager = NULL; REQUIRE(NS_CLIENT_VALID(client)); + manager = client->manager; if (client->state <= client->newstate) return (ISC_FALSE); /* Business as usual. */ - INSIST(client->newstate < NS_CLIENTSTATE_WORKING); + INSIST(client->newstate < NS_CLIENTSTATE_RECURSING); /* * We need to detach from the view early when shutting down @@ -293,13 +312,16 @@ exit_check(ns_client_t *client) { client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL) dns_view_detach(&client->view); - if (client->state == NS_CLIENTSTATE_WORKING) { + if (client->state == NS_CLIENTSTATE_WORKING || + client->state == NS_CLIENTSTATE_RECURSING) + { INSIST(client->newstate <= NS_CLIENTSTATE_READING); /* * Let the update processing complete. */ if (client->nupdates > 0) return (ISC_TRUE); + /* * We are trying to abort request processing. */ @@ -322,23 +344,28 @@ exit_check(ns_client_t *client) { */ return (ISC_TRUE); } + /* * I/O cancel is complete. Burn down all state * related to the current request. Ensure that - * the client is on the active list and not the - * recursing list. + * the client is no longer on the recursing list. + * + * We need to check whether the client is still linked, + * because it may already have been removed from the + * recursing list by ns_client_killoldestquery() */ - LOCK(&client->manager->lock); - if (client->list == &client->manager->recursing) { - ISC_LIST_UNLINK(*client->list, client, link); - ISC_LIST_APPEND(client->manager->active, client, link); - client->list = &client->manager->active; + if (client->state == NS_CLIENTSTATE_RECURSING) { + LOCK(&manager->reclock); + if (ISC_LINK_LINKED(client, rlink)) + ISC_LIST_UNLINK(manager->recursing, + client, rlink); + UNLOCK(&manager->reclock); } - UNLOCK(&client->manager->lock); ns_client_endrequest(client); client->state = NS_CLIENTSTATE_READING; INSIST(client->recursionquota == NULL); + if (NS_CLIENTSTATE_READING == client->newstate) { client_read(client); client->newstate = NS_CLIENTSTATE_MAX; @@ -389,8 +416,27 @@ exit_check(ns_client_t *client) { * or UDP request, but we may have enough clients doing * that already. Check whether this client needs to remain * active and force it to go inactive if not. + * + * UDP clients go inactive at this point, but TCP clients + * may remain active if we have fewer active TCP client + * objects than desired due to an earlier quota exhaustion. */ - ns_client_checkactive(client); + if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { + LOCK(&client->interface->lock); + if (client->interface->ntcpcurrent < + client->interface->ntcptarget) + client->mortal = ISC_FALSE; + UNLOCK(&client->interface->lock); + } + + /* + * We don't need the client; send it to the inactive + * queue for recycling. + */ + if (client->mortal) { + if (client->newstate > NS_CLIENTSTATE_INACTIVE) + client->newstate = NS_CLIENTSTATE_INACTIVE; + } if (NS_CLIENTSTATE_READY == client->newstate) { if (TCP_CLIENT(client)) { @@ -404,6 +450,7 @@ exit_check(ns_client_t *client) { if (client->state == NS_CLIENTSTATE_READY) { INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE); + /* * We are trying to enter the inactive state. */ @@ -411,25 +458,22 @@ exit_check(ns_client_t *client) { isc_socket_cancel(client->tcplistener, client->task, ISC_SOCKCANCEL_ACCEPT); - if (! (client->naccepts == 0)) { - /* Still waiting for accept cancel completion. */ + /* Still waiting for accept cancel completion. */ + if (! (client->naccepts == 0)) return (ISC_TRUE); - } - /* Accept cancel is complete. */ + /* Accept cancel is complete. */ if (client->nrecvs > 0) isc_socket_cancel(client->udpsocket, client->task, ISC_SOCKCANCEL_RECV); - if (! (client->nrecvs == 0)) { - /* Still waiting for recv cancel completion. */ - return (ISC_TRUE); - } - /* Recv cancel is complete. */ - if (client->nctls > 0) { - /* Still waiting for control event to be delivered */ + /* Still waiting for recv cancel completion. */ + if (! (client->nrecvs == 0)) + return (ISC_TRUE); + + /* Still waiting for control event to be delivered */ + if (client->nctls > 0) return (ISC_TRUE); - } /* Deactivate the client. */ if (client->interface) @@ -449,7 +493,6 @@ exit_check(ns_client_t *client) { client->attributes = 0; client->mortal = ISC_FALSE; - LOCK(&client->manager->lock); /* * Put the client on the inactive list. If we are aiming for * the "freed" state, it will be removed from the inactive @@ -457,18 +500,18 @@ exit_check(ns_client_t *client) { * that has been done, lest the manager decide to reactivate * the dying client inbetween. */ - locked_manager = client->manager; - ISC_LIST_UNLINK(*client->list, client, link); - ISC_LIST_APPEND(client->manager->inactive, client, link); - client->list = &client->manager->inactive; client->state = NS_CLIENTSTATE_INACTIVE; INSIST(client->recursionquota == NULL); if (client->state == client->newstate) { client->newstate = NS_CLIENTSTATE_MAX; + if (!ns_g_clienttest && manager != NULL && + !manager->exiting) + ISC_QUEUE_PUSH(manager->inactive, client, + ilink); if (client->needshutdown) isc_task_shutdown(client->task); - goto unlock; + return (ISC_TRUE); } } @@ -485,6 +528,7 @@ exit_check(ns_client_t *client) { REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE); INSIST(client->recursionquota == NULL); + INSIST(!ISC_QLINK_LINKED(client, ilink)); ns_query_free(client); isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE); @@ -493,27 +537,27 @@ exit_check(ns_client_t *client) { isc_timer_detach(&client->timer); if (client->tcpbuf != NULL) - isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE); + isc_mem_put(client->mctx, client->tcpbuf, + TCP_BUFFER_SIZE); if (client->opt != NULL) { INSIST(dns_rdataset_isassociated(client->opt)); dns_rdataset_disassociate(client->opt); - dns_message_puttemprdataset(client->message, &client->opt); + dns_message_puttemprdataset(client->message, + &client->opt); } + dns_message_destroy(&client->message); - if (client->manager != NULL) { - ns_clientmgr_t *manager = client->manager; - if (locked_manager == NULL) { - LOCK(&manager->lock); - locked_manager = manager; - } - ISC_LIST_UNLINK(*client->list, client, link); - client->list = NULL; + if (manager != NULL) { + LOCK(&manager->listlock); + ISC_LIST_UNLINK(manager->clients, client, link); + LOCK(&manager->lock); if (manager->exiting && - ISC_LIST_EMPTY(manager->active) && - ISC_LIST_EMPTY(manager->inactive) && - ISC_LIST_EMPTY(manager->recursing)) - destroy_manager = manager; + ISC_LIST_EMPTY(manager->clients)) + destroy_manager = ISC_TRUE; + UNLOCK(&manager->lock); + UNLOCK(&manager->listlock); } + /* * Detaching the task must be done after unlinking from * the manager's lists because the manager accesses @@ -524,6 +568,7 @@ exit_check(ns_client_t *client) { CTRACE("free"); client->magic = 0; + /* * Check that there are no other external references to * the memory context. @@ -533,22 +578,10 @@ exit_check(ns_client_t *client) { INSIST(0); } isc_mem_putanddetach(&client->mctx, client, sizeof(*client)); - - goto unlock; } - unlock: - if (locked_manager != NULL) { - UNLOCK(&locked_manager->lock); - locked_manager = NULL; - } - - /* - * Only now is it safe to destroy the client manager (if needed), - * because we have accessed its lock for the last time. - */ - if (destroy_manager != NULL) - clientmgr_destroy(destroy_manager); + if (destroy_manager && manager != NULL) + clientmgr_destroy(manager); return (ISC_TRUE); } @@ -604,6 +637,9 @@ client_shutdown(isc_task_t *task, isc_event_t *event) { client->shutdown_arg = NULL; } + if (ISC_QLINK_LINKED(client, ilink)) + ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink); + client->newstate = NS_CLIENTSTATE_FREED; client->needshutdown = ISC_FALSE; (void)exit_check(client); @@ -616,7 +652,8 @@ ns_client_endrequest(ns_client_t *client) { INSIST(client->nsends == 0); INSIST(client->nrecvs == 0); INSIST(client->nupdates == 0); - INSIST(client->state == NS_CLIENTSTATE_WORKING); + INSIST(client->state == NS_CLIENTSTATE_WORKING || + client->state == NS_CLIENTSTATE_RECURSING); CTRACE("endrequest"); @@ -649,46 +686,13 @@ ns_client_endrequest(ns_client_t *client) { client->attributes &= NS_CLIENTATTR_TCP; } -static void -ns_client_checkactive(ns_client_t *client) { - if (client->mortal) { - /* - * This client object should normally go inactive - * at this point, but if we have fewer active client - * objects than desired due to earlier quota exhaustion, - * keep it active to make up for the shortage. - */ - isc_boolean_t need_another_client = ISC_FALSE; - if (TCP_CLIENT(client) && !ns_g_clienttest) { - LOCK(&client->interface->lock); - if (client->interface->ntcpcurrent < - client->interface->ntcptarget) - need_another_client = ISC_TRUE; - UNLOCK(&client->interface->lock); - } else { - /* - * The UDP client quota is enforced by making - * requests fail rather than by not listening - * for new ones. Therefore, there is always a - * full set of UDP clients listening. - */ - } - if (! need_another_client) { - /* - * We don't need this client object. Recycle it. - */ - if (client->newstate >= NS_CLIENTSTATE_INACTIVE) - client->newstate = NS_CLIENTSTATE_INACTIVE; - } - } -} - void ns_client_next(ns_client_t *client, isc_result_t result) { int newstate; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->state == NS_CLIENTSTATE_WORKING || + client->state == NS_CLIENTSTATE_RECURSING || client->state == NS_CLIENTSTATE_READING); CTRACE("next"); @@ -745,9 +749,6 @@ client_senddone(isc_task_t *task, isc_event_t *event) { client->tcpbuf = NULL; } - if (exit_check(client)) - return; - ns_client_next(client, ISC_R_SUCCESS); } @@ -1974,6 +1975,11 @@ static isc_result_t get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) { isc_mem_t *clientmctx; isc_result_t result; +#if NMCTXS > 0 + unsigned int nextmctx; +#endif + + MTRACE("clientmctx"); /* * Caller must be holding the manager lock. @@ -1985,19 +1991,21 @@ get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) { return (result); } #if NMCTXS > 0 - INSIST(manager->nextmctx < NMCTXS); - clientmctx = manager->mctxpool[manager->nextmctx]; + nextmctx = manager->nextmctx++; + if (manager->nextmctx == NMCTXS) + manager->nextmctx = 0; + + INSIST(nextmctx < NMCTXS); + + clientmctx = manager->mctxpool[nextmctx]; if (clientmctx == NULL) { result = isc_mem_create(0, 0, &clientmctx); if (result != ISC_R_SUCCESS) return (result); isc_mem_setname(clientmctx, "client", NULL); - manager->mctxpool[manager->nextmctx] = clientmctx; + manager->mctxpool[nextmctx] = clientmctx; } - manager->nextmctx++; - if (manager->nextmctx == NMCTXS) - manager->nextmctx = 0; #else clientmctx = manager->mctx; #endif @@ -2118,6 +2126,8 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { #ifdef ALLOW_FILTER_AAAA_ON_V4 client->filter_aaaa = dns_v4_aaaa_ok; #endif + client->needshutdown = ns_g_clienttest; + ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, NS_EVENT_CLIENTCONTROL, client_start, client, client, NULL, NULL); @@ -2129,7 +2139,8 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { client->formerrcache.time = 0; client->formerrcache.id = 0; ISC_LINK_INIT(client, link); - client->list = NULL; + ISC_LINK_INIT(client, rlink); + ISC_QLINK_INIT(client, ilink); /* * We call the init routines for the various kinds of client here, @@ -2144,8 +2155,6 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { if (result != ISC_R_SUCCESS) goto cleanup_query; - client->needshutdown = ns_g_clienttest; - CTRACE("create"); *clientp = client; @@ -2410,10 +2419,8 @@ ns_client_replace(ns_client_t *client) { REQUIRE(client != NULL); REQUIRE(client->manager != NULL); - result = ns_clientmgr_createclients(client->manager, - 1, client->interface, - (TCP_CLIENT(client) ? - ISC_TRUE : ISC_FALSE)); + result = get_client(client->manager, client->interface, + client->dispatch, TCP_CLIENT(client)); if (result != ISC_R_SUCCESS) return (result); @@ -2437,9 +2444,7 @@ clientmgr_destroy(ns_clientmgr_t *manager) { int i; #endif - REQUIRE(ISC_LIST_EMPTY(manager->active)); - REQUIRE(ISC_LIST_EMPTY(manager->inactive)); - REQUIRE(ISC_LIST_EMPTY(manager->recursing)); + REQUIRE(ISC_LIST_EMPTY(manager->clients)); MTRACE("clientmgr_destroy"); @@ -2450,7 +2455,10 @@ clientmgr_destroy(ns_clientmgr_t *manager) { } #endif + ISC_QUEUE_DESTROY(manager->inactive); DESTROYLOCK(&manager->lock); + DESTROYLOCK(&manager->listlock); + DESTROYLOCK(&manager->reclock); manager->magic = 0; isc_mem_put(manager->mctx, manager, sizeof(*manager)); } @@ -2473,13 +2481,21 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, if (result != ISC_R_SUCCESS) goto cleanup_manager; + result = isc_mutex_init(&manager->listlock); + if (result != ISC_R_SUCCESS) + goto cleanup_lock; + + result = isc_mutex_init(&manager->reclock); + if (result != ISC_R_SUCCESS) + goto cleanup_listlock; + manager->mctx = mctx; manager->taskmgr = taskmgr; manager->timermgr = timermgr; manager->exiting = ISC_FALSE; - ISC_LIST_INIT(manager->active); - ISC_LIST_INIT(manager->inactive); + ISC_LIST_INIT(manager->clients); ISC_LIST_INIT(manager->recursing); + ISC_QUEUE_INIT(manager->inactive, ilink); #if NMCTXS > 0 manager->nextmctx = 0; for (i = 0; i < NMCTXS; i++) @@ -2493,6 +2509,12 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, return (ISC_R_SUCCESS); + cleanup_listlock: + (void) isc_mutex_destroy(&manager->listlock); + + cleanup_lock: + (void) isc_mutex_destroy(&manager->lock); + cleanup_manager: isc_mem_put(manager->mctx, manager, sizeof(*manager)); @@ -2501,9 +2523,10 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, void ns_clientmgr_destroy(ns_clientmgr_t **managerp) { + isc_result_t result; ns_clientmgr_t *manager; ns_client_t *client; - isc_boolean_t need_destroy = ISC_FALSE; + isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE; REQUIRE(managerp != NULL); manager = *managerp; @@ -2511,31 +2534,27 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) { MTRACE("destroy"); - LOCK(&manager->lock); + /* + * Check for success because we may already be task-exclusive + * at this point. Only if we succeed at obtaining an exclusive + * lock now will we need to relinquish it later. + */ + result = isc_task_beginexclusive(ns_g_server->task); + if (result == ISC_R_SUCCESS) + unlock = ISC_TRUE; manager->exiting = ISC_TRUE; - for (client = ISC_LIST_HEAD(manager->recursing); + for (client = ISC_LIST_HEAD(manager->clients); client != NULL; client = ISC_LIST_NEXT(client, link)) isc_task_shutdown(client->task); - for (client = ISC_LIST_HEAD(manager->active); - client != NULL; - client = ISC_LIST_NEXT(client, link)) - isc_task_shutdown(client->task); - - for (client = ISC_LIST_HEAD(manager->inactive); - client != NULL; - client = ISC_LIST_NEXT(client, link)) - isc_task_shutdown(client->task); - - if (ISC_LIST_EMPTY(manager->active) && - ISC_LIST_EMPTY(manager->inactive) && - ISC_LIST_EMPTY(manager->recursing)) + if (ISC_LIST_EMPTY(manager->clients)) need_destroy = ISC_TRUE; - UNLOCK(&manager->lock); + if (unlock) + isc_task_endexclusive(ns_g_server->task); if (need_destroy) clientmgr_destroy(manager); @@ -2543,81 +2562,86 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) { *managerp = NULL; } +static isc_result_t +get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + dns_dispatch_t *disp, isc_boolean_t tcp) +{ + isc_result_t result = ISC_R_SUCCESS; + isc_event_t *ev; + ns_client_t *client; + MTRACE("get client"); + + REQUIRE(manager != NULL); + + if (manager->exiting) + return (ISC_R_SHUTTINGDOWN); + + /* + * Allocate a client. First try to get a recycled one; + * if that fails, make a new one. + */ + client = NULL; + if (!ns_g_clienttest) + ISC_QUEUE_POP(manager->inactive, ilink, client); + + if (client != NULL) + MTRACE("recycle"); + else { + MTRACE("create new"); + + LOCK(&manager->lock); + result = client_create(manager, &client); + UNLOCK(&manager->lock); + if (result != ISC_R_SUCCESS) + return (result); + + LOCK(&manager->listlock); + ISC_LIST_APPEND(manager->clients, client, link); + UNLOCK(&manager->listlock); + } + + client->manager = manager; + ns_interface_attach(ifp, &client->interface); + client->state = NS_CLIENTSTATE_READY; + INSIST(client->recursionquota == NULL); + + if (tcp) { + client->attributes |= NS_CLIENTATTR_TCP; + isc_socket_attach(ifp->tcpsocket, + &client->tcplistener); + } else { + isc_socket_t *sock; + + dns_dispatch_attach(disp, &client->dispatch); + sock = dns_dispatch_getsocket(client->dispatch); + isc_socket_attach(sock, &client->udpsocket); + } + + INSIST(client->nctls == 0); + client->nctls++; + ev = &client->ctlevent; + isc_task_send(client->task, &ev); + + return (ISC_R_SUCCESS); +} + isc_result_t ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, ns_interface_t *ifp, isc_boolean_t tcp) { isc_result_t result = ISC_R_SUCCESS; - unsigned int i; - ns_client_t *client; + unsigned int disp; REQUIRE(VALID_MANAGER(manager)); REQUIRE(n > 0); MTRACE("createclients"); - /* - * We MUST lock the manager lock for the entire client creation - * process. If we didn't do this, then a client could get a - * shutdown event and disappear out from under us. - */ - - LOCK(&manager->lock); - - for (i = 0; i < n; i++) { - isc_event_t *ev; - /* - * Allocate a client. First try to get a recycled one; - * if that fails, make a new one. - */ - client = NULL; - if (!ns_g_clienttest) - client = ISC_LIST_HEAD(manager->inactive); - if (client != NULL) { - MTRACE("recycle"); - ISC_LIST_UNLINK(manager->inactive, client, link); - client->list = NULL; - } else { - MTRACE("create new"); - result = client_create(manager, &client); - if (result != ISC_R_SUCCESS) - break; - } - - ns_interface_attach(ifp, &client->interface); - client->state = NS_CLIENTSTATE_READY; - INSIST(client->recursionquota == NULL); - - if (tcp) { - client->attributes |= NS_CLIENTATTR_TCP; - isc_socket_attach(ifp->tcpsocket, - &client->tcplistener); - } else { - isc_socket_t *sock; - - dns_dispatch_attach(ifp->udpdispatch, - &client->dispatch); - sock = dns_dispatch_getsocket(client->dispatch); - isc_socket_attach(sock, &client->udpsocket); - } - client->manager = manager; - ISC_LIST_APPEND(manager->active, client, link); - client->list = &manager->active; - - INSIST(client->nctls == 0); - client->nctls++; - ev = &client->ctlevent; - isc_task_send(client->task, &ev); + for (disp = 0; disp < n; disp++) { + result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp); + if (result != ISC_R_SUCCESS) + break; } - if (i != 0) { - /* - * We managed to create at least one client, so we - * declare victory. - */ - result = ISC_R_SUCCESS; - } - - UNLOCK(&manager->lock); return (result); } @@ -2702,19 +2726,41 @@ ns_client_logv(ns_client_t *client, isc_logcategory_t *category, { char msgbuf[2048]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; - const char *name = ""; - const char *sep = ""; + char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE]; + const char *viewname = ""; + const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = ""; + const char *signer = "", *qname = ""; + dns_name_t *q = NULL; vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + ns_client_name(client, peerbuf, sizeof(peerbuf)); + + if (client->signer != NULL) { + dns_name_format(client->signer, signerbuf, sizeof(signerbuf)); + sep1 = "/key "; + signer = signerbuf; + } + + q = client->query.origqname != NULL + ? client->query.origqname : client->query.qname; + if (q != NULL) { + dns_name_format(q, qnamebuf, sizeof(qnamebuf)); + sep2 = " ("; + sep3 = ")"; + qname = qnamebuf; + } + if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && strcmp(client->view->name, "_default") != 0) { - name = client->view->name; - sep = ": view "; + sep4 = ": view "; + viewname = client->view->name; } isc_log_write(ns_g_lctx, category, module, level, - "client %s%s%s: %s", peerbuf, sep, name, msgbuf); + "client %s%s%s%s%s%s%s%s: %s", + peerbuf, sep1, signer, sep2, qname, sep3, + sep4, viewname, msgbuf); } void @@ -2796,9 +2842,11 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { REQUIRE(VALID_MANAGER(manager)); - LOCK(&manager->lock); + LOCK(&manager->reclock); client = ISC_LIST_HEAD(manager->recursing); while (client != NULL) { + INSIST(client->state == NS_CLIENTSTATE_RECURSING); + ns_client_name(client, peerbuf, sizeof(peerbuf)); if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && @@ -2809,6 +2857,9 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { name = ""; sep = ""; } + + LOCK(&client->query.fetchlock); + INSIST(client->query.qname != NULL); dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); if (client->query.qname != client->query.origqname && client->query.origqname != NULL) { @@ -2831,20 +2882,19 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { strcpy(typebuf, "-"); strcpy(classbuf, "-"); } + UNLOCK(&client->query.fetchlock); fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s " "requesttime %d\n", peerbuf, sep, name, client->message->id, namebuf, typebuf, classbuf, origfor, original, client->requesttime); - client = ISC_LIST_NEXT(client, link); + client = ISC_LIST_NEXT(client, rlink); } - UNLOCK(&manager->lock); + UNLOCK(&manager->reclock); } void ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) { - - if (client->manager != NULL) - LOCK(&client->manager->lock); + LOCK(&client->query.fetchlock); if (client->query.restarts > 0) { /* * client->query.qname was dynamically allocated. @@ -2853,6 +2903,16 @@ ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) { &client->query.qname); } client->query.qname = name; - if (client->manager != NULL) - UNLOCK(&client->manager->lock); + UNLOCK(&client->query.fetchlock); +} + +isc_result_t +ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) { + ns_client_t *client = (ns_client_t *) ci->data; + + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(addrp != NULL); + + *addrp = &client->peeraddr; + return (ISC_R_SUCCESS); } diff --git a/contrib/bind9/bin/named/config.c b/contrib/bind9/bin/named/config.c index 25ebac4db0c1..fa349eeade2f 100644 --- a/contrib/bind9/bin/named/config.c +++ b/contrib/bind9/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.113.16.2 2011/02/28 01:19:58 tbox Exp $ */ +/* $Id: config.c,v 1.123 2012/01/06 23:46:41 tbox Exp $ */ /*! \file */ @@ -73,6 +73,7 @@ options {\n\ listen-on {any;};\n\ listen-on-v6 {none;};\n\ match-mapped-addresses no;\n\ + max-rsa-exponent-size 0; /* no limit */\n\ memstatistics-file \"named.memstats\";\n\ multiple-cnames no;\n\ # named-xfer ;\n\ @@ -90,7 +91,7 @@ options {\n\ "\ recursive-clients 1000;\n\ resolver-query-timeout 10;\n\ - rrset-order {type NS order random; order cyclic; };\n\ + rrset-order { order random; };\n\ serial-queries 20;\n\ serial-query-rate 20;\n\ server-id none;\n\ @@ -200,7 +201,8 @@ options {\n\ sig-signing-nodes 100;\n\ sig-signing-signatures 10;\n\ sig-signing-type 65534;\n\ - zone-statistics false;\n\ + inline-signing no;\n\ + zone-statistics terse;\n\ max-journal-size unlimited;\n\ ixfr-from-differences false;\n\ check-wildcard yes;\n\ @@ -210,7 +212,10 @@ options {\n\ check-srv-cname warn;\n\ zero-no-soa-ttl yes;\n\ update-check-ksk yes;\n\ + serial-update-method increment;\n\ + dnssec-update-mode maintain;\n\ dnssec-dnskey-kskonly no;\n\ + dnssec-loadkeys-interval 60;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ };\n\ " @@ -292,7 +297,8 @@ ns_checknames_get(const cfg_obj_t **maps, const char *which, if (maps[i] == NULL) return (ISC_R_NOTFOUND); checknames = NULL; - if (cfg_map_get(maps[i], "check-names", &checknames) == ISC_R_SUCCESS) { + if (cfg_map_get(maps[i], "check-names", + &checknames) == ISC_R_SUCCESS) { /* * Zone map entry is not a list. */ @@ -305,7 +311,8 @@ ns_checknames_get(const cfg_obj_t **maps, const char *which, element = cfg_list_next(element)) { value = cfg_listelt_value(element); type = cfg_tuple_get(value, "type"); - if (strcasecmp(cfg_obj_asstring(type), which) == 0) { + if (strcasecmp(cfg_obj_asstring(type), + which) == 0) { *obj = cfg_tuple_get(value, "mode"); return (ISC_R_SUCCESS); } @@ -378,6 +385,8 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj) { ztype = dns_zone_stub; else if (strcasecmp(str, "static-stub") == 0) ztype = dns_zone_staticstub; + else if (strcasecmp(str, "redirect") == 0) + ztype = dns_zone_redirect; else INSIST(0); return (ztype); diff --git a/contrib/bind9/bin/named/control.c b/contrib/bind9/bin/named/control.c index 2a1a5a8e734e..fabe442aabc3 100644 --- a/contrib/bind9/bin/named/control.c +++ b/contrib/bind9/bin/named/control.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.41 2010/12/03 22:05:19 each Exp $ */ +/* $Id$ */ /*! \file */ @@ -154,7 +154,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_DUMPSTATS)) { result = ns_server_dumpstats(ns_g_server); } else if (command_compare(command, NS_COMMAND_QUERYLOG)) { - result = ns_server_togglequerylog(ns_g_server); + result = ns_server_togglequerylog(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_DUMPDB)) { ns_server_dumpdb(ns_g_server, command); result = ISC_R_SUCCESS; @@ -169,7 +169,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_FLUSH)) { result = ns_server_flushcache(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) { - result = ns_server_flushname(ns_g_server, command); + result = ns_server_flushnode(ns_g_server, command, ISC_FALSE); + } else if (command_compare(command, NS_COMMAND_FLUSHTREE)) { + result = ns_server_flushnode(ns_g_server, command, ISC_TRUE); } else if (command_compare(command, NS_COMMAND_STATUS)) { result = ns_server_status(ns_g_server, text); } else if (command_compare(command, NS_COMMAND_TSIGLIST)) { @@ -183,6 +185,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { command_compare(command, NS_COMMAND_THAW)) { result = ns_server_freeze(ns_g_server, ISC_FALSE, command, text); + } else if (command_compare(command, NS_COMMAND_SYNC)) { + result = ns_server_sync(ns_g_server, command, text); } else if (command_compare(command, NS_COMMAND_RECURSING)) { result = ns_server_dumprecursing(ns_g_server); } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) { @@ -201,6 +205,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { result = ns_server_add_zone(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_DELZONE)) { result = ns_server_del_zone(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_SIGNING)) { + result = ns_server_signing(ns_g_server, command, text); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, diff --git a/contrib/bind9/bin/named/controlconf.c b/contrib/bind9/bin/named/controlconf.c index 73c0f37e9737..c46a6e15f467 100644 --- a/contrib/bind9/bin/named/controlconf.c +++ b/contrib/bind9/bin/named/controlconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: controlconf.c,v 1.60.544.3 2011/12/22 08:10:09 marka Exp $ */ +/* $Id: controlconf.c,v 1.63 2011/12/22 08:07:48 marka Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h b/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h index 7af325a13b30..602b3c074d12 100644 --- a/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h +++ b/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz_dlopen_driver.h,v 1.1.4.4 2011/03/17 09:41:06 fdupont Exp $ */ +/* $Id: dlz_dlopen_driver.h,v 1.4 2011/03/17 09:25:53 fdupont Exp $ */ #ifndef DLZ_DLOPEN_DRIVER_H #define DLZ_DLOPEN_DRIVER_H diff --git a/contrib/bind9/bin/named/include/named/client.h b/contrib/bind9/bin/named/include/named/client.h index e6414d2f7a7a..98e79df70668 100644 --- a/contrib/bind9/bin/named/include/named/client.h +++ b/contrib/bind9/bin/named/include/named/client.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.91.278.2 2012/01/31 23:46:39 tbox Exp $ */ +/* $Id$ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -66,7 +66,9 @@ #include #include #include +#include +#include #include #include #include @@ -81,8 +83,6 @@ *** Types ***/ -typedef ISC_LIST(ns_client_t) client_list_t; - /*% nameserver client structure */ struct ns_client { unsigned int magic; @@ -155,13 +155,15 @@ struct ns_client { isc_stdtime_t time; dns_messageid_t id; } formerrcache; + ISC_LINK(ns_client_t) link; - /*% - * The list 'link' is part of, or NULL if not on any list. - */ - client_list_t *list; + ISC_LINK(ns_client_t) rlink; + ISC_QLINK(ns_client_t) ilink; }; +typedef ISC_QUEUE(ns_client_t) client_queue_t; +typedef ISC_LIST(ns_client_t) client_list_t; + #define NS_CLIENT_MAGIC ISC_MAGIC('N','S','C','c') #define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC) @@ -379,4 +381,7 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, * Isself callback. */ +isc_result_t +ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp); + #endif /* NAMED_CLIENT_H */ diff --git a/contrib/bind9/bin/named/include/named/control.h b/contrib/bind9/bin/named/include/named/control.h index 24e59093b4d1..d730a83280cd 100644 --- a/contrib/bind9/bin/named/include/named/control.h +++ b/contrib/bind9/bin/named/include/named/control.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.h,v 1.31 2010/08/16 22:21:06 marka Exp $ */ +/* $Id$ */ #ifndef NAMED_CONTROL_H #define NAMED_CONTROL_H 1 @@ -47,6 +47,7 @@ #define NS_COMMAND_NOTRACE "notrace" #define NS_COMMAND_FLUSH "flush" #define NS_COMMAND_FLUSHNAME "flushname" +#define NS_COMMAND_FLUSHTREE "flushtree" #define NS_COMMAND_STATUS "status" #define NS_COMMAND_TSIGLIST "tsig-list" #define NS_COMMAND_TSIGDELETE "tsig-delete" @@ -62,6 +63,8 @@ #define NS_COMMAND_LOADKEYS "loadkeys" #define NS_COMMAND_ADDZONE "addzone" #define NS_COMMAND_DELZONE "delzone" +#define NS_COMMAND_SYNC "sync" +#define NS_COMMAND_SIGNING "signing" isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); diff --git a/contrib/bind9/bin/named/include/named/globals.h b/contrib/bind9/bin/named/include/named/globals.h index 39307f36996b..cbc14d8b72d9 100644 --- a/contrib/bind9/bin/named/include/named/globals.h +++ b/contrib/bind9/bin/named/include/named/globals.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.89.54.2 2011/06/17 23:47:10 tbox Exp $ */ +/* $Id: globals.h,v 1.92 2011/11/09 18:44:04 each Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -51,6 +51,7 @@ EXTERN isc_mem_t * ns_g_mctx INIT(NULL); EXTERN unsigned int ns_g_cpus INIT(0); +EXTERN unsigned int ns_g_udpdisp INIT(0); EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL); EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL); EXTERN isc_entropy_t * ns_g_entropy INIT(NULL); diff --git a/contrib/bind9/bin/named/include/named/interfacemgr.h b/contrib/bind9/bin/named/include/named/interfacemgr.h index 2724c393cdc5..380dbedd7686 100644 --- a/contrib/bind9/bin/named/include/named/interfacemgr.h +++ b/contrib/bind9/bin/named/include/named/interfacemgr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.h,v 1.33 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */ #ifndef NAMED_INTERFACEMGR_H #define NAMED_INTERFACEMGR_H 1 @@ -65,7 +65,8 @@ #define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC) #define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */ - +#define MAX_UDP_DISPATCH 128 /*%< Maximum number of UDP dispatchers + to start per interface */ /*% The nameserver interface structure */ struct ns_interface { unsigned int magic; /*%< Magic number. */ @@ -76,11 +77,13 @@ struct ns_interface { isc_sockaddr_t addr; /*%< Address and port. */ unsigned int flags; /*%< Interface characteristics */ char name[32]; /*%< Null terminated. */ - dns_dispatch_t * udpdispatch; /*%< UDP dispatcher. */ + dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; + /*%< UDP dispatchers. */ isc_socket_t * tcpsocket; /*%< TCP socket. */ int ntcptarget; /*%< Desired number of concurrent TCP accepts */ int ntcpcurrent; /*%< Current ditto, locked */ + int nudpdispatch; /*%< Number of UDP dispatches */ ns_clientmgr_t * clientmgr; /*%< Client manager. */ ISC_LINK(ns_interface_t) link; }; diff --git a/contrib/bind9/bin/named/include/named/server.h b/contrib/bind9/bin/named/include/named/server.h index 9982e88e09e4..3ba0c64a712d 100644 --- a/contrib/bind9/bin/named/include/named/server.h +++ b/contrib/bind9/bin/named/include/named/server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.110 2010/08/16 23:46:52 tbox Exp $ */ +/* $Id$ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -230,9 +230,10 @@ ns_server_retransfercommand(ns_server_t *server, char *args); */ isc_result_t -ns_server_togglequerylog(ns_server_t *server); +ns_server_togglequerylog(ns_server_t *server, char *args); /*%< - * Toggle logging of queries, as in BIND 8. + * Enable/disable logging of queries. (Takes "yes" or "no" argument, + * but can also be used as a toggle for backward comptibility.) */ /*% @@ -266,10 +267,12 @@ isc_result_t ns_server_flushcache(ns_server_t *server, char *args); /*% - * Flush a particular name from the server's cache(s) + * Flush a particular name from the server's cache. If 'tree' is false, + * also flush the name from the ADB and badcache. If 'tree' is true, also + * flush all the names under the specified name. */ isc_result_t -ns_server_flushname(ns_server_t *server, char *args); +ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree); /*% * Report the server's status. @@ -296,6 +299,12 @@ isc_result_t ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_buffer_t *text); +/*% + * Dump zone updates to disk, optionally removing the journal file + */ +isc_result_t +ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text); + /*% * Update a zone's DNSKEY set from the key repository. If * the command that triggered the call to this function was "sign", @@ -336,4 +345,9 @@ ns_server_add_zone(ns_server_t *server, char *args); isc_result_t ns_server_del_zone(ns_server_t *server, char *args); +/*% + * Lists the status of the signing records for a given zone. + */ +isc_result_t +ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text); #endif /* NAMED_SERVER_H */ diff --git a/contrib/bind9/bin/named/include/named/zoneconf.h b/contrib/bind9/bin/named/include/named/zoneconf.h index ebaad684ae7a..0e684d2d4c7e 100644 --- a/contrib/bind9/bin/named/include/named/zoneconf.h +++ b/contrib/bind9/bin/named/include/named/zoneconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.h,v 1.28 2010/12/20 23:47:20 tbox Exp $ */ +/* $Id: zoneconf.h,v 1.30 2011/08/30 23:46:51 tbox Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 @@ -33,7 +33,7 @@ ISC_LANG_BEGINDECLS isc_result_t ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, - dns_zone_t *zone); + dns_zone_t *zone, dns_zone_t *raw); /*%< * Configure or reconfigure a zone according to the named.conf * data in 'cctx' and 'czone'. diff --git a/contrib/bind9/bin/named/interfacemgr.c b/contrib/bind9/bin/named/interfacemgr.c index 15ffe00aa51a..84bf21d77142 100644 --- a/contrib/bind9/bin/named/interfacemgr.c +++ b/contrib/bind9/bin/named/interfacemgr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,13 +15,14 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.c,v 1.95.426.2 2011/03/12 04:59:14 tbox Exp $ */ +/* $Id: interfacemgr.c,v 1.101 2011/11/09 18:44:03 each Exp $ */ /*! \file */ #include #include +#include #include #include #include @@ -185,11 +186,14 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, { ns_interface_t *ifp; isc_result_t result; + int disp; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); + ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); if (ifp == NULL) return (ISC_R_NOMEMORY); + ifp->mgr = NULL; ifp->generation = mgr->generation; ifp->addr = *addr; @@ -212,9 +216,11 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, goto clientmgr_create_failure; } - ifp->udpdispatch = NULL; + for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) + ifp->udpdispatch[disp] = NULL; ifp->tcpsocket = NULL; + /* * Create a single TCP client object. It will replace itself * with a new one as soon as it gets a connection, so the actual @@ -223,6 +229,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, */ ifp->ntcptarget = 1; ifp->ntcpcurrent = 0; + ifp->nudpdispatch = 0; ISC_LINK_INIT(ifp, link); @@ -237,6 +244,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, clientmgr_create_failure: DESTROYLOCK(&ifp->lock); + lock_create_failure: ifp->magic = 0; isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); @@ -249,6 +257,7 @@ ns_interface_listenudp(ns_interface_t *ifp) { isc_result_t result; unsigned int attrs; unsigned int attrmask; + int disp, i; attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; @@ -260,18 +269,28 @@ ns_interface_listenudp(ns_interface_t *ifp) { attrmask = 0; attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; - result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr, - ns_g_taskmgr, &ifp->addr, - 4096, 1000, 32768, 8219, 8237, - attrs, attrmask, &ifp->udpdispatch); - if (result != ISC_R_SUCCESS) { - isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, - "could not listen on UDP socket: %s", - isc_result_totext(result)); - goto udp_dispatch_failure; + + ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH); + for (disp = 0; disp < ifp->nudpdispatch; disp++) { + result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr, + ns_g_socketmgr, + ns_g_taskmgr, &ifp->addr, + 4096, 1000, 32768, 8219, 8237, + attrs, attrmask, + &ifp->udpdispatch[disp], + disp == 0 + ? NULL + : ifp->udpdispatch[0]); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "could not listen on UDP socket: %s", + isc_result_totext(result)); + goto udp_dispatch_failure; + } + } - result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus, + result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch, ifp, ISC_FALSE); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, @@ -279,12 +298,17 @@ ns_interface_listenudp(ns_interface_t *ifp) { isc_result_totext(result)); goto addtodispatch_failure; } + return (ISC_R_SUCCESS); addtodispatch_failure: - dns_dispatch_changeattributes(ifp->udpdispatch, 0, - DNS_DISPATCHATTR_NOLISTEN); - dns_dispatch_detach(&ifp->udpdispatch); + for (i = disp - 1; i <= 0; i--) { + dns_dispatch_changeattributes(ifp->udpdispatch[i], 0, + DNS_DISPATCHATTR_NOLISTEN); + dns_dispatch_detach(&(ifp->udpdispatch[i])); + } + ifp->nudpdispatch = 0; + udp_dispatch_failure: return (result); } @@ -398,15 +422,19 @@ ns_interface_shutdown(ns_interface_t *ifp) { static void ns_interface_destroy(ns_interface_t *ifp) { isc_mem_t *mctx = ifp->mgr->mctx; + int disp; + REQUIRE(NS_INTERFACE_VALID(ifp)); ns_interface_shutdown(ifp); - if (ifp->udpdispatch != NULL) { - dns_dispatch_changeattributes(ifp->udpdispatch, 0, - DNS_DISPATCHATTR_NOLISTEN); - dns_dispatch_detach(&ifp->udpdispatch); - } + for (disp = 0; disp < ifp->nudpdispatch; disp++) + if (ifp->udpdispatch[disp] != NULL) { + dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0, + DNS_DISPATCHATTR_NOLISTEN); + dns_dispatch_detach(&(ifp->udpdispatch[disp])); + } + if (ifp->tcpsocket != NULL) isc_socket_detach(&ifp->tcpsocket); diff --git a/contrib/bind9/bin/named/logconf.c b/contrib/bind9/bin/named/logconf.c index f02b97fcddee..b99a167d12f1 100644 --- a/contrib/bind9/bin/named/logconf.c +++ b/contrib/bind9/bin/named/logconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: logconf.c,v 1.42.816.3 2011/03/05 23:52:06 tbox Exp $ */ +/* $Id: logconf.c,v 1.45 2011/03/05 23:52:29 tbox Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/main.c b/contrib/bind9/bin/named/main.c index f6c929e5b967..a5467249082a 100644 --- a/contrib/bind9/bin/named/main.c +++ b/contrib/bind9/bin/named/main.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.c,v 1.180.14.4 2011/11/05 00:45:52 each Exp $ */ +/* $Id$ */ /*! \file */ @@ -418,7 +418,7 @@ parse_command_line(int argc, char *argv[]) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "46c:C:d:E:fFgi:lm:n:N:p:P:" - "sS:t:T:u:vVx:")) != -1) { + "sS:t:T:U:u:vVx:")) != -1) { switch (ch) { case '4': if (disable4) @@ -531,6 +531,11 @@ parse_command_line(int argc, char *argv[]) { fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument); break; + case 'U': + ns_g_udpdisp = parse_int(isc_commandline_argument, + "number of UDP listeners " + "per interface"); + break; case 'u': ns_g_username = isc_commandline_argument; break; @@ -595,6 +600,18 @@ create_managers(void) { #else ns_g_cpus = 1; #endif +#ifdef WIN32 + ns_g_udpdisp = 1; +#else + if (ns_g_udpdisp == 0) + ns_g_udpdisp = ns_g_cpus_detected; + if (ns_g_udpdisp > ns_g_cpus) + ns_g_udpdisp = ns_g_cpus; +#endif + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_INFO, "using %u UDP listener%s per interface", + ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s"); + result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, diff --git a/contrib/bind9/bin/named/named.8 b/contrib/bind9/bin/named/named.8 index 222ff426cabd..b27be3185997 100644 --- a/contrib/bind9/bin/named/named.8 +++ b/contrib/bind9/bin/named/named.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001, 2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -33,7 +33,7 @@ named \- Internet domain name server .SH "SYNOPSIS" .HP 6 -\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] +\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-U\ \fR\fB\fI#listeners\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] .SH "DESCRIPTION" .PP \fBnamed\fR @@ -168,6 +168,19 @@ is defined allows a process with root privileges to escape a chroot jail. .RE .RE .PP +\-U \fI#listeners\fR +.RS 4 +Use +\fI#listeners\fR +worker threads to listen for incoming UDP packets on each address. If not specified, +\fBnamed\fR +will use the number of detected CPUs. If +\fB\-n\fR +has been set to a higher value than the number of CPUs, then +\fB\-U\fR +may be increased as high as that value, but no higher. +.RE +.PP \-u \fIuser\fR .RS 4 Setuid to @@ -267,7 +280,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004\-2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000, 2001, 2003 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/named/named.conf.5 b/contrib/bind9/bin/named/named.conf.5 index 09b147ee7de2..8d0122280b8a 100644 --- a/contrib/bind9/bin/named/named.conf.5 +++ b/contrib/bind9/bin/named/named.conf.5 @@ -289,7 +289,8 @@ options { notify\-delay \fIseconds\fR; notify\-to\-soa \fIboolean\fR; also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) - [ port \fIinteger\fR ]; ... }; + [ port \fIinteger\fR ]; ... + [ key \fIkeyname\fR ] ... }; allow\-notify { \fIaddress_match_element\fR; ... }; forward ( first | only ); forwarders [ port \fIinteger\fR ] { @@ -458,7 +459,8 @@ view \fIstring\fR \fIoptional_class\fR { notify\-delay \fIseconds\fR; notify\-to\-soa \fIboolean\fR; also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) - [ port \fIinteger\fR ]; ... }; + [ port \fIinteger\fR ]; ... + [ key \fIkeyname\fR ] ... }; allow\-notify { \fIaddress_match_element\fR; ... }; forward ( first | only ); forwarders [ port \fIinteger\fR ] { @@ -502,7 +504,7 @@ view \fIstring\fR \fIoptional_class\fR { .RS 4 .nf zone \fIstring\fR \fIoptional_class\fR { - type ( master | slave | stub | hint | + type ( master | slave | stub | hint | redirect | forward | delegation\-only ); file \fIquoted_string\fR; masters [ port \fIinteger\fR ] { @@ -544,7 +546,8 @@ zone \fIstring\fR \fIoptional_class\fR { notify\-delay \fIseconds\fR; notify\-to\-soa \fIboolean\fR; also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) - [ port \fIinteger\fR ]; ... }; + [ port \fIinteger\fR ]; ... + [ key \fIkeyname\fR ] ... }; allow\-notify { \fIaddress_match_element\fR; ... }; forward ( first | only ); forwarders [ port \fIinteger\fR ] { @@ -560,6 +563,7 @@ zone \fIstring\fR \fIoptional_class\fR { max\-refresh\-time \fIinteger\fR; min\-refresh\-time \fIinteger\fR; multi\-master \fIboolean\fR; + request\-ixfr \fIboolean\fR; sig\-validity\-interval \fIinteger\fR; transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; diff --git a/contrib/bind9/bin/named/named.conf.docbook b/contrib/bind9/bin/named/named.conf.docbook index 2527ac3ae7e8..d778706930e0 100644 --- a/contrib/bind9/bin/named/named.conf.docbook +++ b/contrib/bind9/bin/named/named.conf.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + Aug 13, 2004 @@ -326,7 +326,8 @@ options { notify-delay seconds; notify-to-soa boolean; also-notify port integer { ( ipv4_address | ipv6_address ) - port integer ; ... }; + port integer ; ... + key keyname ... }; allow-notify { address_match_element; ... }; forward ( first | only ); @@ -513,7 +514,8 @@ view string optional_class notify-delay seconds; notify-to-soa boolean; also-notify port integer { ( ipv4_address | ipv6_address ) - port integer ; ... }; + port integer ; ... + key keyname ... }; allow-notify { address_match_element; ... }; forward ( first | only ); @@ -563,7 +565,7 @@ view string optional_class ZONE zone string optional_class { - type ( master | slave | stub | hint | + type ( master | slave | stub | hint | redirect | forward | delegation-only ); file quoted_string; @@ -609,7 +611,8 @@ zone string optional_class notify-delay seconds; notify-to-soa boolean; also-notify port integer { ( ipv4_address | ipv6_address ) - port integer ; ... }; + port integer ; ... + key keyname ... }; allow-notify { address_match_element; ... }; forward ( first | only ); @@ -627,6 +630,7 @@ zone string optional_class max-refresh-time integer; min-refresh-time integer; multi-master boolean; + request-ixfr boolean; sig-validity-interval integer; transfer-source ( ipv4_address | * ) diff --git a/contrib/bind9/bin/named/named.conf.html b/contrib/bind9/bin/named/named.conf.html index a8b35edc8602..23d9391af3d0 100644 --- a/contrib/bind9/bin/named/named.conf.html +++ b/contrib/bind9/bin/named/named.conf.html @@ -21,7 +21,7 @@
-
+

Name

named.conf — configuration file for named

@@ -31,7 +31,7 @@

named.conf

-

DESCRIPTION

+

DESCRIPTION

named.conf is the configuration file for named. Statements are enclosed @@ -50,14 +50,14 @@

-

ACL

+

ACL


acl string { address_match_element; ... };

-

KEY

+

KEY


key domain_name {
algorithm string;
@@ -66,7 +66,7 @@ key

-

MASTERS

+

MASTERS


masters string [ port integer ] {
masters | ipv4_address [port integer] |
@@ -75,7 +75,7 @@ masters

-

SERVER

+

SERVER


server ( ipv4_address[/prefixlen] | ipv6_address[/prefixlen] ) {
bogus boolean;
@@ -97,7 +97,7 @@ server

-

TRUSTED-KEYS

+

TRUSTED-KEYS


trusted-keys {
domain_name flags protocol algorithm key; ... 
@@ -105,7 +105,7 @@ trusted-keys

-

MANAGED-KEYS

+

MANAGED-KEYS


managed-keys {
domain_name initial-key flags protocol algorithm key; ... 
@@ -113,7 +113,7 @@ managed-keys

-

CONTROLS

+

CONTROLS


controls {
inet ( ipv4_address | ipv6_address | * )
@@ -125,7 +125,7 @@ controls

-

LOGGING

+

LOGGING


logging {
channel string {
@@ -143,7 +143,7 @@ logging

-

LWRES

+

LWRES


lwres {
listen-on [ port integer ] {
@@ -156,7 +156,7 @@ lwres

-

OPTIONS

+

OPTIONS


options {
avoid-v4-udp-ports { port; ... };
@@ -291,7 +291,8 @@ options notify-delay seconds;
notify-to-soa boolean;
also-notify [ port integer ] { ( ipv4_address | ipv6_address )
- [ port integer ]; ... };
+ [ port integer ]; ...
+ [ key keyname ] ... };
allow-notify { address_match_element; ... };

forward ( first | only );
@@ -360,7 +361,7 @@ options

-

VIEW

+

VIEW


view string optional_class {
match-clients { address_match_element; ... };
@@ -477,7 +478,8 @@ view notify-delay seconds;
notify-to-soa boolean;
also-notify [ port integer ] { ( ipv4_address | ipv6_address )
- [ port integer ]; ... };
+ [ port integer ]; ...
+ [ key keyname ] ... };
allow-notify { address_match_element; ... };

forward ( first | only );
@@ -523,10 +525,10 @@ view

-

ZONE

+

ZONE


zone string optional_class {
- type ( master | slave | stub | hint |
+ type ( master | slave | stub | hint | redirect |
forward | delegation-only );
file quoted_string;

@@ -572,7 +574,8 @@ zone notify-delay seconds;
notify-to-soa boolean;
also-notify [ port integer ] { ( ipv4_address | ipv6_address )
- [ port integer ]; ... };
+ [ port integer ]; ...
+ [ key keyname ] ... };
allow-notify { address_match_element; ... };

forward ( first | only );
@@ -590,6 +593,7 @@ zone max-refresh-time integer;
min-refresh-time integer;
multi-master boolean;
+ request-ixfr boolean;
sig-validity-interval integer;

transfer-source ( ipv4_address | * )
@@ -618,12 +622,12 @@ zone

-

FILES

+

FILES

/etc/named.conf

-

SEE ALSO

+

SEE ALSO

named(8), named-checkconf(8), rndc(8), diff --git a/contrib/bind9/bin/named/named.docbook b/contrib/bind9/bin/named/named.docbook index c748911e24a1..1f08e196e040 100644 --- a/contrib/bind9/bin/named/named.docbook +++ b/contrib/bind9/bin/named/named.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + May 21, 2009 @@ -43,6 +43,8 @@ 2007 2008 2009 + 2011 + 2013 Internet Systems Consortium, Inc. ("ISC") @@ -69,6 +71,7 @@ + @@ -281,6 +284,21 @@ + + -U #listeners + + + Use #listeners + worker threads to listen for incoming UDP packets on each + address. If not specified, named will + use the number of detected CPUs. If + has been set to a higher value than the number of CPUs, + then may be increased as high as that + value, but no higher. + + + + -u user diff --git a/contrib/bind9/bin/named/named.html b/contrib/bind9/bin/named/named.html index cf3cb2678f39..fc8de5147ad8 100644 --- a/contrib/bind9/bin/named/named.html +++ b/contrib/bind9/bin/named/named.html @@ -1,5 +1,5 @@ - + Aug 25, 2009 @@ -42,6 +42,8 @@ 2008 2009 2010 + 2011 + 2012 Internet Systems Consortium, Inc. ("ISC") @@ -424,7 +426,7 @@ - prereq nxdomain + prereq nxdomain domain-name @@ -438,7 +440,7 @@ - prereq yxdomain + prereq yxdomain domain-name @@ -452,7 +454,7 @@ - prereq nxrrset + prereq nxrrset domain-name class type @@ -474,7 +476,7 @@ - prereq yxrrset + prereq yxrrset domain-name class type @@ -496,7 +498,7 @@ - prereq yxrrset + prereq yxrrset domain-name class type @@ -530,7 +532,7 @@ - update delete + update delete domain-name ttl class @@ -556,7 +558,7 @@ - update add + update add domain-name ttl class diff --git a/contrib/bind9/bin/nsupdate/nsupdate.html b/contrib/bind9/bin/nsupdate/nsupdate.html index 5c108e374611..276d4af6fbe1 100644 --- a/contrib/bind9/bin/nsupdate/nsupdate.html +++ b/contrib/bind9/bin/nsupdate/nsupdate.html @@ -1,5 +1,5 @@ - + Feb 19, 2009 @@ -39,7 +39,6 @@ 2009 2010 2011 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/bin/tools/genrandom.html b/contrib/bind9/bin/tools/genrandom.html index f69b7ca2da21..6b7043407973 100644 --- a/contrib/bind9/bin/tools/genrandom.html +++ b/contrib/bind9/bin/tools/genrandom.html @@ -1,5 +1,5 @@ - + DNSSEC, Dynamic Zones, and Automatic Signing @@ -100,8 +100,7 @@ named can search the key directory for keys matching the zone, insert them into the zone, and use them to sign the zone. It will do so only when it receives an - rndc sign <zonename> or - rndc loadkeys <zonename> command. + rndc sign <zonename>. auto-dnssec maintain includes the above @@ -109,12 +108,34 @@ DNSKEY records on schedule according to the keys' timing metadata. (See and for more information.) + + + named will periodically search the key directory + for keys matching the zone, and if the keys' metadata indicates + that any change should be made the zone, such as adding, removing, + or revoking a key, then that action will be carried out. By default, + the key directory is checked for changes every 60 minutes; this period + can be adjusted with the , up + to a maximum of 24 hours. The rndc loadkeys forces + named to check for key updates immediately. + + If keys are present in the key directory the first time the zone - is loaded, it will be signed immediately, without waiting for an + is loaded, the zone will be signed immediately, without waiting for an rndc sign or rndc loadkeys command. (Those commands can still be used when there are unscheduled key changes, however.) + + If you wish the zone to be signed using NSEC3 instead of NSEC, + submit an NSEC3PARAM record via dynamic update prior to the + scheduled publication and activation of the keys. If you wish the + NSEC3 chain to have the OPTOUT bit set, set it in the flags field + of the NSEC3PARAM record. The NSEC3PARAM record will not appear in + the zone immediately, but it will be stored for later reference. When + the zone is signed and the NSEC3 chain is completed, the NSEC3PARAM + record will appear in the zone. + Using the auto-dnssec option requires the zone to be configured to allow dynamic updates, by adding an diff --git a/contrib/bind9/doc/arm/man.arpaname.html b/contrib/bind9/doc/arm/man.arpaname.html index c57540be6fab..45391da16d94 100644 --- a/contrib/bind9/doc/arm/man.arpaname.html +++ b/contrib/bind9/doc/arm/man.arpaname.html @@ -50,20 +50,20 @@

arpaname {ipaddress ...}

-

DESCRIPTION

+

DESCRIPTION

arpaname translates IP addresses (IPv4 and IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names.

-

SEE ALSO

+

SEE ALSO

BIND 9 Administrator Reference Manual.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.ddns-confgen.html b/contrib/bind9/doc/arm/man.ddns-confgen.html index 3555d5152ce4..fed8fbcf7876 100644 --- a/contrib/bind9/doc/arm/man.ddns-confgen.html +++ b/contrib/bind9/doc/arm/man.ddns-confgen.html @@ -50,7 +50,7 @@

ddns-confgen [-a algorithm] [-h] [-k keyname] [-r randomfile] [ -s name | -z zone ] [-q] [name]

-

DESCRIPTION

+

DESCRIPTION

ddns-confgen generates a key for use by nsupdate and named. It simplifies configuration @@ -77,7 +77,7 @@

-

OPTIONS

+

OPTIONS

-a algorithm

@@ -144,7 +144,7 @@

-

SEE ALSO

+

SEE ALSO

nsupdate(1), named.conf(5), named(8), @@ -152,7 +152,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.dig.html b/contrib/bind9/doc/arm/man.dig.html index b2d2b541dd4e..556e34b12b4c 100644 --- a/contrib/bind9/doc/arm/man.dig.html +++ b/contrib/bind9/doc/arm/man.dig.html @@ -52,7 +52,7 @@

dig [global-queryopt...] [query...]

-

DESCRIPTION

+

DESCRIPTION

dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and @@ -99,7 +99,7 @@

-

SIMPLE USAGE

+

SIMPLE USAGE

A typical invocation of dig looks like:

@@ -152,7 +152,7 @@

-

OPTIONS

+

OPTIONS

The -b option sets the source IP address of the query to address. This must be a valid @@ -256,7 +256,7 @@

-

QUERY OPTIONS

+

QUERY OPTIONS

dig provides a number of query options which affect the way in which lookups are made and the results displayed. Some of @@ -341,7 +341,8 @@ policy of the server. AD=1 indicates that all records have been validated as secure and the answer is not from a OPT-OUT range. AD=0 indicate that some part - of the answer was insecure or not validated. + of the answer was insecure or not validated. This + bit is set by default.

+[no]cdflag

@@ -360,15 +361,13 @@

+[no]recurse

- Toggle the setting of the RD (recursion desired) bit in the - query. - This bit is set by default, which means dig - normally sends recursive queries. Recursion is automatically - disabled - when the +nssearch or - +trace query options are - used. -

+ Toggle the setting of the RD (recursion desired) bit + in the query. This bit is set by default, which means + dig normally sends recursive + queries. Recursion is automatically disabled when + the +nssearch or + +trace query options are used. +

+[no]nssearch

When this option is set, dig @@ -380,18 +379,21 @@ zone.

+[no]trace
-

- Toggle tracing of the delegation path from the root name servers - for - the name being looked up. Tracing is disabled by default. When - tracing is enabled, dig makes - iterative queries to - resolve the name being looked up. It will follow referrals from - the - root servers, showing the answer from each server that was used - to - resolve the lookup. -

+
+

+ Toggle tracing of the delegation path from the root + name servers for the name being looked up. Tracing + is disabled by default. When tracing is enabled, + dig makes iterative queries to + resolve the name being looked up. It will follow + referrals from the root servers, showing the answer + from each server that was used to resolve the lookup. +

+

+ +dnssec is also set when +trace is + set to better emulate the default queries from a nameserver. +

+
+[no]cmd

Toggles the printing of the initial comment in the output @@ -418,8 +420,25 @@

+[no]comments

Toggle the display of comment lines in the output. The default - is to - print comments. + is to print comments. +

+
+[no]rrcomments
+

+ Toggle the display of per-record comments in the output (for + example, human-readable key information about DNSKEY records). + The default is not to print record comments unless multiline + mode is active. +

+
+split=W
+

+ Split long hex- or base64-formatted fields in resource + records into chunks of W characters + (where W is rounded up to the nearest + multiple of 4). + +nosplit or + +split=0 causes fields not to be + split at all. The default is 56 characters, or 44 characters + when multiline mode is active.

+[no]stats

@@ -514,9 +533,10 @@

+edns=#

Specify the EDNS version to query with. Valid values - are 0 to 255. Setting the EDNS version will cause a - EDNS query to be sent. +noedns clears the - remembered EDNS version. + are 0 to 255. Setting the EDNS version will cause + a EDNS query to be sent. +noedns + clears the remembered EDNS version. EDNS is set to + 0 by default.

+[no]multiline

@@ -587,7 +607,7 @@

-

MULTIPLE QUERIES

+

MULTIPLE QUERIES

The BIND 9 implementation of dig supports @@ -633,7 +653,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

-

IDN SUPPORT

+

IDN SUPPORT

If dig has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. @@ -647,14 +667,14 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

-

FILES

+

FILES

/etc/resolv.conf

${HOME}/.digrc

-

SEE ALSO

+

SEE ALSO

host(1), named(8), dnssec-keygen(8), @@ -662,7 +682,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr

-

BUGS

+

BUGS

There are probably too many query options.

diff --git a/contrib/bind9/doc/arm/man.dnssec-dsfromkey.html b/contrib/bind9/doc/arm/man.dnssec-dsfromkey.html index 6d8eeabe6f43..bb8d13607fff 100644 --- a/contrib/bind9/doc/arm/man.dnssec-dsfromkey.html +++ b/contrib/bind9/doc/arm/man.dnssec-dsfromkey.html @@ -22,7 +22,7 @@ - + @@ -31,7 +31,7 @@ dnssec-dsfromkey -Prev  +Prev  Manual pages  Next @@ -47,18 +47,18 @@

Synopsis

-

dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] [-l domain] {keyfile}

-

dnssec-dsfromkey {-s} [-1] [-2] [-a alg] [-K directory] [-l domain] [-s] [-c class] [-f file] [-A] [-v level] {dnsname}

+

dnssec-dsfromkey [-v level] [-1] [-2] [-a alg] [-l domain] [-T TTL] {keyfile}

+

dnssec-dsfromkey {-s} [-1] [-2] [-a alg] [-K directory] [-l domain] [-s] [-c class] [-T TTL] [-f file] [-A] [-v level] {dnsname}

-

DESCRIPTION

+

DESCRIPTION

dnssec-dsfromkey outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s).

-

OPTIONS

+

OPTIONS

-1

@@ -76,6 +76,10 @@ SHA-256 (SHA256), GOST or SHA-384 (SHA384). These values are case insensitive.

+
-T TTL
+

+ Specifies the TTL of the DS records. +

-K directory

Look for key files (or, in keyset mode, @@ -83,12 +87,23 @@ directory.

-f file
-

+

+

Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from file. If the zone name is the same as file, then it may be omitted. -

+

+

+ If file is set to "-", then + the zone data is read from the standard input. This makes it + possible to use the output of the dig + command as input, as in: +

+

+ dig dnskey example.com | dnssec-dsfromkey -f - example.com +

+
-A

Include ZSK's when generating DS records. Without this option, @@ -120,7 +135,7 @@

-

EXAMPLE

+

EXAMPLE

To build the SHA-256 DS RR from the Kexample.com.+003+26160 @@ -135,7 +150,7 @@

-

FILES

+

FILES

The keyfile can be designed by the key identification Knnnn.+aaa+iiiii or the full file name @@ -149,13 +164,13 @@

-

CAVEAT

+

CAVEAT

A keyfile error can give a "file not found" even if the file exists.

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -165,7 +180,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

@@ -175,13 +190,14 @@ +Prev  - + diff --git a/contrib/bind9/doc/arm/man.dnssec-keyfromlabel.html b/contrib/bind9/doc/arm/man.dnssec-keyfromlabel.html index b691828823be..dad88378e892 100644 --- a/contrib/bind9/doc/arm/man.dnssec-keyfromlabel.html +++ b/contrib/bind9/doc/arm/man.dnssec-keyfromlabel.html @@ -47,10 +47,10 @@

Synopsis

-

dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-k] [-K directory] [-n nametype] [-P date/offset] [-p protocol] [-R date/offset] [-t type] [-v level] [-y] {name}

+

dnssec-keyfromlabel {-l label} [-3] [-a algorithm] [-A date/offset] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-I date/offset] [-k] [-K directory] [-L ttl] [-n nametype] [-P date/offset] [-p protocol] [-R date/offset] [-t type] [-v level] [-y] {name}

-

DESCRIPTION

+

DESCRIPTION

dnssec-keyfromlabel gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 @@ -63,7 +63,7 @@

-

OPTIONS

+

OPTIONS

-a algorithm
@@ -154,6 +154,15 @@

Generate KEY records rather than DNSKEY records.

+
-L ttl
+

+ Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. +

-p protocol

Sets the protocol value for the key. The protocol @@ -183,7 +192,7 @@

-

TIMING OPTIONS

+

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as @@ -230,7 +239,7 @@

-

GENERATED KEY FILES

+

GENERATED KEY FILES

When dnssec-keyfromlabel completes successfully, @@ -269,7 +278,7 @@

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -277,7 +286,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.dnssec-keygen.html b/contrib/bind9/doc/arm/man.dnssec-keygen.html index 2852022cdb81..8f846e0c34e6 100644 --- a/contrib/bind9/doc/arm/man.dnssec-keygen.html +++ b/contrib/bind9/doc/arm/man.dnssec-keygen.html @@ -47,10 +47,10 @@

Synopsis

-

dnssec-keygen [-a algorithm] [-b keysize] [-n nametype] [-3] [-A date/offset] [-C] [-c class] [-D date/offset] [-E engine] [-e] [-f flag] [-G] [-g generator] [-h] [-I date/offset] [-i interval] [-K directory] [-k] [-P date/offset] [-p protocol] [-q] [-R date/offset] [-r randomdev] [-S key] [-s strength] [-t type] [-v level] [-z] {name}

+

dnssec-keygen [-a algorithm] [-b keysize] [-n nametype] [-3] [-A date/offset] [-C] [-c class] [-D date/offset] [-E engine] [-f flag] [-G] [-g generator] [-h] [-I date/offset] [-i interval] [-K directory] [-L ttl] [-k] [-P date/offset] [-p protocol] [-q] [-R date/offset] [-r randomdev] [-S key] [-s strength] [-t type] [-v level] [-z] {name}

-

DESCRIPTION

+

DESCRIPTION

dnssec-keygen generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with @@ -64,7 +64,7 @@

-

OPTIONS

+

OPTIONS

-a algorithm
@@ -157,10 +157,6 @@ support it defaults to pkcs11; the empty name resets it to no engine.

-
-e
-

- If generating an RSAMD5/RSASHA1 key, use a large exponent. -

-f flag

Set the specified flag in the flag field of the KEY/DNSKEY record. @@ -191,6 +187,15 @@

Deprecated in favor of -T KEY.

+
-L ttl
+

+ Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. +

-p protocol

Sets the protocol value for the generated key. The protocol @@ -269,7 +274,7 @@

-

TIMING OPTIONS

+

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as @@ -340,7 +345,7 @@

-

GENERATED KEYS

+

GENERATED KEYS

When dnssec-keygen completes successfully, @@ -386,7 +391,7 @@

-

EXAMPLE

+

EXAMPLE

To generate a 768-bit DSA key for the domain example.com, the following command would be @@ -407,7 +412,7 @@

-

SEE ALSO

+

SEE ALSO

dnssec-signzone(8), BIND 9 Administrator Reference Manual, RFC 2539, @@ -416,7 +421,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.dnssec-revoke.html b/contrib/bind9/doc/arm/man.dnssec-revoke.html index b1eb6914fa87..c6490eff2b85 100644 --- a/contrib/bind9/doc/arm/man.dnssec-revoke.html +++ b/contrib/bind9/doc/arm/man.dnssec-revoke.html @@ -50,7 +50,7 @@

dnssec-revoke [-hr] [-v level] [-K directory] [-E engine] [-f] [-R] {keyfile}

-

DESCRIPTION

+

DESCRIPTION

dnssec-revoke reads a DNSSEC key file, sets the REVOKED bit on the key as defined in RFC 5011, and creates a new pair of key files containing the @@ -58,7 +58,7 @@

-

OPTIONS

+

OPTIONS

-h

@@ -96,14 +96,14 @@

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), BIND 9 Administrator Reference Manual, RFC 5011.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.dnssec-settime.html b/contrib/bind9/doc/arm/man.dnssec-settime.html index 541223ccda8c..3e121c4e2645 100644 --- a/contrib/bind9/doc/arm/man.dnssec-settime.html +++ b/contrib/bind9/doc/arm/man.dnssec-settime.html @@ -47,10 +47,10 @@

Synopsis

-

dnssec-settime [-f] [-K directory] [-P date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-h] [-v level] [-E engine] {keyfile}

+

dnssec-settime [-f] [-K directory] [-L ttl] [-P date/offset] [-A date/offset] [-R date/offset] [-I date/offset] [-D date/offset] [-h] [-v level] [-E engine] {keyfile}

-

DESCRIPTION

+

DESCRIPTION

dnssec-settime reads a DNSSEC private key file and sets the key timing metadata as specified by the -P, -A, @@ -76,7 +76,7 @@

-

OPTIONS

+

OPTIONS

-f

@@ -93,6 +93,15 @@

Sets the directory in which the key files are to reside.

+
-L ttl
+

+ Sets the default TTL to use for this key when it is converted + into a DNSKEY RR. If the key is imported into a zone, + this is the TTL that will be used for it, unless there was + already a DNSKEY RRset in place, in which case the existing TTL + would take precedence. Setting the default TTL to + 0 or none removes it. +

-h

Emit usage message and exit. @@ -109,7 +118,7 @@

-

TIMING OPTIONS

+

TIMING OPTIONS

Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '-', it is interpreted as @@ -188,7 +197,7 @@

-

PRINTING OPTIONS

+

PRINTING OPTIONS

dnssec-settime can also be used to print the timing metadata associated with a key. @@ -214,7 +223,7 @@

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), dnssec-signzone(8), BIND 9 Administrator Reference Manual, @@ -222,7 +231,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.dnssec-signzone.html b/contrib/bind9/doc/arm/man.dnssec-signzone.html index 4f73bf4dfb33..290e7700973c 100644 --- a/contrib/bind9/doc/arm/man.dnssec-signzone.html +++ b/contrib/bind9/doc/arm/man.dnssec-signzone.html @@ -23,7 +23,7 @@ - + -
-Prev  Up  Next
host  +dnssec-coverage  Home  dnssec-keyfromlabel Prev  Manual pages Next + Next
@@ -47,10 +47,10 @@

Synopsis

-

dnssec-signzone [-a] [-c class] [-d directory] [-E engine] [-e end-time] [-f output-file] [-g] [-h] [-K directory] [-k key] [-l domain] [-i interval] [-I input-format] [-j jitter] [-N soa-serial-format] [-o origin] [-O output-format] [-p] [-P] [-r randomdev] [-S] [-s start-time] [-T ttl] [-t] [-u] [-v level] [-x] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

+

dnssec-signzone [-a] [-c class] [-d directory] [-D] [-E engine] [-e end-time] [-f output-file] [-g] [-h] [-K directory] [-k key] [-L serial] [-l domain] [-i interval] [-I input-format] [-j jitter] [-N soa-serial-format] [-o origin] [-O output-format] [-P] [-p] [-R] [-r randomdev] [-S] [-s start-time] [-T ttl] [-t] [-u] [-v level] [-X extended end-time] [-x] [-z] [-3 salt] [-H iterations] [-A] {zonefile} [key...]

-

DESCRIPTION

+

DESCRIPTION

dnssec-signzone signs a zone. It generates NSEC and RRSIG records and produces a signed version of the @@ -61,7 +61,7 @@

-

OPTIONS

+

OPTIONS

-a

@@ -85,6 +85,17 @@ Look for dsset- or keyset- files in directory.

+
-D
+

+ Output only those record types automatically managed by + dnssec-signzone, i.e. RRSIG, NSEC, + NSEC3 and NSEC3PARAM records. If smart signing + (-S) is used, DNSKEY records are also + included. The resulting file can be included in the original + zone file with $INCLUDE. This option + cannot be combined with -O raw or serial + number updating. +

-E engine

Uses a crypto hardware (OpenSSL engine) for the crypto operations @@ -136,12 +147,36 @@ end-time must be later than start-time.

+
-X extended end-time
+
+

+ Specify the date and time when the generated RRSIG records + for the DNSKEY RRset will expire. This is to be used in cases + when the DNSKEY signatures need to persist longer than + signatures on other records; e.g., when the private component + of the KSK is kept offline and the KSK signature is to be + refreshed manually. +

+

+ As with start-time, an absolute + time is indicated in YYYYMMDDHHMMSS notation. A time relative + to the start time is indicated with +N, which is N seconds from + the start time. A time relative to the current time is + indicated with now+N. If no extended end-time is + specified, the value of end-time is used as + the default. (end-time, in turn, defaults to + 30 days from the start time.) extended end-time + must be later than start-time. +

+
-f output-file

The name of the output file containing the signed zone. The default is to append .signed to - the - input filename. + the input filename. If output-file is + set to "-", then the signed zone is + written to the standard output, with a default output + format of "full".

-h

@@ -202,6 +237,12 @@ validators need to refetch at mostly the same time.

+
-L serial
+

+ When writing a signed zone to 'raw' format, set the "source serial" + value in the header to the specified serial number. (This is + expected to be used primarily for testing purposes.) +

-n ncpus

Specifies the number of threads to use. By default, one @@ -235,7 +276,15 @@

The format of the output file containing the signed zone. Possible formats are "text" (default) - and "raw". + "full", which is text output in a + format suitable for processing by external scripts, + and "raw" or "raw=N", + which store the zone in a binary format for rapid loading + by named. "raw=N" + specifies the format version of the raw zone file: if N + is 0, the raw file can be read by any version of + named; if N is 1, the file can be + read by release 9.9.0 or higher. The default is 1.

-p

@@ -257,6 +306,22 @@ This option skips these tests.

+
-R
+
+

+ Remove signatures from keys that no longer exist. +

+

+ Normally, when a previously-signed zone is passed as input + to the signer, and a DNSKEY record has been removed and + replaced with a new one, signatures from the old key + that are still within their validity period are retained. + This allows the zone to continue to validate with cached + copies of the old DNSKEY RRset. The -R forces + dnssec-signzone to remove all orphaned + signatures. +

+
-r randomdev

Specifies the source of randomness. If the operating @@ -315,15 +380,17 @@

-T ttl

- Specifies the TTL to be used for new DNSKEY records imported - into the zone from the key repository. If not specified, - the default is the minimum TTL value from the zone's SOA + Specifies a TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not + specified, the default is the TTL value from the zone's SOA record. This option is ignored when signing without -S, since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match - them. + them, or if any of the imported DNSKEY records had a default + TTL value. In the event of a a conflict between TTL values in + imported keys, the shortest one is used.

-t

@@ -397,7 +464,7 @@

-

EXAMPLE

+

EXAMPLE

The following command signs the example.com zone with the DSA key generated by dnssec-keygen @@ -427,14 +494,14 @@ db.example.com.signed %

-

SEE ALSO

+

SEE ALSO

dnssec-keygen(8), BIND 9 Administrator Reference Manual, RFC 4033.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

@@ -446,14 +513,14 @@ db.example.com.signed Prev  UpNextNext dnssec-settime  Homenamed-checkconfdnssec-verify diff --git a/contrib/bind9/doc/arm/man.dnssec-verify.html b/contrib/bind9/doc/arm/man.dnssec-verify.html new file mode 100644 index 000000000000..d8a0bf0ebb4b --- /dev/null +++ b/contrib/bind9/doc/arm/man.dnssec-verify.html @@ -0,0 +1,156 @@ + + + + + +dnssec-verify + + + + + + + + +
+
+
+

Name

+

dnssec-verify — DNSSEC zone verification tool

+
+
+

Synopsis

+

dnssec-verify [-c class] [-E engine] [-I input-format] [-o origin] [-v level] [-x] [-z] {zonefile}

+
+
+

DESCRIPTION

+

dnssec-verify + verifies that a zone is fully signed for each algorithm found + in the DNSKEY RRset for the zone, and that the NSEC / NSEC3 + chains are complete. +

+
+
+

OPTIONS

+
+
-c class
+

+ Specifies the DNS class of the zone. +

+
-I input-format
+

+ The format of the input zone file. + Possible formats are "text" (default) + and "raw". + This option is primarily intended to be used for dynamic + signed zones so that the dumped zone file in a non-text + format containing updates can be verified independently. + The use of this option does not make much sense for + non-dynamic zones. +

+
-o origin
+

+ The zone origin. If not specified, the name of the zone file + is assumed to be the origin. +

+
-v level
+

+ Sets the debugging level. +

+
-x
+

+ Only verify that the DNSKEY RRset is signed with key-signing + keys. Without this flag, it is assumed that the DNSKEY RRset + will be signed by all active keys. When this flag is set, + it will not be an error if the DNSKEY RRset is not signed + by zone-signing keys. This corresponds to the -x + option in dnssec-signzone. +

+
-z
+
+

+ Ignore the KSK flag on the keys when determining whether + the zone if correctly signed. Without this flag it is + assumed that there will be a non-revoked, self-signed + DNSKEY with the KSK flag set for each algorithm and + that RRsets other than DNSKEY RRset will be signed with + a different DNSKEY without the KSK flag set. +

+

+ With this flag set, we only require that for each algorithm, + there will be at least one non-revoked, self-signed DNSKEY, + regardless of the KSK flag state, and that other RRsets + will be signed by a non-revoked key for the same algorithm + that includes the self-signed key; the same key may be used + for both purposes. This corresponds to the -z + option in dnssec-signzone. +

+
+
zonefile
+

+ The file containing the zone to be signed. +

+
+
+
+

SEE ALSO

+

+ dnssec-signzone(8), + BIND 9 Administrator Reference Manual, + RFC 4033. +

+
+
+

AUTHOR

+

Internet Systems Consortium +

+
+
+ + + diff --git a/contrib/bind9/doc/arm/man.genrandom.html b/contrib/bind9/doc/arm/man.genrandom.html index 596dddacce7e..e7f0eebaf6ff 100644 --- a/contrib/bind9/doc/arm/man.genrandom.html +++ b/contrib/bind9/doc/arm/man.genrandom.html @@ -50,7 +50,7 @@

genrandom [-n number] {size} {filename}

-

DESCRIPTION

+

DESCRIPTION

genrandom generates a file or a set of files containing a specified quantity @@ -59,7 +59,7 @@

-

ARGUMENTS

+

ARGUMENTS

-n number

@@ -77,14 +77,14 @@

-

SEE ALSO

+

SEE ALSO

rand(3), arc4random(3)

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.host.html b/contrib/bind9/doc/arm/man.host.html index f4f0ef800182..2166dd224a70 100644 --- a/contrib/bind9/doc/arm/man.host.html +++ b/contrib/bind9/doc/arm/man.host.html @@ -23,7 +23,7 @@ - +
-

DESCRIPTION

+

DESCRIPTION

host is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. @@ -202,7 +202,7 @@

-

IDN SUPPORT

+

IDN SUPPORT

If host has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. @@ -216,12 +216,12 @@

-

FILES

+

FILES

/etc/resolv.conf

-

SEE ALSO

+

SEE ALSO

dig(1), named(8).

@@ -234,13 +234,13 @@ Prev  UpNextNext dig  Homednssec-dsfromkeydnssec-checkds diff --git a/contrib/bind9/doc/arm/man.isc-hmac-fixup.html b/contrib/bind9/doc/arm/man.isc-hmac-fixup.html index 9c2a9611237a..5b35c3854ec8 100644 --- a/contrib/bind9/doc/arm/man.isc-hmac-fixup.html +++ b/contrib/bind9/doc/arm/man.isc-hmac-fixup.html @@ -50,7 +50,7 @@

isc-hmac-fixup {algorithm} {secret}

-

DESCRIPTION

+

DESCRIPTION

Versions of BIND 9 up to and including BIND 9.6 had a bug causing HMAC-SHA* TSIG keys which were longer than the digest length of the @@ -76,7 +76,7 @@

-

SECURITY CONSIDERATIONS

+

SECURITY CONSIDERATIONS

Secrets that have been converted by isc-hmac-fixup are shortened, but as this is how the HMAC protocol works in @@ -87,14 +87,14 @@

-

SEE ALSO

+

SEE ALSO

BIND 9 Administrator Reference Manual, RFC 2104.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.named-checkconf.html b/contrib/bind9/doc/arm/man.named-checkconf.html index 9a2f687843c2..d120cb44d1bd 100644 --- a/contrib/bind9/doc/arm/man.named-checkconf.html +++ b/contrib/bind9/doc/arm/man.named-checkconf.html @@ -22,7 +22,7 @@ - + @@ -31,7 +31,7 @@ named-checkconf -Prev  +Prev  Manual pages  Next @@ -50,7 +50,7 @@

named-checkconf [-h] [-v] [-j] [-t directory] {filename} [-p] [-z]

-

DESCRIPTION

+

DESCRIPTION

named-checkconf checks the syntax, but not the semantics, of a named configuration file. The file is parsed @@ -70,7 +70,7 @@

-

OPTIONS

+

OPTIONS

-h

@@ -109,21 +109,21 @@

-

RETURN VALUES

+

RETURN VALUES

named-checkconf returns an exit status of 1 if errors were detected and 0 otherwise.

-

SEE ALSO

+

SEE ALSO

named(8), named-checkzone(8), BIND 9 Administrator Reference Manual.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

@@ -133,14 +133,14 @@ +Prev  +dnssec-verify  diff --git a/contrib/bind9/doc/arm/man.named-checkzone.html b/contrib/bind9/doc/arm/man.named-checkzone.html index 78fade2cf738..b828f19764c8 100644 --- a/contrib/bind9/doc/arm/man.named-checkzone.html +++ b/contrib/bind9/doc/arm/man.named-checkzone.html @@ -47,11 +47,11 @@

Synopsis

-

named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-o filename] [-r mode] [-s style] [-S mode] [-t directory] [-T mode] [-w directory] [-D] [-W mode] {zonename} {filename}

-

named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-n mode] [-r mode] [-s style] [-t directory] [-T mode] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

+

named-checkzone [-d] [-h] [-j] [-q] [-v] [-c class] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-M mode] [-n mode] [-L serial] [-o filename] [-r mode] [-s style] [-S mode] [-t directory] [-T mode] [-w directory] [-D] [-W mode] {zonename} {filename}

+

named-compilezone [-d] [-j] [-q] [-v] [-c class] [-C mode] [-f format] [-F format] [-i mode] [-k mode] [-m mode] [-n mode] [-L serial] [-r mode] [-s style] [-t directory] [-T mode] [-w directory] [-D] [-W mode] {-o filename} {zonename} {filename}

-

DESCRIPTION

+

DESCRIPTION

named-checkzone checks the syntax and integrity of a zone file. It performs the same checks as named does when loading a @@ -71,7 +71,7 @@

-

OPTIONS

+

OPTIONS

-d

@@ -146,14 +146,24 @@ and "raw".

-F format
-

+

+

Specify the format of the output file specified. - Possible formats are "text" (default) - and "raw". For named-checkzone, this does not cause any effects unless it dumps the zone contents. -

+

+

+ Possible formats are "text" (default) + and "raw" or "raw=N", + which store the zone in a binary format for rapid loading + by named. "raw=N" + specifies the format version of the raw zone file: if N + is 0, the raw file can be read by any version of + named; if N is 1, the file can be read + by release 9.9.0 or higher. The default is 1. +

+
-k mode

Perform "check-names" checks with the @@ -164,6 +174,12 @@ (default for named-checkzone) and "ignore".

+
-L serial
+

+ When compiling a zone to 'raw' format, set the "source serial" + value in the header to the specified serial number. (This is + expected to be used primarily for testing purposes.) +

-m mode

Specify whether MX records should be checked to see if they @@ -272,14 +288,14 @@

-

RETURN VALUES

+

RETURN VALUES

named-checkzone returns an exit status of 1 if errors were detected and 0 otherwise.

-

SEE ALSO

+

SEE ALSO

named(8), named-checkconf(8), RFC 1035, @@ -287,7 +303,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.named-journalprint.html b/contrib/bind9/doc/arm/man.named-journalprint.html index 2869ceaf3f67..5c1f3db111f9 100644 --- a/contrib/bind9/doc/arm/man.named-journalprint.html +++ b/contrib/bind9/doc/arm/man.named-journalprint.html @@ -50,7 +50,7 @@

named-journalprint {journal}

-

DESCRIPTION

+

DESCRIPTION

named-journalprint prints the contents of a zone journal file in a human-readable @@ -76,7 +76,7 @@

-

SEE ALSO

+

SEE ALSO

named(8), nsupdate(8), @@ -84,7 +84,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.named.html b/contrib/bind9/doc/arm/man.named.html index c7371d2d2a69..02d61353a8c6 100644 --- a/contrib/bind9/doc/arm/man.named.html +++ b/contrib/bind9/doc/arm/man.named.html @@ -47,10 +47,10 @@

Synopsis

-

named [-4] [-6] [-c config-file] [-d debug-level] [-E engine-name] [-f] [-g] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-u user] [-v] [-V] [-x cache-file]

+

named [-4] [-6] [-c config-file] [-d debug-level] [-E engine-name] [-f] [-g] [-m flag] [-n #cpus] [-p port] [-s] [-S #max-socks] [-t directory] [-U #listeners] [-u user] [-v] [-V] [-x cache-file]

-

DESCRIPTION

+

DESCRIPTION

named is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more @@ -65,7 +65,7 @@

-

OPTIONS

+

OPTIONS

-4

@@ -196,6 +196,16 @@

+
-U #listeners
+

+ Use #listeners + worker threads to listen for incoming UDP packets on each + address. If not specified, named will + use the number of detected CPUs. If -n + has been set to a higher value than the number of CPUs, + then -U may be increased as high as that + value, but no higher. +

-u user

Setuid @@ -246,7 +256,7 @@

-

SIGNALS

+

SIGNALS

In routine operation, signals should not be used to control the nameserver; rndc should be used @@ -267,7 +277,7 @@

-

CONFIGURATION

+

CONFIGURATION

The named configuration file is too complex to describe in detail here. A complete description is provided @@ -284,7 +294,7 @@

-

FILES

+

FILES

/etc/named.conf

@@ -297,7 +307,7 @@

-

SEE ALSO

+

SEE ALSO

RFC 1033, RFC 1034, RFC 1035, @@ -310,7 +320,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.nsec3hash.html b/contrib/bind9/doc/arm/man.nsec3hash.html index 11df51863847..bdba8a683d2a 100644 --- a/contrib/bind9/doc/arm/man.nsec3hash.html +++ b/contrib/bind9/doc/arm/man.nsec3hash.html @@ -48,7 +48,7 @@

nsec3hash {salt} {algorithm} {iterations} {domain}

-

DESCRIPTION

+

DESCRIPTION

nsec3hash generates an NSEC3 hash based on a set of NSEC3 parameters. This can be used to check the validity @@ -56,7 +56,7 @@

-

ARGUMENTS

+

ARGUMENTS

salt

@@ -80,14 +80,14 @@

-

SEE ALSO

+

SEE ALSO

BIND 9 Administrator Reference Manual, RFC 5155.

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.nsupdate.html b/contrib/bind9/doc/arm/man.nsupdate.html index d7f164ef1fe1..6793b42389cb 100644 --- a/contrib/bind9/doc/arm/man.nsupdate.html +++ b/contrib/bind9/doc/arm/man.nsupdate.html @@ -50,7 +50,7 @@

nsupdate [-d] [-D] [[-g] | [-o] | [-l] | [-y [hmac:]keyname:secret] | [-k keyfile]] [-t timeout] [-u udptimeout] [-r udpretries] [-R randomdev] [-v] [filename]

-

DESCRIPTION

+

DESCRIPTION

nsupdate is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. @@ -210,7 +210,7 @@

-

INPUT FORMAT

+

INPUT FORMAT

nsupdate reads input from filename @@ -349,7 +349,7 @@ realm is specified the saved realm is cleared.

- prereq nxdomain + [prereq] nxdomain {domain-name}

@@ -357,7 +357,7 @@ domain-name.

- prereq yxdomain + [prereq] yxdomain {domain-name}

@@ -366,7 +366,7 @@ exists (has as at least one resource record, of any type).

- prereq nxrrset + [prereq] nxrrset {domain-name} [class] {type} @@ -382,7 +382,7 @@ is omitted, IN (internet) is assumed.

- prereq yxrrset + [prereq] yxrrset {domain-name} [class] {type} @@ -399,7 +399,7 @@ is omitted, IN (internet) is assumed.

- prereq yxrrset + [prereq] yxrrset {domain-name} [class] {type} @@ -428,7 +428,7 @@ RDATA.

- update delete + [update] del[ete] {domain-name} [ttl] [class] @@ -449,7 +449,7 @@ is ignored, and is only allowed for compatibility.

- update add + [update] add {domain-name} {ttl} [class] @@ -498,7 +498,7 @@

-

EXAMPLES

+

EXAMPLES

The examples below show how nsupdate @@ -552,7 +552,7 @@

-

FILES

+

FILES

/etc/resolv.conf

@@ -575,7 +575,7 @@

-

SEE ALSO

+

SEE ALSO

RFC 2136, RFC 3007, @@ -590,7 +590,7 @@

-

BUGS

+

BUGS

The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library diff --git a/contrib/bind9/doc/arm/man.rndc-confgen.html b/contrib/bind9/doc/arm/man.rndc-confgen.html index 977ec220457d..1ad009bffb17 100644 --- a/contrib/bind9/doc/arm/man.rndc-confgen.html +++ b/contrib/bind9/doc/arm/man.rndc-confgen.html @@ -50,7 +50,7 @@

rndc-confgen [-a] [-b keysize] [-c keyfile] [-h] [-k keyname] [-p port] [-r randomfile] [-s address] [-t chrootdir] [-u user]

-

DESCRIPTION

+

DESCRIPTION

rndc-confgen generates configuration files for rndc. It can be used as a @@ -66,7 +66,7 @@

-

OPTIONS

+

OPTIONS

-a
@@ -173,7 +173,7 @@
-

EXAMPLES

+

EXAMPLES

To allow rndc to be used with no manual configuration, run @@ -190,7 +190,7 @@

-

SEE ALSO

+

SEE ALSO

rndc(8), rndc.conf(5), named(8), @@ -198,7 +198,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.rndc.conf.html b/contrib/bind9/doc/arm/man.rndc.conf.html index ebb4e40dd4ff..6b9ea5fb7d73 100644 --- a/contrib/bind9/doc/arm/man.rndc.conf.html +++ b/contrib/bind9/doc/arm/man.rndc.conf.html @@ -50,7 +50,7 @@

rndc.conf

-

DESCRIPTION

+

DESCRIPTION

rndc.conf is the configuration file for rndc, the BIND 9 name server control utility. This file has a similar structure and syntax to @@ -135,7 +135,7 @@

-

EXAMPLE

+

EXAMPLE

       options {
         default-server  localhost;
@@ -209,7 +209,7 @@
     

-

NAME SERVER CONFIGURATION

+

NAME SERVER CONFIGURATION

The name server must be configured to accept rndc connections and to recognize the key specified in the rndc.conf @@ -219,7 +219,7 @@

-

SEE ALSO

+

SEE ALSO

rndc(8), rndc-confgen(8), mmencode(1), @@ -227,7 +227,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/man.rndc.html b/contrib/bind9/doc/arm/man.rndc.html index d433baf5fa0a..059f7263ca75 100644 --- a/contrib/bind9/doc/arm/man.rndc.html +++ b/contrib/bind9/doc/arm/man.rndc.html @@ -50,7 +50,7 @@

rndc [-b source-address] [-c config-file] [-k key-file] [-s server] [-p port] [-V] [-y key_id] {command}

-

DESCRIPTION

+

DESCRIPTION

rndc controls the operation of a name server. It supersedes the ndc utility @@ -79,7 +79,7 @@

-

OPTIONS

+

OPTIONS

-b source-address

@@ -151,7 +151,7 @@

-

LIMITATIONS

+

LIMITATIONS

rndc does not yet support all the commands of the BIND 8 ndc utility. @@ -165,7 +165,7 @@

-

SEE ALSO

+

SEE ALSO

rndc.conf(5), rndc-confgen(8), named(8), @@ -175,7 +175,7 @@

-

AUTHOR

+

AUTHOR

Internet Systems Consortium

diff --git a/contrib/bind9/doc/arm/pkcs11.xml b/contrib/bind9/doc/arm/pkcs11.xml index 2eb85cb02042..8a0062f4adb4 100644 --- a/contrib/bind9/doc/arm/pkcs11.xml +++ b/contrib/bind9/doc/arm/pkcs11.xml @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + PKCS #11 (Cryptoki) support diff --git a/contrib/bind9/doc/misc/options b/contrib/bind9/doc/misc/options index 9cfc5a600e4d..2c9cddde4bbe 100644 --- a/contrib/bind9/doc/misc/options +++ b/contrib/bind9/doc/misc/options @@ -67,8 +67,9 @@ options { allow-update { ; ... }; allow-update-forwarding { ; ... }; allow-v6-synthesis { ; ... }; // obsolete - also-notify [ port ] { ( | - ) [ port ]; ... }; + also-notify [ port ] { ( | [ + port ] | [ port ] ) [ key + ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; @@ -115,9 +116,11 @@ options { dnssec-accept-expired ; dnssec-dnskey-kskonly ; dnssec-enable ; + dnssec-loadkeys-interval ; dnssec-lookaside ( trust-anchor | auto | no ); dnssec-must-be-secure ; dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); dual-stack-servers [ port ] { ( [ port ] | [ port ] | @@ -141,6 +144,7 @@ options { host-statistics ; // not implemented host-statistics-max ; // not implemented hostname ( | none ); + inline-signing ; interface-interval ; ixfr-from-differences ; key-directory ; @@ -160,6 +164,7 @@ options { max-ncache-ttl ; max-refresh-time ; max-retry-time ; + max-rsa-exponent-size ; max-transfer-idle-in ; max-transfer-idle-out ; max-transfer-time-in ; @@ -194,6 +199,7 @@ options { recursion ; recursive-clients ; request-ixfr ; + request-ixfr ; request-nsid ; reserved-sockets ; resolver-query-timeout ; @@ -209,6 +215,7 @@ options { secroots-file ; serial-queries ; // obsolete serial-query-rate ; + serial-update-method ( increment | unixtime ); server-id ( | none | hostname ); session-keyalg ; session-keyfile ( | none ); @@ -247,7 +254,7 @@ options { version ( | none ); zero-no-soa-ttl ; zero-no-soa-ttl-cache ; - zone-statistics ; + zone-statistics ; }; server { @@ -293,8 +300,9 @@ view { allow-update { ; ... }; allow-update-forwarding { ; ... }; allow-v6-synthesis { ; ... }; // obsolete - also-notify [ port ] { ( | - ) [ port ]; ... }; + also-notify [ port ] { ( | [ + port ] | [ port ] ) [ key + ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; @@ -337,9 +345,11 @@ view { dnssec-accept-expired ; dnssec-dnskey-kskonly ; dnssec-enable ; + dnssec-loadkeys-interval ; dnssec-lookaside ( trust-anchor | auto | no ); dnssec-must-be-secure ; dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); dnssec-validation ( yes | no | auto ); dual-stack-servers [ port ] { ( [ port ] | [ port ] | @@ -354,6 +364,7 @@ view { forward ( first | only ); forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; ixfr-from-differences ; key { algorithm ; @@ -401,6 +412,7 @@ view { queryport-pool-updateinterval ; // obsolete recursion ; request-ixfr ; + request-ixfr ; request-nsid ; resolver-query-timeout ; response-policy { zone [ policy ( given | disabled @@ -412,6 +424,7 @@ view { root-delegation-only [ exclude { ; ... } ]; rrset-order { [ class ] [ type ] [ name ] ; ... }; + serial-update-method ( increment | unixtime ); server { bogus ; edns ; @@ -459,8 +472,9 @@ view { allow-transfer { ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; - also-notify [ port ] { ( | - ) [ port ]; ... }; + also-notify [ port ] { ( | + [ port ] | [ + port ] ) [ key ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( @@ -479,11 +493,14 @@ view { delegation-only ; dialup ; dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); file ; forward ( first | only ); forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; ixfr-base ; // obsolete ixfr-from-differences ; ixfr-tmp-file ; // obsolete @@ -515,6 +532,8 @@ view { nsec3-test-zone ; // test only pubkey ; // obsolete + request-ixfr ; + serial-update-method ( increment | unixtime ); server-addresses { ( | ) [ port ]; ... }; server-names { ; ... }; @@ -528,7 +547,7 @@ view { | * ) ]; try-tcp-refresh ; type ( master | slave | stub | static-stub | hint | forward - | delegation-only ); + | delegation-only | redirect ); update-check-ksk ; update-policy ( local | { ( grant | deny ) ( name | subdomain | wildcard | self | selfsub | selfwild | @@ -537,9 +556,9 @@ view { ] ; ... }; use-alt-transfer-source ; zero-no-soa-ttl ; - zone-statistics ; + zone-statistics ; }; - zone-statistics ; + zone-statistics ; }; zone { @@ -549,8 +568,9 @@ zone { allow-transfer { ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; - also-notify [ port ] { ( | - ) [ port ]; ... }; + also-notify [ port ] { ( | [ + port ] | [ port ] ) [ key + ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ]; alt-transfer-source-v6 ( | * ) [ port ( | * ) ]; @@ -568,11 +588,14 @@ zone { delegation-only ; dialup ; dnssec-dnskey-kskonly ; + dnssec-loadkeys-interval ; dnssec-secure-to-insecure ; + dnssec-update-mode ( maintain | no-resign ); file ; forward ( first | only ); forwarders [ port ] { ( | ) [ port ]; ... }; + inline-signing ; ixfr-base ; // obsolete ixfr-from-differences ; ixfr-tmp-file ; // obsolete @@ -601,6 +624,8 @@ zone { notify-to-soa ; nsec3-test-zone ; // test only pubkey ; // obsolete + request-ixfr ; + serial-update-method ( increment | unixtime ); server-addresses { ( | ) [ port ]; ... }; server-names { ; ... }; @@ -612,7 +637,7 @@ zone { transfer-source-v6 ( | * ) [ port ( | * ) ]; try-tcp-refresh ; type ( master | slave | stub | static-stub | hint | forward | - delegation-only ); + delegation-only | redirect ); update-check-ksk ; update-policy ( local | { ( grant | deny ) ( name | subdomain | wildcard | self | selfsub | selfwild | krb5-self | @@ -620,6 +645,6 @@ zone { | zonesub | external ) [ ] ; ... }; use-alt-transfer-source ; zero-no-soa-ttl ; - zone-statistics ; + zone-statistics ; }; diff --git a/contrib/bind9/lib/bind9/api b/contrib/bind9/lib/bind9/api index 99f8d317f469..a27437f4335b 100644 --- a/contrib/bind9/lib/bind9/api +++ b/contrib/bind9/lib/bind9/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 80 -LIBREVISION = 8 +LIBINTERFACE = 90 +LIBREVISION = 7 LIBAGE = 0 diff --git a/contrib/bind9/lib/bind9/check.c b/contrib/bind9/lib/bind9/check.c index 7c975c9846af..91f8bff13e95 100644 --- a/contrib/bind9/lib/bind9/check.c +++ b/contrib/bind9/lib/bind9/check.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -732,6 +732,20 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx, } } + obj = NULL; + cfg_map_get(options, "max-rsa-exponent-size", &obj); + if (obj != NULL) { + isc_uint32_t val; + + val = cfg_obj_asuint32(obj); + if (val != 0 && (val < 35 || val > 4096)) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "max-rsa-exponent-size '%u' is out of " + "range (35..4096)", val); + result = ISC_R_RANGE; + } + } + obj = NULL; cfg_map_get(options, "sig-validity-interval", &obj); if (obj != NULL) { @@ -1247,7 +1261,9 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { #define FORWARDZONE 16 #define DELEGATIONZONE 32 #define STATICSTUBZONE 64 -#define CHECKACL 128 +#define REDIRECTZONE 128 +#define STREDIRECTZONE 0 /* Set to REDIRECTZONE to allow xfr-in. */ +#define CHECKACL 512 typedef struct { const char *name; @@ -1299,74 +1315,76 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, const cfg_listelt_t *element; static optionstable options[] = { - { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL | - STATICSTUBZONE }, + { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE | + CHECKACL | STATICSTUBZONE }, { "allow-notify", SLAVEZONE | CHECKACL }, { "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL }, { "notify", MASTERZONE | SLAVEZONE }, { "also-notify", MASTERZONE | SLAVEZONE }, - { "dialup", MASTERZONE | SLAVEZONE | STUBZONE }, + { "dialup", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE }, { "delegation-only", HINTZONE | STUBZONE | DELEGATIONZONE }, { "forward", MASTERZONE | SLAVEZONE | STUBZONE | STATICSTUBZONE | FORWARDZONE }, { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | STATICSTUBZONE | FORWARDZONE }, - { "maintain-ixfr-base", MASTERZONE | SLAVEZONE }, - { "max-ixfr-log-size", MASTERZONE | SLAVEZONE }, + { "maintain-ixfr-base", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, + { "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, { "notify-source", MASTERZONE | SLAVEZONE }, { "notify-source-v6", MASTERZONE | SLAVEZONE }, - { "transfer-source", SLAVEZONE | STUBZONE }, - { "transfer-source-v6", SLAVEZONE | STUBZONE }, - { "max-transfer-time-in", SLAVEZONE | STUBZONE }, + { "transfer-source", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "transfer-source-v6", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "max-transfer-time-in", SLAVEZONE | STUBZONE | STREDIRECTZONE }, { "max-transfer-time-out", MASTERZONE | SLAVEZONE }, - { "max-transfer-idle-in", SLAVEZONE | STUBZONE }, + { "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE }, { "max-transfer-idle-out", MASTERZONE | SLAVEZONE }, - { "max-retry-time", SLAVEZONE | STUBZONE }, - { "min-retry-time", SLAVEZONE | STUBZONE }, - { "max-refresh-time", SLAVEZONE | STUBZONE }, - { "min-refresh-time", SLAVEZONE | STUBZONE }, + { "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "min-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "min-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, { "dnssec-secure-to-insecure", MASTERZONE }, - { "sig-validity-interval", MASTERZONE }, - { "sig-re-signing-interval", MASTERZONE }, - { "sig-signing-nodes", MASTERZONE }, - { "sig-signing-type", MASTERZONE }, - { "sig-signing-signatures", MASTERZONE }, + { "sig-re-signing-interval", MASTERZONE | SLAVEZONE }, + { "sig-signing-nodes", MASTERZONE | SLAVEZONE }, + { "sig-signing-signatures", MASTERZONE | SLAVEZONE }, + { "sig-signing-type", MASTERZONE | SLAVEZONE }, + { "sig-validity-interval", MASTERZONE | SLAVEZONE }, + { "signing", MASTERZONE | SLAVEZONE }, { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE | - STATICSTUBZONE}, + STATICSTUBZONE | REDIRECTZONE }, { "allow-update", MASTERZONE | CHECKACL }, { "allow-update-forwarding", SLAVEZONE | CHECKACL }, - { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE }, - { "journal", MASTERZONE | SLAVEZONE }, + { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE | REDIRECTZONE }, + { "journal", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, { "ixfr-base", MASTERZONE | SLAVEZONE }, { "ixfr-tmp-file", MASTERZONE | SLAVEZONE }, - { "masters", SLAVEZONE | STUBZONE }, + { "masters", SLAVEZONE | STUBZONE | REDIRECTZONE }, { "pubkey", MASTERZONE | SLAVEZONE | STUBZONE }, { "update-policy", MASTERZONE }, - { "database", MASTERZONE | SLAVEZONE | STUBZONE }, - { "key-directory", MASTERZONE }, + { "database", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE }, + { "key-directory", MASTERZONE | SLAVEZONE }, { "check-wildcard", MASTERZONE }, { "check-mx", MASTERZONE }, { "check-dup-records", MASTERZONE }, { "integrity-check", MASTERZONE }, { "check-mx-cname", MASTERZONE }, { "check-srv-cname", MASTERZONE }, - { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE }, - { "update-check-ksk", MASTERZONE }, - { "dnssec-dnskey-kskonly", MASTERZONE }, - { "auto-dnssec", MASTERZONE }, - { "try-tcp-refresh", SLAVEZONE }, + { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE | + REDIRECTZONE }, + { "update-check-ksk", MASTERZONE | SLAVEZONE }, + { "dnssec-dnskey-kskonly", MASTERZONE | SLAVEZONE }, + { "dnssec-loadkeys-interval", MASTERZONE | SLAVEZONE }, + { "auto-dnssec", MASTERZONE | SLAVEZONE }, + { "try-tcp-refresh", SLAVEZONE | STREDIRECTZONE }, { "server-addresses", STATICSTUBZONE }, { "server-names", STATICSTUBZONE }, }; static optionstable dialups[] = { - { "notify", MASTERZONE | SLAVEZONE }, - { "notify-passive", SLAVEZONE }, - { "refresh", SLAVEZONE | STUBZONE }, - { "passive", SLAVEZONE | STUBZONE }, + { "notify", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, + { "notify-passive", SLAVEZONE | STREDIRECTZONE }, + { "refresh", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "passive", SLAVEZONE | STUBZONE | STREDIRECTZONE }, }; - znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); zoptions = cfg_tuple_get(zconfig, "options"); @@ -1397,6 +1415,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, ztype = HINTZONE; else if (strcasecmp(typestr, "delegation-only") == 0) ztype = DELEGATIONZONE; + else if (strcasecmp(typestr, "redirect") == 0) + ztype = REDIRECTZONE; else { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': invalid type %s", @@ -1404,6 +1424,11 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, return (ISC_R_FAILURE); } + if (ztype == REDIRECTZONE && strcmp(znamestr, ".") != 0) { + cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, + "redirect zones must be called \".\""); + return (ISC_R_FAILURE); + } obj = cfg_tuple_get(zconfig, "class"); if (cfg_obj_isstring(obj)) { isc_textregion_t r; @@ -1445,7 +1470,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, zname = dns_fixedname_name(&fixedname); dns_name_format(zname, namebuf, sizeof(namebuf)); - tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2, + tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : + ztype == REDIRECTZONE ? 2 : 3, symtab, "zone '%s': already exists " "previous definition: %s:%u", logctx, mctx); if (tresult != ISC_R_SUCCESS) @@ -1497,6 +1523,21 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, } + /* + * Master & slave zones must have a "also-notify" field. + */ + if (ztype == MASTERZONE || ztype == SLAVEZONE ) { + obj = NULL; + tresult = cfg_map_get(zoptions, "also-notify", &obj); + if (tresult == ISC_R_SUCCESS) { + isc_uint32_t count; + tresult = validate_masters(obj, config, &count, + logctx, mctx); + if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) + result = tresult; + } + } + /* * Slave & stub zones must have a "masters" field. */ @@ -1525,10 +1566,10 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, /* * Master zones can't have both "allow-update" and "update-policy". */ - if (ztype == MASTERZONE) { + if (ztype == MASTERZONE || ztype == SLAVEZONE) { isc_result_t res1, res2, res3; const char *arg; - isc_boolean_t ddns; + isc_boolean_t ddns = ISC_FALSE, signing = ISC_FALSE; obj = NULL; res1 = cfg_map_get(zoptions, "allow-update", &obj); @@ -1545,16 +1586,23 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, result = ISC_R_FAILURE; ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS); + obj = NULL; + res1 = cfg_map_get(zoptions, "inline-signing", &obj); + if (res1 == ISC_R_SUCCESS) + signing = cfg_obj_asboolean(obj); + obj = NULL; arg = "off"; res3 = cfg_map_get(zoptions, "auto-dnssec", &obj); if (res3 == ISC_R_SUCCESS) arg = cfg_obj_asstring(obj); - if (strcasecmp(arg, "off") != 0 && !ddns) { + if (strcasecmp(arg, "off") != 0 && !ddns && !signing) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "'auto-dnssec %s;' requires " - "dynamic DNS to be configured in the zone", - arg); + "'auto-dnssec %s;' requires%s " + "inline-signing to be configured for " + "the zone", arg, + (ztype == MASTERZONE) ? + " dynamic DNS or" : ""); result = ISC_R_FAILURE; } if (strcasecmp(arg, "create") == 0) { @@ -1575,6 +1623,33 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, 0xff00U, 0xffffU); result = ISC_R_FAILURE; } + + obj = NULL; + res1 = cfg_map_get(zoptions, "dnssec-dnskey-kskonly", &obj); + if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "dnssec-dnskey-kskonly: requires " + "inline-signing when used in slave zone"); + result = ISC_R_FAILURE; + } + + obj = NULL; + res1 = cfg_map_get(zoptions, "dnssec-loadkeys-interval", &obj); + if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "dnssec-loadkeys-interval: requires " + "inline-signing when used in slave zone"); + result = ISC_R_FAILURE; + } + + obj = NULL; + res1 = cfg_map_get(zoptions, "update-check-ksk", &obj); + if (res1 == ISC_R_SUCCESS && ztype == SLAVEZONE && !signing) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "update-check-ksk: requires " + "inline-signing when used in slave zone"); + result = ISC_R_FAILURE; + } } /* @@ -1710,20 +1785,27 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, /* * If the zone type is rbt/rbt64 then master/hint zones * require file clauses. + * If inline signing is used, then slave zones require a + * file clause as well */ obj = NULL; tresult = cfg_map_get(zoptions, "database", &obj); if (tresult == ISC_R_NOTFOUND || (tresult == ISC_R_SUCCESS && (strcmp("rbt", cfg_obj_asstring(obj)) == 0 || - strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) { + strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) + { + isc_result_t res1; obj = NULL; tresult = cfg_map_get(zoptions, "file", &obj); - if (tresult != ISC_R_SUCCESS && - (ztype == MASTERZONE || ztype == HINTZONE)) { + obj = NULL; + res1 = cfg_map_get(zoptions, "inline-signing", &obj); + if ((tresult != ISC_R_SUCCESS && + (ztype == MASTERZONE || ztype == HINTZONE)) || + (ztype == SLAVEZONE && res1 == ISC_R_SUCCESS)) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': missing 'file' entry", - znamestr); + "zone '%s': missing 'file' entry", + znamestr); result = tresult; } } diff --git a/contrib/bind9/lib/dns/Makefile.in b/contrib/bind9/lib/dns/Makefile.in index 51d60666dec3..b712ab1cd874 100644 --- a/contrib/bind9/lib/dns/Makefile.in +++ b/contrib/bind9/lib/dns/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id$ +# $Id: Makefile.in,v 1.180 2011/10/11 00:09:03 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -57,7 +57,7 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \ # Alphabetically DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ - cache.@O@ callbacks.@O@ compress.@O@ \ + cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \ db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \ journal.@O@ keydata.@O@ keytable.@O@ \ @@ -71,7 +71,7 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ rriterator.@O@ sdb.@O@ \ sdlz.@O@ soa.@O@ ssu.@O@ ssu_external.@O@ \ stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \ - tsec.@O@ tsig.@O@ ttl.@O@ validator.@O@ \ + tsec.@O@ tsig.@O@ ttl.@O@ update.@O@ validator.@O@ \ version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@ OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} @@ -87,7 +87,7 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \ hmac_link.c key.c DNSSRCS = acache.c acl.c adb.c byaddr.c \ - cache.c callbacks.c compress.c \ + cache.c callbacks.c clientinfo.c compress.c \ db.c dbiterator.c dbtable.c diff.c dispatch.c \ dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \ keydata.c keytable.c lib.c log.c lookup.c \ @@ -98,7 +98,7 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c \ resolver.c result.c rootns.c rpz.c rriterator.c \ sdb.c sdlz.c soa.c ssu.c ssu_external.c \ stats.c tcpmsg.c time.c timer.c tkey.c \ - tsec.c tsig.c ttl.c validator.c \ + tsec.c tsig.c ttl.c update.c validator.c \ version.c view.c xfrin.c zone.c zonekey.c zt.c ${OTHERSRCS} SRCS = ${DSTSRCS} ${DNSSRCS} diff --git a/contrib/bind9/lib/dns/acache.c b/contrib/bind9/lib/dns/acache.c index 863df35535ff..6df9b9838635 100644 --- a/contrib/bind9/lib/dns/acache.c +++ b/contrib/bind9/lib/dns/acache.c @@ -1781,9 +1781,8 @@ dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) { * function for more details about the logic. */ void -dns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size) { - isc_uint32_t lowater; - isc_uint32_t hiwater; +dns_acache_setcachesize(dns_acache_t *acache, size_t size) { + size_t hiwater, lowater; REQUIRE(DNS_ACACHE_VALID(acache)); diff --git a/contrib/bind9/lib/dns/acl.c b/contrib/bind9/lib/dns/acl.c index ec29bc7b54ca..3221d30c2b52 100644 --- a/contrib/bind9/lib/dns/acl.c +++ b/contrib/bind9/lib/dns/acl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: acl.c,v 1.55 2011/06/17 23:47:49 tbox Exp $ */ /*! \file */ @@ -48,7 +48,10 @@ dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) { acl = isc_mem_get(mctx, sizeof(*acl)); if (acl == NULL) return (ISC_R_NOMEMORY); - acl->mctx = mctx; + + acl->mctx = NULL; + isc_mem_attach(mctx, &acl->mctx); + acl->name = NULL; result = isc_refcount_init(&acl->refcount, 1); @@ -467,7 +470,7 @@ destroy(dns_acl_t *dacl) { dns_iptable_detach(&dacl->iptable); isc_refcount_destroy(&dacl->refcount); dacl->magic = 0; - isc_mem_put(dacl->mctx, dacl, sizeof(*dacl)); + isc_mem_putanddetach(&dacl->mctx, dacl, sizeof(*dacl)); } void diff --git a/contrib/bind9/lib/dns/adb.c b/contrib/bind9/lib/dns/adb.c index 6aa5e5a730d5..ef7875dcb46b 100644 --- a/contrib/bind9/lib/dns/adb.c +++ b/contrib/bind9/lib/dns/adb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: adb.c,v 1.264 2011/12/05 17:10:51 each Exp $ */ /*! \file * @@ -4130,9 +4130,8 @@ water(void *arg, int mark) { } void -dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) { - isc_uint32_t hiwater; - isc_uint32_t lowater; +dns_adb_setadbsize(dns_adb_t *adb, size_t size) { + size_t hiwater, lowater; INSIST(DNS_ADB_VALID(adb)); diff --git a/contrib/bind9/lib/dns/api b/contrib/bind9/lib/dns/api index 5241a88477cf..a8881101f4e1 100644 --- a/contrib/bind9/lib/dns/api +++ b/contrib/bind9/lib/dns/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 122 +LIBINTERFACE = 99 LIBREVISION = 1 LIBAGE = 0 diff --git a/contrib/bind9/lib/dns/byaddr.c b/contrib/bind9/lib/dns/byaddr.c index 6a3a6036180a..eb05f9f80f37 100644 --- a/contrib/bind9/lib/dns/byaddr.c +++ b/contrib/bind9/lib/dns/byaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -224,7 +224,8 @@ dns_byaddr_create(isc_mem_t *mctx, isc_netaddr_t *address, dns_view_t *view, byaddr = isc_mem_get(mctx, sizeof(*byaddr)); if (byaddr == NULL) return (ISC_R_NOMEMORY); - byaddr->mctx = mctx; + byaddr->mctx = NULL; + isc_mem_attach(mctx, &byaddr->mctx); byaddr->options = options; byaddr->event = isc_mem_get(mctx, sizeof(*byaddr->event)); @@ -277,7 +278,7 @@ dns_byaddr_create(isc_mem_t *mctx, isc_netaddr_t *address, dns_view_t *view, isc_task_detach(&byaddr->task); cleanup_byaddr: - isc_mem_put(mctx, byaddr, sizeof(*byaddr)); + isc_mem_putanddetach(&mctx, byaddr, sizeof(*byaddr)); return (result); } @@ -310,7 +311,7 @@ dns_byaddr_destroy(dns_byaddr_t **byaddrp) { DESTROYLOCK(&byaddr->lock); byaddr->magic = 0; - isc_mem_put(byaddr->mctx, byaddr, sizeof(*byaddr)); + isc_mem_putanddetach(&byaddr->mctx, byaddr, sizeof(*byaddr)); *byaddrp = NULL; } diff --git a/contrib/bind9/lib/dns/cache.c b/contrib/bind9/lib/dns/cache.c index bced80e6e5af..d0f05b9a09ab 100644 --- a/contrib/bind9/lib/dns/cache.c +++ b/contrib/bind9/lib/dns/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: cache.c,v 1.91 2011/08/26 05:12:56 marka Exp $ */ /*! \file */ @@ -136,7 +136,7 @@ struct dns_cache { char *db_type; int db_argc; char **db_argv; - isc_uint32_t size; + size_t size; /* Locked by 'filelock'. */ char *filename; @@ -1028,9 +1028,8 @@ water(void *arg, int mark) { } void -dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) { - isc_uint32_t lowater; - isc_uint32_t hiwater; +dns_cache_setcachesize(dns_cache_t *cache, size_t size) { + size_t hiwater, lowater; REQUIRE(VALID_CACHE(cache)); @@ -1068,9 +1067,9 @@ dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) { isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater); } -isc_uint32_t +size_t dns_cache_getcachesize(dns_cache_t *cache) { - isc_uint32_t size; + size_t size; REQUIRE(VALID_CACHE(cache)); @@ -1153,31 +1152,14 @@ dns_cache_flush(dns_cache_t *cache) { return (ISC_R_SUCCESS); } -isc_result_t -dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) { +static isc_result_t +clearnode(dns_db_t *db, dns_dbnode_t *node) { isc_result_t result; dns_rdatasetiter_t *iter = NULL; - dns_dbnode_t *node = NULL; - dns_db_t *db = NULL; - LOCK(&cache->lock); - if (cache->db != NULL) - dns_db_attach(cache->db, &db); - UNLOCK(&cache->lock); - if (db == NULL) - return (ISC_R_SUCCESS); - result = dns_db_findnode(cache->db, name, ISC_FALSE, &node); - if (result == ISC_R_NOTFOUND) { - result = ISC_R_SUCCESS; - goto cleanup_db; - } + result = dns_db_allrdatasets(db, node, NULL, (isc_stdtime_t)0, &iter); if (result != ISC_R_SUCCESS) - goto cleanup_db; - - result = dns_db_allrdatasets(cache->db, node, NULL, - (isc_stdtime_t)0, &iter); - if (result != ISC_R_SUCCESS) - goto cleanup_node; + return (result); for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; @@ -1187,19 +1169,110 @@ dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) { dns_rdataset_init(&rdataset); dns_rdatasetiter_current(iter, &rdataset); - result = dns_db_deleterdataset(cache->db, node, NULL, + result = dns_db_deleterdataset(db, node, NULL, rdataset.type, rdataset.covers); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) break; } + if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; dns_rdatasetiter_destroy(&iter); + return (result); +} - cleanup_node: - dns_db_detachnode(cache->db, &node); +static isc_result_t +cleartree(dns_db_t *db, dns_name_t *name) { + isc_result_t result, answer = ISC_R_SUCCESS; + dns_dbiterator_t *iter = NULL; + dns_dbnode_t *node = NULL; + dns_fixedname_t fnodename; + dns_name_t *nodename; + + dns_fixedname_init(&fnodename); + nodename = dns_fixedname_name(&fnodename); + + result = dns_db_createiterator(db, 0, &iter); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_dbiterator_seek(iter, name); + if (result != ISC_R_SUCCESS) + goto cleanup; + + while (result == ISC_R_SUCCESS) { + result = dns_dbiterator_current(iter, &node, nodename); + if (result == DNS_R_NEWORIGIN) + result = ISC_R_SUCCESS; + if (result != ISC_R_SUCCESS) + goto cleanup; + /* + * Are we done? + */ + if (! dns_name_issubdomain(nodename, name)) + goto cleanup; + + /* + * If clearnode fails record and move onto the next node. + */ + result = clearnode(db, node); + if (result != ISC_R_SUCCESS && answer == ISC_R_SUCCESS) + answer = result; + dns_db_detachnode(db, &node); + result = dns_dbiterator_next(iter); + } + + cleanup: + if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) + result = ISC_R_SUCCESS; + if (result != ISC_R_SUCCESS && answer == ISC_R_SUCCESS) + answer = result; + if (node != NULL) + dns_db_detachnode(db, &node); + if (iter != NULL) + dns_dbiterator_destroy(&iter); + + return (answer); +} + +isc_result_t +dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) { + return (dns_cache_flushnode(cache, name, ISC_FALSE)); +} + +isc_result_t +dns_cache_flushnode(dns_cache_t *cache, dns_name_t *name, + isc_boolean_t tree) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_db_t *db = NULL; + + if (dns_name_equal(name, dns_rootname)) + return (dns_cache_flush(cache)); + + LOCK(&cache->lock); + if (cache->db != NULL) + dns_db_attach(cache->db, &db); + UNLOCK(&cache->lock); + if (db == NULL) + return (ISC_R_SUCCESS); + + if (tree) { + result = cleartree(cache->db, name); + } else { + result = dns_db_findnode(cache->db, name, ISC_FALSE, &node); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + goto cleanup_db; + } + if (result != ISC_R_SUCCESS) + goto cleanup_db; + result = clearnode(cache->db, node); + dns_db_detachnode(cache->db, &node); + } cleanup_db: dns_db_detach(&db); diff --git a/contrib/bind9/lib/dns/callbacks.c b/contrib/bind9/lib/dns/callbacks.c index 705b6f10a8db..0ef17abce7bc 100644 --- a/contrib/bind9/lib/dns/callbacks.c +++ b/contrib/bind9/lib/dns/callbacks.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: callbacks.c,v 1.19 2011/12/09 23:47:05 tbox Exp $ */ /*! \file */ @@ -88,6 +88,8 @@ dns_rdatacallbacks_initcommon(dns_rdatacallbacks_t *callbacks) { REQUIRE(callbacks != NULL); callbacks->add = NULL; + callbacks->rawdata = NULL; + callbacks->zone = NULL; callbacks->add_private = NULL; callbacks->error_private = NULL; callbacks->warn_private = NULL; diff --git a/contrib/bind9/lib/dns/client.c b/contrib/bind9/lib/dns/client.c index c4780f7bb010..fc551cf9dfe5 100644 --- a/contrib/bind9/lib/dns/client.c +++ b/contrib/bind9/lib/dns/client.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: client.c,v 1.14 2011/03/12 04:59:47 tbox Exp $ */ #include @@ -318,7 +318,7 @@ dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, return (result); } - result = dns_view_createresolver(view, taskmgr, ntasks, socketmgr, + result = dns_view_createresolver(view, taskmgr, ntasks, 1, socketmgr, timermgr, 0, dispatchmgr, dispatchv4, dispatchv6); if (result != ISC_R_SUCCESS) { diff --git a/contrib/bind9/lib/dns/clientinfo.c b/contrib/bind9/lib/dns/clientinfo.c new file mode 100644 index 000000000000..fd5a5e281642 --- /dev/null +++ b/contrib/bind9/lib/dns/clientinfo.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: clientinfo.c,v 1.3 2011/10/11 00:25:12 marka Exp $ */ + +/*! \file */ + +#include "config.h" + +#include + +void +dns_clientinfomethods_init(dns_clientinfomethods_t *methods, + dns_clientinfo_sourceip_t sourceip) +{ + methods->version = DNS_CLIENTINFOMETHODS_VERSION; + methods->age = DNS_CLIENTINFOMETHODS_AGE; + methods->sourceip = sourceip; +} + +void +dns_clientinfo_init(dns_clientinfo_t *ci, void *data) { + ci->version = DNS_CLIENTINFO_VERSION; + ci->data = data; +} diff --git a/contrib/bind9/lib/dns/db.c b/contrib/bind9/lib/dns/db.c index 77f82f15abf0..bf4a5b37540c 100644 --- a/contrib/bind9/lib/dns/db.c +++ b/contrib/bind9/lib/dns/db.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: db.c,v 1.99.4.1 2011/10/23 20:12:07 vjs Exp $ */ /*! \file */ @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -478,7 +479,31 @@ dns_db_findnode(dns_db_t *db, dns_name_t *name, REQUIRE(DNS_DB_VALID(db)); REQUIRE(nodep != NULL && *nodep == NULL); - return ((db->methods->findnode)(db, name, create, nodep)); + if (db->methods->findnode != NULL) + return ((db->methods->findnode)(db, name, create, nodep)); + else + return ((db->methods->findnodeext)(db, name, create, + NULL, NULL, nodep)); +} + +isc_result_t +dns_db_findnodeext(dns_db_t *db, dns_name_t *name, + isc_boolean_t create, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) +{ + /* + * Find the node with name 'name', passing 'arg' to the database + * implementation. + */ + + REQUIRE(DNS_DB_VALID(db)); + REQUIRE(nodep != NULL && *nodep == NULL); + + if (db->methods->findnodeext != NULL) + return ((db->methods->findnodeext)(db, name, create, + methods, clientinfo, nodep)); + else + return ((db->methods->findnode)(db, name, create, nodep)); } isc_result_t @@ -502,7 +527,6 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { - /* * Find the best match for 'name' and 'type' in version 'version' * of 'db'. @@ -519,8 +543,50 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, (DNS_RDATASET_VALID(sigrdataset) && ! dns_rdataset_isassociated(sigrdataset))); - return ((db->methods->find)(db, name, version, type, options, now, - nodep, foundname, rdataset, sigrdataset)); + if (db->methods->find != NULL) + return ((db->methods->find)(db, name, version, type, + options, now, nodep, foundname, + rdataset, sigrdataset)); + else + return ((db->methods->findext)(db, name, version, type, + options, now, nodep, foundname, + NULL, NULL, + rdataset, sigrdataset)); +} + +isc_result_t +dns_db_findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +{ + + /* + * Find the best match for 'name' and 'type' in version 'version' + * of 'db', passing in 'arg'. + */ + + REQUIRE(DNS_DB_VALID(db)); + REQUIRE(type != dns_rdatatype_rrsig); + REQUIRE(nodep == NULL || (nodep != NULL && *nodep == NULL)); + REQUIRE(dns_name_hasbuffer(foundname)); + REQUIRE(rdataset == NULL || + (DNS_RDATASET_VALID(rdataset) && + ! dns_rdataset_isassociated(rdataset))); + REQUIRE(sigrdataset == NULL || + (DNS_RDATASET_VALID(sigrdataset) && + ! dns_rdataset_isassociated(sigrdataset))); + + if (db->methods->findext != NULL) + return ((db->methods->findext)(db, name, version, type, + options, now, nodep, foundname, + methods, clientinfo, + rdataset, sigrdataset)); + else + return ((db->methods->find)(db, name, version, type, + options, now, nodep, foundname, + rdataset, sigrdataset)); } isc_result_t @@ -653,11 +719,6 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { - /* - * Search for an rdataset of type 'type' at 'node' that are in version - * 'version' of 'db'. If found, make 'rdataset' refer to it. - */ - REQUIRE(DNS_DB_VALID(db)); REQUIRE(node != NULL); REQUIRE(DNS_RDATASET_VALID(rdataset)); @@ -668,8 +729,9 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, (DNS_RDATASET_VALID(sigrdataset) && ! dns_rdataset_isassociated(sigrdataset))); - return ((db->methods->findrdataset)(db, node, version, type, covers, - now, rdataset, sigrdataset)); + return ((db->methods->findrdataset)(db, node, version, type, + covers, now, rdataset, + sigrdataset)); } isc_result_t diff --git a/contrib/bind9/lib/dns/dbtable.c b/contrib/bind9/lib/dns/dbtable.c index 57bbfc1ef81e..20092209d58d 100644 --- a/contrib/bind9/lib/dns/dbtable.c +++ b/contrib/bind9/lib/dns/dbtable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -89,7 +89,8 @@ dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, goto clean3; dbtable->default_db = NULL; - dbtable->mctx = mctx; + dbtable->mctx = NULL; + isc_mem_attach(mctx, &dbtable->mctx); dbtable->rdclass = rdclass; dbtable->magic = DBTABLE_MAGIC; dbtable->references = 1; @@ -105,7 +106,7 @@ dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_rbt_destroy(&dbtable->rbt); clean1: - isc_mem_put(mctx, dbtable, sizeof(*dbtable)); + isc_mem_putanddetach(&mctx, dbtable, sizeof(*dbtable)); return (result); } @@ -129,7 +130,7 @@ dbtable_free(dns_dbtable_t *dbtable) { dbtable->magic = 0; - isc_mem_put(dbtable->mctx, dbtable, sizeof(*dbtable)); + isc_mem_putanddetach(&dbtable->mctx, dbtable, sizeof(*dbtable)); } void diff --git a/contrib/bind9/lib/dns/diff.c b/contrib/bind9/lib/dns/diff.c index de00d0f9566b..ff60d462f372 100644 --- a/contrib/bind9/lib/dns/diff.c +++ b/contrib/bind9/lib/dns/diff.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: diff.c,v 1.26 2011/03/25 23:53:02 each Exp $ */ /*! \file */ @@ -73,7 +73,8 @@ dns_difftuple_create(isc_mem_t *mctx, t = isc_mem_allocate(mctx, size); if (t == NULL) return (ISC_R_NOMEMORY); - t->mctx = mctx; + t->mctx = NULL; + isc_mem_attach(mctx, &t->mctx); t->op = op; datap = (unsigned char *)(t + 1); @@ -105,10 +106,15 @@ dns_difftuple_create(isc_mem_t *mctx, void dns_difftuple_free(dns_difftuple_t **tp) { dns_difftuple_t *t = *tp; + isc_mem_t *mctx; + REQUIRE(DNS_DIFFTUPLE_VALID(t)); + dns_name_invalidate(&t->name); t->magic = 0; - isc_mem_free(t->mctx, t); + mctx = t->mctx; + isc_mem_free(mctx, t); + isc_mem_detach(&mctx); *tp = NULL; } diff --git a/contrib/bind9/lib/dns/dispatch.c b/contrib/bind9/lib/dns/dispatch.c index 9848ac28a64a..5063914a9b29 100644 --- a/contrib/bind9/lib/dns/dispatch.c +++ b/contrib/bind9/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: dispatch.c,v 1.175 2011/11/29 01:03:47 marka Exp $ */ /*! \file */ @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -101,12 +102,16 @@ struct dns_dispatchmgr { unsigned int maxbuffers; /*%< max buffers */ /* Locked internally. */ - isc_mutex_t pool_lock; - isc_mempool_t *epool; /*%< memory pool for events */ - isc_mempool_t *rpool; /*%< memory pool for replies */ + isc_mutex_t depool_lock; + isc_mempool_t *depool; /*%< pool for dispatch events */ + isc_mutex_t rpool_lock; + isc_mempool_t *rpool; /*%< pool for replies */ + isc_mutex_t dpool_lock; isc_mempool_t *dpool; /*%< dispatch allocations */ - isc_mempool_t *bpool; /*%< memory pool for buffers */ - isc_mempool_t *spool; /*%< memory pool for dispsocs */ + isc_mutex_t bpool_lock; + isc_mempool_t *bpool; /*%< pool for buffers */ + isc_mutex_t spool_lock; + isc_mempool_t *spool; /*%< pool for dispsocks */ /*% * Locked by qid->lock if qid exists; otherwise, can be used without @@ -226,6 +231,9 @@ struct dns_dispatch { unsigned int maxrequests; /*%< max requests */ isc_event_t *ctlevent; + isc_mutex_t sepool_lock; + isc_mempool_t *sepool; /*%< pool for socket events */ + /*% Locked by mgr->lock. */ ISC_LINK(dns_dispatch_t) link; @@ -301,8 +309,8 @@ static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t, in_port_t); static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len); static void *allocate_udp_buffer(dns_dispatch_t *disp); -static inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev); -static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp); +static inline void free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev); +static inline dns_dispatchevent_t *allocate_devent(dns_dispatch_t *disp); static void do_cancel(dns_dispatch_t *disp); static dns_dispentry_t *linear_first(dns_qid_t *disp); static dns_dispentry_t *linear_next(dns_qid_t *disp, @@ -312,14 +320,16 @@ static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr, - isc_socket_t **sockp); + isc_socket_t **sockp, + isc_socket_t *dup_socket); static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, unsigned int maxrequests, unsigned int attributes, - dns_dispatch_t **dispp); + dns_dispatch_t **dispp, + isc_socket_t *dup_socket); static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr); static void destroy_mgr(dns_dispatchmgr_t **mgrp); static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, @@ -327,7 +337,8 @@ static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, isc_boolean_t needaddrtable); static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp); static isc_result_t open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, - unsigned int options, isc_socket_t **sockp); + unsigned int options, isc_socket_t **sockp, + isc_socket_t *dup_socket); static isc_boolean_t portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock, isc_sockaddr_t *sockaddrp); @@ -720,6 +731,11 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { "shutting down; detaching from sock %p, task %p", disp->socket, disp->task[0]); /* XXXX */ + if (disp->sepool != NULL) { + isc_mempool_destroy(&disp->sepool); + (void)isc_mutex_destroy(&disp->sepool_lock); + } + if (disp->socket != NULL) isc_socket_detach(&disp->socket); while ((dispsocket = ISC_LIST_HEAD(disp->inactivesockets)) != NULL) { @@ -784,6 +800,7 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) { static void deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { dispportentry_t *portentry = *portentryp; + isc_boolean_t unlink = ISC_FALSE; dns_qid_t *qid; REQUIRE(disp->port_table != NULL); @@ -792,7 +809,10 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { qid = DNS_QID(disp); LOCK(&qid->lock); portentry->refs--; - if (portentry->refs == 0) { + unlink = ISC_TF(portentry->refs == 0); + UNLOCK(&qid->lock); + + if (unlink) { ISC_LIST_UNLINK(disp->port_table[portentry->port % DNS_DISPATCH_PORTTABLESIZE], portentry, link); @@ -800,7 +820,6 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { } *portentryp = NULL; - UNLOCK(&qid->lock); } /*% @@ -830,12 +849,12 @@ socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port, /*% * Make a new socket for a single dispatch with a random port number. - * The caller must hold the disp->lock and qid->lock. + * The caller must hold the disp->lock */ static isc_result_t get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, - isc_socketmgr_t *sockmgr, dns_qid_t *qid, - dispsocket_t **dispsockp, in_port_t *portp) + isc_socketmgr_t *sockmgr, dispsocket_t **dispsockp, + in_port_t *portp) { int i; isc_uint32_t r; @@ -850,6 +869,7 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, in_port_t *ports; unsigned int bindoptions; dispportentry_t *portentry = NULL; + dns_qid_t *qid; if (isc_sockaddr_pf(&disp->local) == AF_INET) { nports = disp->mgr->nv4ports; @@ -890,19 +910,27 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, * very likely to fail in bind(2) or connect(2). */ localaddr = disp->local; + qid = DNS_QID(disp); + for (i = 0; i < 64; i++) { port = ports[dispatch_uniformrandom(DISP_ARC4CTX(disp), nports)]; isc_sockaddr_setport(&localaddr, port); + LOCK(&qid->lock); bucket = dns_hash(qid, dest, 0, port); - if (socket_search(qid, dest, port, bucket) != NULL) + if (socket_search(qid, dest, port, bucket) != NULL) { + UNLOCK(&qid->lock); continue; + } + UNLOCK(&qid->lock); bindoptions = 0; portentry = port_search(disp, port); + if (portentry != NULL) bindoptions |= ISC_SOCKET_REUSEADDRESS; - result = open_socket(sockmgr, &localaddr, bindoptions, &sock); + result = open_socket(sockmgr, &localaddr, bindoptions, &sock, + NULL); if (result == ISC_R_SUCCESS) { if (portentry == NULL) { portentry = new_portentry(disp, port); @@ -928,7 +956,9 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest, dispsock->host = *dest; dispsock->portentry = portentry; dispsock->bucket = bucket; + LOCK(&qid->lock); ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); + UNLOCK(&qid->lock); *dispsockp = dispsock; *portp = port; } else { @@ -1063,6 +1093,7 @@ entry_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id, static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) { + isc_mempool_t *bpool; INSIST(buf != NULL && len != 0); @@ -1077,8 +1108,9 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) { INSIST(disp->mgr->buffers > 0); INSIST(len == disp->mgr->buffersize); disp->mgr->buffers--; - isc_mempool_put(disp->mgr->bpool, buf); + bpool = disp->mgr->bpool; UNLOCK(&disp->mgr->buffer_lock); + isc_mempool_put(bpool, buf); break; default: INSIST(0); @@ -1088,20 +1120,60 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) { static void * allocate_udp_buffer(dns_dispatch_t *disp) { + isc_mempool_t *bpool; void *temp; LOCK(&disp->mgr->buffer_lock); - temp = isc_mempool_get(disp->mgr->bpool); - - if (temp != NULL) - disp->mgr->buffers++; + bpool = disp->mgr->bpool; + disp->mgr->buffers++; UNLOCK(&disp->mgr->buffer_lock); + temp = isc_mempool_get(bpool); + + if (temp == NULL) { + LOCK(&disp->mgr->buffer_lock); + disp->mgr->buffers--; + UNLOCK(&disp->mgr->buffer_lock); + } + return (temp); } static inline void -free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) { +free_sevent(isc_event_t *ev) { + isc_mempool_t *pool = ev->ev_destroy_arg; + isc_socketevent_t *sev = (isc_socketevent_t *) ev; + isc_mempool_put(pool, sev); +} + +static inline isc_socketevent_t * +allocate_sevent(dns_dispatch_t *disp, isc_socket_t *socket, + isc_eventtype_t type, isc_taskaction_t action, const void *arg) +{ + isc_socketevent_t *ev; + void *deconst_arg; + + ev = isc_mempool_get(disp->sepool); + if (ev == NULL) + return (NULL); + DE_CONST(arg, deconst_arg); + ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, type, + action, deconst_arg, socket, + free_sevent, disp->sepool); + ev->result = ISC_R_UNSET; + ISC_LINK_INIT(ev, ev_link); + ISC_LIST_INIT(ev->bufferlist); + ev->region.base = NULL; + ev->n = 0; + ev->offset = 0; + ev->attributes = 0; + + return (ev); +} + + +static inline void +free_devent(dns_dispatch_t *disp, dns_dispatchevent_t *ev) { if (disp->failsafe_ev == ev) { INSIST(disp->shutdown_out == 1); disp->shutdown_out = 0; @@ -1109,14 +1181,14 @@ free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) { return; } - isc_mempool_put(disp->mgr->epool, ev); + isc_mempool_put(disp->mgr->depool, ev); } static inline dns_dispatchevent_t * -allocate_event(dns_dispatch_t *disp) { +allocate_devent(dns_dispatch_t *disp) { dns_dispatchevent_t *ev; - ev = isc_mempool_get(disp->mgr->epool); + ev = isc_mempool_get(disp->mgr->depool); if (ev == NULL) return (NULL); ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0, @@ -1381,7 +1453,7 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { sendresponse: queue_response = resp->item_out; - rev = allocate_event(resp->disp); + rev = allocate_devent(resp->disp); if (rev == NULL) { free_buffer(disp, ev->region.base, ev->region.length); goto unlock; @@ -1579,7 +1651,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { if (resp == NULL) goto unlock; queue_response = resp->item_out; - rev = allocate_event(disp); + rev = allocate_devent(disp); if (rev == NULL) goto unlock; @@ -1660,16 +1732,33 @@ startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) { if (region.base == NULL) return (ISC_R_NOMEMORY); if (dispsock != NULL) { - res = isc_socket_recv(socket, ®ion, 1, - dispsock->task, udp_exrecv, - dispsock); + isc_task_t *dt = dispsock->task; + isc_socketevent_t *sev = + allocate_sevent(disp, socket, + ISC_SOCKEVENT_RECVDONE, + udp_exrecv, dispsock); + if (sev == NULL) { + free_buffer(disp, region.base, region.length); + return (ISC_R_NOMEMORY); + } + + res = isc_socket_recv2(socket, ®ion, 1, dt, sev, 0); if (res != ISC_R_SUCCESS) { free_buffer(disp, region.base, region.length); return (res); } } else { - res = isc_socket_recv(socket, ®ion, 1, - disp->task[0], udp_shrecv, disp); + isc_task_t *dt = disp->task[0]; + isc_socketevent_t *sev = + allocate_sevent(disp, socket, + ISC_SOCKEVENT_RECVDONE, + udp_shrecv, disp); + if (sev == NULL) { + free_buffer(disp, region.base, region.length); + return (ISC_R_NOMEMORY); + } + + res = isc_socket_recv2(socket, ®ion, 1, dt, sev, 0); if (res != ISC_R_SUCCESS) { free_buffer(disp, region.base, region.length); disp->shutdown_why = res; @@ -1709,16 +1798,16 @@ static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr) { mgr_log(mgr, LVL(90), "destroy_mgr_ok: shuttingdown=%d, listnonempty=%d, " - "epool=%d, rpool=%d, dpool=%d", + "depool=%d, rpool=%d, dpool=%d", MGR_IS_SHUTTINGDOWN(mgr), !ISC_LIST_EMPTY(mgr->list), - isc_mempool_getallocated(mgr->epool), + isc_mempool_getallocated(mgr->depool), isc_mempool_getallocated(mgr->rpool), isc_mempool_getallocated(mgr->dpool)); if (!MGR_IS_SHUTTINGDOWN(mgr)) return (ISC_FALSE); if (!ISC_LIST_EMPTY(mgr->list)) return (ISC_FALSE); - if (isc_mempool_getallocated(mgr->epool) != 0) + if (isc_mempool_getallocated(mgr->depool) != 0) return (ISC_FALSE); if (isc_mempool_getallocated(mgr->rpool) != 0) return (ISC_FALSE); @@ -1748,7 +1837,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { DESTROYLOCK(&mgr->arc4_lock); - isc_mempool_destroy(&mgr->epool); + isc_mempool_destroy(&mgr->depool); isc_mempool_destroy(&mgr->rpool); isc_mempool_destroy(&mgr->dpool); if (mgr->bpool != NULL) @@ -1756,7 +1845,11 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { if (mgr->spool != NULL) isc_mempool_destroy(&mgr->spool); - DESTROYLOCK(&mgr->pool_lock); + DESTROYLOCK(&mgr->spool_lock); + DESTROYLOCK(&mgr->bpool_lock); + DESTROYLOCK(&mgr->dpool_lock); + DESTROYLOCK(&mgr->rpool_lock); + DESTROYLOCK(&mgr->depool_lock); #ifdef BIND9 if (mgr->entropy != NULL) @@ -1787,19 +1880,14 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { static isc_result_t open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, - unsigned int options, isc_socket_t **sockp) + unsigned int options, isc_socket_t **sockp, + isc_socket_t *dup_socket) { isc_socket_t *sock; isc_result_t result; sock = *sockp; - if (sock == NULL) { - result = isc_socket_create(mgr, isc_sockaddr_pf(local), - isc_sockettype_udp, &sock); - if (result != ISC_R_SUCCESS) - return (result); - isc_socket_setname(sock, "dispatcher", NULL); - } else { + if (sock != NULL) { #ifdef BIND9 result = isc_socket_open(sock); if (result != ISC_R_SUCCESS) @@ -1807,8 +1895,23 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, #else INSIST(0); #endif + } else if (dup_socket != NULL) { + result = isc_socket_dup(dup_socket, &sock); + if (result != ISC_R_SUCCESS) + return (result); + + isc_socket_setname(sock, "dispatcher", NULL); + *sockp = sock; + return (ISC_R_SUCCESS); + } else { + result = isc_socket_create(mgr, isc_sockaddr_pf(local), + isc_sockettype_udp, &sock); + if (result != ISC_R_SUCCESS) + return (result); } + isc_socket_setname(sock, "dispatcher", NULL); + #ifndef ISC_ALLOW_MAPPED isc_socket_ipv6only(sock, ISC_TRUE); #endif @@ -1886,22 +1989,38 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, if (result != ISC_R_SUCCESS) goto kill_arc4_lock; - result = isc_mutex_init(&mgr->pool_lock); + result = isc_mutex_init(&mgr->depool_lock); if (result != ISC_R_SUCCESS) goto kill_buffer_lock; - mgr->epool = NULL; + result = isc_mutex_init(&mgr->rpool_lock); + if (result != ISC_R_SUCCESS) + goto kill_depool_lock; + + result = isc_mutex_init(&mgr->dpool_lock); + if (result != ISC_R_SUCCESS) + goto kill_rpool_lock; + + result = isc_mutex_init(&mgr->bpool_lock); + if (result != ISC_R_SUCCESS) + goto kill_dpool_lock; + + result = isc_mutex_init(&mgr->spool_lock); + if (result != ISC_R_SUCCESS) + goto kill_bpool_lock; + + mgr->depool = NULL; if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatchevent_t), - &mgr->epool) != ISC_R_SUCCESS) { + &mgr->depool) != ISC_R_SUCCESS) { result = ISC_R_NOMEMORY; - goto kill_pool_lock; + goto kill_spool_lock; } mgr->rpool = NULL; if (isc_mempool_create(mgr->mctx, sizeof(dns_dispentry_t), &mgr->rpool) != ISC_R_SUCCESS) { result = ISC_R_NOMEMORY; - goto kill_epool; + goto kill_depool; } mgr->dpool = NULL; @@ -1911,17 +2030,23 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, goto kill_rpool; } - isc_mempool_setname(mgr->epool, "dispmgr_epool"); - isc_mempool_setfreemax(mgr->epool, 1024); - isc_mempool_associatelock(mgr->epool, &mgr->pool_lock); + isc_mempool_setname(mgr->depool, "dispmgr_depool"); + isc_mempool_setmaxalloc(mgr->depool, 32768); + isc_mempool_setfreemax(mgr->depool, 32768); + isc_mempool_associatelock(mgr->depool, &mgr->depool_lock); + isc_mempool_setfillcount(mgr->depool, 256); isc_mempool_setname(mgr->rpool, "dispmgr_rpool"); - isc_mempool_setfreemax(mgr->rpool, 1024); - isc_mempool_associatelock(mgr->rpool, &mgr->pool_lock); + isc_mempool_setmaxalloc(mgr->rpool, 32768); + isc_mempool_setfreemax(mgr->rpool, 32768); + isc_mempool_associatelock(mgr->rpool, &mgr->rpool_lock); + isc_mempool_setfillcount(mgr->rpool, 256); isc_mempool_setname(mgr->dpool, "dispmgr_dpool"); - isc_mempool_setfreemax(mgr->dpool, 1024); - isc_mempool_associatelock(mgr->dpool, &mgr->pool_lock); + isc_mempool_setmaxalloc(mgr->dpool, 32768); + isc_mempool_setfreemax(mgr->dpool, 32768); + isc_mempool_associatelock(mgr->dpool, &mgr->dpool_lock); + isc_mempool_setfillcount(mgr->dpool, 256); mgr->buffers = 0; mgr->buffersize = 0; @@ -1970,10 +2095,18 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, isc_mempool_destroy(&mgr->dpool); kill_rpool: isc_mempool_destroy(&mgr->rpool); - kill_epool: - isc_mempool_destroy(&mgr->epool); - kill_pool_lock: - DESTROYLOCK(&mgr->pool_lock); + kill_depool: + isc_mempool_destroy(&mgr->depool); + kill_spool_lock: + DESTROYLOCK(&mgr->spool_lock); + kill_bpool_lock: + DESTROYLOCK(&mgr->bpool_lock); + kill_dpool_lock: + DESTROYLOCK(&mgr->dpool_lock); + kill_rpool_lock: + DESTROYLOCK(&mgr->rpool_lock); + kill_depool_lock: + DESTROYLOCK(&mgr->depool_lock); kill_buffer_lock: DESTROYLOCK(&mgr->buffer_lock); kill_arc4_lock: @@ -2127,6 +2260,7 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, */ if (maxbuffers > mgr->maxbuffers) { isc_mempool_setmaxalloc(mgr->bpool, maxbuffers); + isc_mempool_setfreemax(mgr->bpool, maxbuffers); mgr->maxbuffers = maxbuffers; } } else { @@ -2137,12 +2271,16 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, } isc_mempool_setname(mgr->bpool, "dispmgr_bpool"); isc_mempool_setmaxalloc(mgr->bpool, maxbuffers); - isc_mempool_associatelock(mgr->bpool, &mgr->pool_lock); + isc_mempool_setfreemax(mgr->bpool, maxbuffers); + isc_mempool_associatelock(mgr->bpool, &mgr->bpool_lock); + isc_mempool_setfillcount(mgr->bpool, 256); } /* Create or adjust socket pool */ if (mgr->spool != NULL) { - isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); + if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2) + isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); + isc_mempool_setfreemax(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); UNLOCK(&mgr->buffer_lock); return (ISC_R_SUCCESS); } @@ -2154,7 +2292,9 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, } isc_mempool_setname(mgr->spool, "dispmgr_spool"); isc_mempool_setmaxalloc(mgr->spool, maxrequests); - isc_mempool_associatelock(mgr->spool, &mgr->pool_lock); + isc_mempool_setfreemax(mgr->spool, maxrequests); + isc_mempool_associatelock(mgr->spool, &mgr->spool_lock); + isc_mempool_setfillcount(mgr->spool, 256); result = qid_allocate(mgr, buckets, increment, &mgr->qid, ISC_TRUE); if (result != ISC_R_SUCCESS) @@ -2480,7 +2620,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, if (result != ISC_R_SUCCESS) goto deallocate; - disp->failsafe_ev = allocate_event(disp); + disp->failsafe_ev = allocate_devent(disp); if (disp->failsafe_ev == NULL) { result = ISC_R_NOMEMORY; goto kill_lock; @@ -2531,7 +2671,7 @@ dispatch_free(dns_dispatch_t **dispp) INSIST(ISC_LIST_EMPTY(disp->activesockets)); INSIST(ISC_LIST_EMPTY(disp->inactivesockets)); - isc_mempool_put(mgr->epool, disp->failsafe_ev); + isc_mempool_put(mgr->depool, disp->failsafe_ev); disp->failsafe_ev = NULL; if (disp->qid != NULL) @@ -2595,6 +2735,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, disp->socket = NULL; isc_socket_attach(sock, &disp->socket); + disp->sepool = NULL; + disp->ntasks = 1; disp->task[0] = NULL; result = isc_task_create(taskmgr, 0, &disp->task[0]); @@ -2646,13 +2788,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, } isc_result_t -dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, +dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, unsigned int buffersize, unsigned int maxbuffers, unsigned int maxrequests, unsigned int buckets, unsigned int increment, unsigned int attributes, unsigned int mask, - dns_dispatch_t **dispp) + dns_dispatch_t **dispp, dns_dispatch_t *dup_dispatch) { isc_result_t result; dns_dispatch_t *disp = NULL; @@ -2683,28 +2825,31 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, /* * See if we have a dispatcher that matches. */ - result = dispatch_find(mgr, localaddr, attributes, mask, &disp); - if (result == ISC_R_SUCCESS) { - disp->refcount++; + if (dup_dispatch == NULL) { + result = dispatch_find(mgr, localaddr, attributes, mask, &disp); + if (result == ISC_R_SUCCESS) { + disp->refcount++; - if (disp->maxrequests < maxrequests) - disp->maxrequests = maxrequests; + if (disp->maxrequests < maxrequests) + disp->maxrequests = maxrequests; - if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 && - (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) - { - disp->attributes |= DNS_DISPATCHATTR_NOLISTEN; - if (disp->recv_pending != 0) - isc_socket_cancel(disp->socket, disp->task[0], - ISC_SOCKCANCEL_RECV); + if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 + && (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) + { + disp->attributes |= DNS_DISPATCHATTR_NOLISTEN; + if (disp->recv_pending != 0) + isc_socket_cancel(disp->socket, + disp->task[0], + ISC_SOCKCANCEL_RECV); + } + + UNLOCK(&disp->lock); + UNLOCK(&mgr->lock); + + *dispp = disp; + + return (ISC_R_SUCCESS); } - - UNLOCK(&disp->lock); - UNLOCK(&mgr->lock); - - *dispp = disp; - - return (ISC_R_SUCCESS); } createudp: @@ -2712,7 +2857,11 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, * Nope, create one. */ result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr, - maxrequests, attributes, &disp); + maxrequests, attributes, &disp, + dup_dispatch == NULL + ? NULL + : dup_dispatch->socket); + if (result != ISC_R_SUCCESS) { UNLOCK(&mgr->lock); return (result); @@ -2720,9 +2869,25 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, UNLOCK(&mgr->lock); *dispp = disp; + return (ISC_R_SUCCESS); } +isc_result_t +dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, + isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, + unsigned int buffersize, + unsigned int maxbuffers, unsigned int maxrequests, + unsigned int buckets, unsigned int increment, + unsigned int attributes, unsigned int mask, + dns_dispatch_t **dispp) +{ + return (dns_dispatch_getudp_dup(mgr, sockmgr, taskmgr, localaddr, + buffersize, maxbuffers, maxrequests, + buckets, increment, attributes, + mask, dispp, NULL)); +} + /* * mgr should be locked. */ @@ -2734,7 +2899,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr, - isc_socket_t **sockp) + isc_socket_t **sockp, isc_socket_t *dup_socket) { unsigned int i, j; isc_socket_t *held[DNS_DISPATCH_HELD]; @@ -2774,7 +2939,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, nports)]; isc_sockaddr_setport(&localaddr_bound, prt); result = open_socket(sockmgr, &localaddr_bound, - 0, &sock); + 0, &sock, NULL); /* * Continue if the port choosen is already in use * or the OS has reserved it. @@ -2794,7 +2959,8 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, } else { /* Allow to reuse address for non-random ports. */ result = open_socket(sockmgr, localaddr, - ISC_SOCKET_REUSEADDRESS, &sock); + ISC_SOCKET_REUSEADDRESS, &sock, + dup_socket); if (result == ISC_R_SUCCESS) *sockp = sock; @@ -2806,7 +2972,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, i = 0; for (j = 0; j < 0xffffU; j++) { - result = open_socket(sockmgr, localaddr, 0, &sock); + result = open_socket(sockmgr, localaddr, 0, &sock, NULL); if (result != ISC_R_SUCCESS) goto end; else if (portavailable(mgr, sock, NULL)) @@ -2843,7 +3009,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr, unsigned int maxrequests, unsigned int attributes, - dns_dispatch_t **dispp) + dns_dispatch_t **dispp, + isc_socket_t *dup_socket) { isc_result_t result; dns_dispatch_t *disp; @@ -2859,9 +3026,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, return (result); if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) { - result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock); + result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock, + dup_socket); if (result != ISC_R_SUCCESS) goto deallocate_dispatch; + + if (isc_log_wouldlog(dns_lctx, 90)) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(localaddr, addrbuf, + ISC_SOCKADDR_FORMATSIZE); + mgr_log(mgr, LVL(90), "dns_dispatch_createudp: Created" + " UDP dispatch for %s with socket fd %d\n", + addrbuf, isc_socket_getfd(sock)); + } + } else { isc_sockaddr_t sa_any; @@ -2873,7 +3052,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, */ isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { - result = open_socket(sockmgr, localaddr, 0, &sock); + result = open_socket(sockmgr, localaddr, 0, &sock, NULL); if (sock != NULL) isc_socket_detach(&sock); if (result != ISC_R_SUCCESS) @@ -2925,6 +3104,24 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, goto kill_task; } + disp->sepool = NULL; + if (isc_mempool_create(mgr->mctx, sizeof(isc_socketevent_t), + &disp->sepool) != ISC_R_SUCCESS) + { + result = ISC_R_NOMEMORY; + goto kill_ctlevent; + } + + result = isc_mutex_init(&disp->sepool_lock); + if (result != ISC_R_SUCCESS) + goto kill_sepool; + + isc_mempool_setname(disp->sepool, "disp_sepool"); + isc_mempool_setmaxalloc(disp->sepool, 32768); + isc_mempool_setfreemax(disp->sepool, 32768); + isc_mempool_associatelock(disp->sepool, &disp->sepool_lock); + isc_mempool_setfillcount(disp->sepool, 16); + attributes &= ~DNS_DISPATCHATTR_TCP; attributes |= DNS_DISPATCHATTR_UDP; disp->attributes = attributes; @@ -2940,11 +3137,16 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, dispatch_log(disp, LVL(90), "created socket %p", disp->socket); *dispp = disp; + return (result); /* * Error returns. */ + kill_sepool: + isc_mempool_destroy(&disp->sepool); + kill_ctlevent: + isc_event_free(&disp->ctlevent); kill_task: for (i = 0; i < disp->ntasks; i++) isc_task_detach(&disp->task[i]); @@ -3061,7 +3263,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, oldestsocket = ISC_LIST_HEAD(disp->activesockets); oldestresp = oldestsocket->resp; if (oldestresp != NULL && !oldestresp->item_out) { - rev = allocate_event(oldestresp->disp); + rev = allocate_devent(oldestresp->disp); if (rev != NULL) { rev->buffer.base = NULL; rev->result = ISC_R_CANCELED; @@ -3088,16 +3290,14 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, } qid = DNS_QID(disp); - LOCK(&qid->lock); if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { /* * Get a separate UDP socket with a random port number. */ - result = get_dispsocket(disp, dest, sockmgr, qid, &dispsocket, + result = get_dispsocket(disp, dest, sockmgr, &dispsocket, &localport); if (result != ISC_R_SUCCESS) { - UNLOCK(&qid->lock); UNLOCK(&disp->lock); inc_stats(disp->mgr, dns_resstatscounter_dispsockfail); return (result); @@ -3109,6 +3309,7 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, /* * Try somewhat hard to find an unique ID. */ + LOCK(&qid->lock); id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp)); bucket = dns_hash(qid, dest, id, localport); ok = ISC_FALSE; @@ -3121,16 +3322,15 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, id &= 0x0000ffff; bucket = dns_hash(qid, dest, id, localport); } + UNLOCK(&qid->lock); if (!ok) { - UNLOCK(&qid->lock); UNLOCK(&disp->lock); return (ISC_R_NOMORE); } res = isc_mempool_get(disp->mgr->rpool); if (res == NULL) { - UNLOCK(&qid->lock); UNLOCK(&disp->lock); if (dispsocket != NULL) destroy_dispsocket(disp, &dispsocket); @@ -3155,6 +3355,8 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, ISC_LIST_INIT(res->items); ISC_LINK_INIT(res, link); res->magic = RESPONSE_MAGIC; + + LOCK(&qid->lock); ISC_LIST_APPEND(qid->qid_table[bucket], res, link); UNLOCK(&qid->lock); @@ -3302,7 +3504,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, res->item_out = ISC_FALSE; if (ev->buffer.base != NULL) free_buffer(disp, ev->buffer.base, ev->buffer.length); - free_event(disp, ev); + free_devent(disp, ev); } request_log(disp, res, LVL(90), "detaching from task %p", res->task); @@ -3322,7 +3524,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, ISC_LIST_UNLINK(res->items, ev, ev_link); if (ev->buffer.base != NULL) free_buffer(disp, ev->buffer.base, ev->buffer.length); - free_event(disp, ev); + free_devent(disp, ev); ev = ISC_LIST_HEAD(res->items); } res->magic = 0; @@ -3519,6 +3721,128 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) { isc_task_send(disp->task[0], ISC_EVENT_PTR(&newsevent)); } +dns_dispatch_t * +dns_dispatchset_get(dns_dispatchset_t *dset) { + dns_dispatch_t *disp; + + /* check that dispatch set is configured */ + if (dset == NULL || dset->ndisp == 0) + return (NULL); + + LOCK(&dset->lock); + disp = dset->dispatches[dset->cur]; + dset->cur++; + if (dset->cur == dset->ndisp) + dset->cur = 0; + UNLOCK(&dset->lock); + + return (disp); +} + +isc_result_t +dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, + isc_taskmgr_t *taskmgr, dns_dispatch_t *source, + dns_dispatchset_t **dsetp, int n) +{ + isc_result_t result; + dns_dispatchset_t *dset; + dns_dispatchmgr_t *mgr; + int i, j; + + REQUIRE(VALID_DISPATCH(source)); + REQUIRE((source->attributes & DNS_DISPATCHATTR_UDP) != 0); + REQUIRE(dsetp != NULL && *dsetp == NULL); + + mgr = source->mgr; + + dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t)); + if (dset == NULL) + return (ISC_R_NOMEMORY); + memset(dset, 0, sizeof(*dset)); + + result = isc_mutex_init(&dset->lock); + if (result != ISC_R_SUCCESS) + goto fail_alloc; + + dset->dispatches = isc_mem_get(mctx, sizeof(dns_dispatch_t *) * n); + if (dset == NULL) { + result = ISC_R_NOMEMORY; + goto fail_lock; + } + + isc_mem_attach(mctx, &dset->mctx); + dset->ndisp = n; + dset->cur = 0; + + dset->dispatches[0] = NULL; + dns_dispatch_attach(source, &dset->dispatches[0]); + + LOCK(&mgr->lock); + for (i = 1; i < n; i++) { + dset->dispatches[i] = NULL; + result = dispatch_createudp(mgr, sockmgr, taskmgr, + &source->local, + source->maxrequests, + source->attributes, + &dset->dispatches[i], + source->socket); + if (result != ISC_R_SUCCESS) + goto fail; + } + + UNLOCK(&mgr->lock); + *dsetp = dset; + + return (ISC_R_SUCCESS); + + fail: + UNLOCK(&mgr->lock); + + for (j = 0; j < i; j++) + dns_dispatch_detach(&(dset->dispatches[j])); + isc_mem_put(mctx, dset->dispatches, sizeof(dns_dispatch_t *) * n); + if (dset->mctx == mctx) + isc_mem_detach(&dset->mctx); + + fail_lock: + DESTROYLOCK(&dset->lock); + + fail_alloc: + isc_mem_put(mctx, dset, sizeof(dns_dispatchset_t)); + return (result); +} + +void +dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task) { + int i; + + REQUIRE(dset != NULL); + + for (i = 0; i < dset->ndisp; i++) { + isc_socket_t *sock; + sock = dns_dispatch_getsocket(dset->dispatches[i]); + isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL); + } +} + +void +dns_dispatchset_destroy(dns_dispatchset_t **dsetp) { + dns_dispatchset_t *dset; + int i; + + REQUIRE(dsetp != NULL && *dsetp != NULL); + + dset = *dsetp; + for (i = 0; i < dset->ndisp; i++) + dns_dispatch_detach(&(dset->dispatches[i])); + isc_mem_put(dset->mctx, dset->dispatches, + sizeof(dns_dispatch_t *) * dset->ndisp); + DESTROYLOCK(&dset->lock); + isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t)); + + *dsetp = NULL; +} + #if 0 void dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) { diff --git a/contrib/bind9/lib/dns/dns64.c b/contrib/bind9/lib/dns/dns64.c index 0b3f1d48b892..78eff579a2ba 100644 --- a/contrib/bind9/lib/dns/dns64.c +++ b/contrib/bind9/lib/dns/dns64.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: dns64.c,v 1.8 2011/03/12 04:59:47 tbox Exp $ */ #include diff --git a/contrib/bind9/lib/dns/dnssec.c b/contrib/bind9/lib/dns/dnssec.c index 587bd1c3c233..d00c99b4124c 100644 --- a/contrib/bind9/lib/dns/dnssec.c +++ b/contrib/bind9/lib/dns/dnssec.c @@ -372,6 +372,15 @@ isc_result_t dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_boolean_t ignoretime, isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild) +{ + return (dns_dnssec_verify3(name, set, key, ignoretime, 0, mctx, + sigrdata, wild)); +} + +isc_result_t +dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + isc_boolean_t ignoretime, unsigned int maxbits, + isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild) { dns_rdata_rrsig_t sig; dns_fixedname_t fnewname; @@ -546,7 +555,7 @@ dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, r.base = sig.signature; r.length = sig.siglen; - ret = dst_context_verify(ctx, &r); + ret = dst_context_verify2(ctx, maxbits, &r); if (ret == ISC_R_SUCCESS && downcase) { char namebuf[DNS_NAME_FORMATSIZE]; dns_name_format(&sig.signer, namebuf, sizeof(namebuf)); @@ -683,6 +692,8 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, pubkey = NULL; dns_rdataset_current(&rdataset, &rdata); RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey)); + dst_key_setttl(pubkey, rdataset.ttl); + if (!is_zone_key(pubkey) || (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) goto next; @@ -760,6 +771,12 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, goto next; } + /* + * Whatever the key's default TTL may have + * been, the rdataset TTL takes priority. + */ + dst_key_setttl(keys[count], rdataset.ttl); + if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { /* We should never get here. */ dst_key_free(&keys[count]); @@ -1509,6 +1526,7 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin, dns_rdata_reset(&rdata); dns_rdataset_current(&keys, &rdata); RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey)); + dst_key_setttl(pubkey, keys.ttl); if (!is_zone_key(pubkey) || (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) @@ -1581,6 +1599,12 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin, if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) goto skip; + /* + * Whatever the key's default TTL may have + * been, the rdataset TTL takes priority. + */ + dst_key_setttl(privkey, dst_key_getttl(pubkey)); + RETERR(addkey(keylist, &privkey, savekeys, mctx)); skip: if (pubkey != NULL) @@ -1706,16 +1730,22 @@ remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, isc_result_t dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, dns_dnsseckeylist_t *removed, dns_name_t *origin, - dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk, - isc_mem_t *mctx, void (*report)(const char *, ...)) + dns_ttl_t hint_ttl, dns_diff_t *diff, + isc_boolean_t allzsk, isc_mem_t *mctx, + void (*report)(const char *, ...)) { isc_result_t result; dns_dnsseckey_t *key, *key1, *key2, *next; + isc_boolean_t found_ttl = ISC_FALSE; + dns_ttl_t ttl = hint_ttl; /* * First, look through the existing key list to find keys * supplied from the command line which are not in the zone. * Update the zone to include them. + * + * Also, if there are keys published in the zone already, + * use their TTL for all subsequent published keys. */ for (key = ISC_LIST_HEAD(*keys); key != NULL; @@ -1725,6 +1755,30 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, RETERR(publish_key(diff, key, origin, ttl, mctx, allzsk, report)); } + if (key->source == dns_keysource_zoneapex) { + ttl = dst_key_getttl(key->key); + found_ttl = ISC_TRUE; + } + } + + /* + * If there were no existing keys, use the smallest nonzero + * TTL of the keys found in the repository. + */ + if (!found_ttl && !ISC_LIST_EMPTY(*newkeys)) { + dns_ttl_t shortest = 0; + + for (key = ISC_LIST_HEAD(*newkeys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + dns_ttl_t thisttl = dst_key_getttl(key->key); + if (thisttl != 0 && + (shortest == 0 || thisttl < shortest)) + shortest = thisttl; + } + + if (shortest != 0) + ttl = shortest; } /* diff --git a/contrib/bind9/lib/dns/dst_api.c b/contrib/bind9/lib/dns/dst_api.c index 53978bce0701..98607246effc 100644 --- a/contrib/bind9/lib/dns/dst_api.c +++ b/contrib/bind9/lib/dns/dst_api.c @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id$ + * $Id: dst_api.c,v 1.65 2011/10/20 21:20:02 marka Exp $ */ /*! \file */ @@ -58,6 +58,8 @@ #include #include +#define DST_KEY_INTERNAL + #include #include #include @@ -92,6 +94,7 @@ static dst_key_t * get_key_struct(dns_name_t *name, unsigned int protocol, unsigned int bits, dns_rdataclass_t rdclass, + dns_ttl_t ttl, isc_mem_t *mctx); static isc_result_t write_public_key(const dst_key_t *key, int type, const char *directory); @@ -370,6 +373,25 @@ dst_context_verify(dst_context_t *dctx, isc_region_t *sig) { return (dctx->key->func->verify(dctx, sig)); } +isc_result_t +dst_context_verify2(dst_context_t *dctx, unsigned int maxbits, + isc_region_t *sig) +{ + REQUIRE(VALID_CTX(dctx)); + REQUIRE(sig != NULL); + + CHECKALG(dctx->key->key_alg); + if (dctx->key->keydata.generic == NULL) + return (DST_R_NULLKEY); + if (dctx->key->func->verify == NULL && + dctx->key->func->verify2 == NULL) + return (DST_R_NOTPUBLICKEY); + + return (dctx->key->func->verify2 != NULL ? + dctx->key->func->verify2(dctx, maxbits, sig) : + dctx->key->func->verify(dctx, sig)); +} + isc_result_t dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv, isc_buffer_t *secret) @@ -525,7 +547,7 @@ dst_key_fromnamedfile(const char *filename, const char *dirname, key = get_key_struct(pubkey->key_name, pubkey->key_alg, pubkey->key_flags, pubkey->key_proto, 0, - pubkey->key_class, mctx); + pubkey->key_class, pubkey->key_ttl, mctx); if (key == NULL) { dst_key_free(&pubkey); return (ISC_R_NOMEMORY); @@ -726,7 +748,7 @@ dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, REQUIRE(keyp != NULL && *keyp == NULL); key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, - 0, dns_rdataclass_in, mctx); + 0, dns_rdataclass_in, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); @@ -747,6 +769,40 @@ out: return result; } +isc_result_t +dst_key_buildinternal(dns_name_t *name, unsigned int alg, + unsigned int bits, unsigned int flags, + unsigned int protocol, dns_rdataclass_t rdclass, + void *data, isc_mem_t *mctx, dst_key_t **keyp) +{ + dst_key_t *key; + isc_result_t result; + + REQUIRE(dst_initialized == ISC_TRUE); + REQUIRE(dns_name_isabsolute(name)); + REQUIRE(mctx != NULL); + REQUIRE(keyp != NULL && *keyp == NULL); + REQUIRE(data != NULL); + + CHECKALG(alg); + + key = get_key_struct(name, alg, flags, protocol, bits, rdclass, + 0, mctx); + if (key == NULL) + return (ISC_R_NOMEMORY); + + key->keydata.generic = data; + + result = computeid(key); + if (result != ISC_R_SUCCESS) { + dst_key_free(&key); + return (result); + } + + *keyp = key; + return (ISC_R_SUCCESS); +} + isc_result_t dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, @@ -764,7 +820,7 @@ dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags, CHECKALG(alg); - key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx); + key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); @@ -818,7 +874,8 @@ dst_key_generate2(dns_name_t *name, unsigned int alg, CHECKALG(alg); - key = get_key_struct(name, alg, flags, protocol, bits, rdclass, mctx); + key = get_key_struct(name, alg, flags, protocol, bits, + rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); @@ -1078,7 +1135,7 @@ dst_key_free(dst_key_t **keyp) { isc_buffer_free(&key->key_tkeytoken); } memset(key, 0, sizeof(dst_key_t)); - isc_mem_put(mctx, key, sizeof(dst_key_t)); + isc_mem_putanddetach(&mctx, key, sizeof(dst_key_t)); *keyp = NULL; } @@ -1220,7 +1277,7 @@ dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, if (dst_t_func[alg]->restore == NULL) return (ISC_R_NOTIMPLEMENTED); - key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx); + key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); @@ -1244,7 +1301,7 @@ static dst_key_t * get_key_struct(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, unsigned int bits, dns_rdataclass_t rdclass, - isc_mem_t *mctx) + dns_ttl_t ttl, isc_mem_t *mctx) { dst_key_t *key; isc_result_t result; @@ -1277,13 +1334,14 @@ get_key_struct(dns_name_t *name, unsigned int alg, isc_mem_put(mctx, key, sizeof(dst_key_t)); return (NULL); } + isc_mem_attach(mctx, &key->mctx); key->key_alg = alg; key->key_flags = flags; key->key_proto = protocol; - key->mctx = mctx; key->keydata.generic = NULL; key->key_size = bits; key->key_class = rdclass; + key->key_ttl = ttl; key->func = dst_t_func[alg]; key->fmt_major = 0; key->fmt_minor = 0; @@ -1312,7 +1370,7 @@ dst_key_read_public(const char *filename, int type, unsigned int opt = ISC_LEXOPT_DNSMULTILINE; dns_rdataclass_t rdclass = dns_rdataclass_in; isc_lexspecials_t specials; - isc_uint32_t ttl; + isc_uint32_t ttl = 0; isc_result_t result; dns_rdatatype_t keytype; @@ -1413,6 +1471,8 @@ dst_key_read_public(const char *filename, int type, if (ret != ISC_R_SUCCESS) goto cleanup; + dst_key_setttl(*keyp, ttl); + cleanup: if (lex != NULL) isc_lex_destroy(&lex); @@ -1581,9 +1641,11 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { /* Now print the actual key */ ret = dns_name_print(key->key_name, fp); - fprintf(fp, " "); + if (key->key_ttl != 0) + fprintf(fp, "%d ", key->key_ttl); + isc_buffer_usedregion(&classb, &r); if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length) ret = DST_R_WRITEERROR; @@ -1675,7 +1737,7 @@ frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags, REQUIRE(mctx != NULL); REQUIRE(keyp != NULL && *keyp == NULL); - key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx); + key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); if (key == NULL) return (ISC_R_NOMEMORY); diff --git a/contrib/bind9/lib/dns/dst_internal.h b/contrib/bind9/lib/dns/dst_internal.h index ee824f40e88a..c3e8e29a46e8 100644 --- a/contrib/bind9/lib/dns/dst_internal.h +++ b/contrib/bind9/lib/dns/dst_internal.h @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: dst_internal.h,v 1.31 2011/10/20 21:20:02 marka Exp $ */ #ifndef DST_DST_INTERNAL_H #define DST_DST_INTERNAL_H 1 @@ -98,6 +98,7 @@ struct dst_key { revoked */ isc_uint16_t key_bits; /*%< hmac digest bits */ dns_rdataclass_t key_class; /*%< class of the key record */ + dns_ttl_t key_ttl; /*%< default/initial dnskey ttl */ isc_mem_t *mctx; /*%< memory context */ char *engine; /*%< engine name (HSM) */ char *label; /*%< engine label (HSM) */ @@ -170,6 +171,8 @@ struct dst_func { */ isc_result_t (*sign)(dst_context_t *dctx, isc_buffer_t *sig); isc_result_t (*verify)(dst_context_t *dctx, const isc_region_t *sig); + isc_result_t (*verify2)(dst_context_t *dctx, int maxbits, + const isc_region_t *sig); isc_result_t (*computesecret)(const dst_key_t *pub, const dst_key_t *priv, isc_buffer_t *secret); diff --git a/contrib/bind9/lib/dns/dst_openssl.h b/contrib/bind9/lib/dns/dst_openssl.h index e4d636e04922..99a43ef948ac 100644 --- a/contrib/bind9/lib/dns/dst_openssl.h +++ b/contrib/bind9/lib/dns/dst_openssl.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: dst_openssl.h,v 1.11 2011/03/12 04:59:48 tbox Exp $ */ #ifndef DST_OPENSSL_H #define DST_OPENSSL_H 1 diff --git a/contrib/bind9/lib/dns/dst_parse.c b/contrib/bind9/lib/dns/dst_parse.c index 95896c4a8870..ca43cb3d1241 100644 --- a/contrib/bind9/lib/dns/dst_parse.c +++ b/contrib/bind9/lib/dns/dst_parse.c @@ -31,7 +31,7 @@ /*% * Principal Author: Brian Wellington - * $Id$ + * $Id: dst_parse.c,v 1.29 2011/08/18 23:46:35 tbox Exp $ */ #include diff --git a/contrib/bind9/lib/dns/ecdb.c b/contrib/bind9/lib/dns/ecdb.c index 20da5b0e6a0a..8b3f7740081b 100644 --- a/contrib/bind9/lib/dns/ecdb.c +++ b/contrib/bind9/lib/dns/ecdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009-2011, 2013 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: ecdb.c,v 1.10 2011/12/20 00:06:53 marka Exp $ */ #include "config.h" @@ -583,7 +583,9 @@ static dns_dbmethods_t ecdb_methods = { NULL, /* isdnssec */ NULL, /* getrrsetstats */ NULL, /* rpz_enabled */ - NULL /* rpz_findips */ + NULL, /* rpz_findips */ + NULL, /* findnodeext */ + NULL /* findext */ }; static isc_result_t diff --git a/contrib/bind9/lib/dns/gssapi_link.c b/contrib/bind9/lib/dns/gssapi_link.c index a992a8953f20..5ad81cd80ced 100644 --- a/contrib/bind9/lib/dns/gssapi_link.c +++ b/contrib/bind9/lib/dns/gssapi_link.c @@ -16,7 +16,7 @@ */ /* - * $Id$ + * $Id: gssapi_link.c,v 1.17 2011/03/28 05:32:16 marka Exp $ */ #include @@ -362,6 +362,7 @@ static dst_func_t gssapi_functions = { gssapi_adddata, gssapi_sign, gssapi_verify, + NULL, /*%< verify2 */ NULL, /*%< computesecret */ gssapi_compare, NULL, /*%< paramcompare */ diff --git a/contrib/bind9/lib/dns/gssapictx.c b/contrib/bind9/lib/dns/gssapictx.c index e4047d252190..a8c5900e6d14 100644 --- a/contrib/bind9/lib/dns/gssapictx.c +++ b/contrib/bind9/lib/dns/gssapictx.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: gssapictx.c,v 1.29 2011/08/29 06:33:25 marka Exp $ */ #include diff --git a/contrib/bind9/lib/dns/hmac_link.c b/contrib/bind9/lib/dns/hmac_link.c index bc0e9a04ed07..256abb6eb475 100644 --- a/contrib/bind9/lib/dns/hmac_link.c +++ b/contrib/bind9/lib/dns/hmac_link.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -313,6 +313,7 @@ static dst_func_t hmacmd5_functions = { hmacmd5_adddata, hmacmd5_sign, hmacmd5_verify, + NULL, /*%< verify2 */ NULL, /*%< computesecret */ hmacmd5_compare, NULL, /*%< paramcompare */ @@ -589,6 +590,7 @@ static dst_func_t hmacsha1_functions = { hmacsha1_adddata, hmacsha1_sign, hmacsha1_verify, + NULL, /* verify2 */ NULL, /* computesecret */ hmacsha1_compare, NULL, /* paramcompare */ @@ -867,6 +869,7 @@ static dst_func_t hmacsha224_functions = { hmacsha224_adddata, hmacsha224_sign, hmacsha224_verify, + NULL, /* verify2 */ NULL, /* computesecret */ hmacsha224_compare, NULL, /* paramcompare */ @@ -1145,6 +1148,7 @@ static dst_func_t hmacsha256_functions = { hmacsha256_adddata, hmacsha256_sign, hmacsha256_verify, + NULL, /* verify2 */ NULL, /* computesecret */ hmacsha256_compare, NULL, /* paramcompare */ @@ -1423,6 +1427,7 @@ static dst_func_t hmacsha384_functions = { hmacsha384_adddata, hmacsha384_sign, hmacsha384_verify, + NULL, /* verify2 */ NULL, /* computesecret */ hmacsha384_compare, NULL, /* paramcompare */ @@ -1701,6 +1706,7 @@ static dst_func_t hmacsha512_functions = { hmacsha512_adddata, hmacsha512_sign, hmacsha512_verify, + NULL, /* verify2 */ NULL, /* computesecret */ hmacsha512_compare, NULL, /* paramcompare */ diff --git a/contrib/bind9/lib/dns/include/dns/Makefile.in b/contrib/bind9/lib/dns/include/dns/Makefile.in index ad8bc383e4b3..1a69f2c814f4 100644 --- a/contrib/bind9/lib/dns/include/dns/Makefile.in +++ b/contrib/bind9/lib/dns/include/dns/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id$ +# $Id: Makefile.in,v 1.60 2011/11/14 18:32:34 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -22,8 +22,8 @@ top_srcdir = @top_srcdir@ @BIND9_VERSION@ HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ - db.h dbiterator.h dbtable.h diff.h dispatch.h dlz.h \ - dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ + clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ + dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ keyflags.h keytable.h keyvalues.h lib.h log.h \ master.h masterdump.h message.h name.h ncache.h nsec.h \ peer.h portlist.h private.h rbt.h rcode.h \ diff --git a/contrib/bind9/lib/dns/include/dns/acache.h b/contrib/bind9/lib/dns/include/dns/acache.h index c372ed95a372..304cba758ad3 100644 --- a/contrib/bind9/lib/dns/include/dns/acache.h +++ b/contrib/bind9/lib/dns/include/dns/acache.h @@ -238,7 +238,7 @@ dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t); */ void -dns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size); +dns_acache_setcachesize(dns_acache_t *acache, size_t size); /* * Set the maximum additional cache size. 0 means unlimited. */ diff --git a/contrib/bind9/lib/dns/include/dns/acl.h b/contrib/bind9/lib/dns/include/dns/acl.h index 41b9522f0317..f4fc4a3bf9e1 100644 --- a/contrib/bind9/lib/dns/include/dns/acl.h +++ b/contrib/bind9/lib/dns/include/dns/acl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: acl.h,v 1.35 2011/06/17 23:47:49 tbox Exp $ */ #ifndef DNS_ACL_H #define DNS_ACL_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/adb.h b/contrib/bind9/lib/dns/include/dns/adb.h index b8c41dcdd485..a5a312406aff 100644 --- a/contrib/bind9/lib/dns/include/dns/adb.h +++ b/contrib/bind9/lib/dns/include/dns/adb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: adb.h,v 1.88 2011/12/05 17:10:51 each Exp $ */ #ifndef DNS_ADB_H #define DNS_ADB_H 1 @@ -607,7 +607,7 @@ dns_adb_flush(dns_adb_t *adb); */ void -dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size); +dns_adb_setadbsize(dns_adb_t *adb, size_t size); /*%< * Set a target memory size. If memory usage exceeds the target * size entries will be removed before they would have expired on diff --git a/contrib/bind9/lib/dns/include/dns/cache.h b/contrib/bind9/lib/dns/include/dns/cache.h index f0825be3063b..f7140aa7c6ce 100644 --- a/contrib/bind9/lib/dns/include/dns/cache.h +++ b/contrib/bind9/lib/dns/include/dns/cache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: cache.h,v 1.32 2011/08/02 23:47:52 tbox Exp $ */ #ifndef DNS_CACHE_H #define DNS_CACHE_H 1 @@ -245,12 +245,6 @@ dns_cache_getcleaninginterval(dns_cache_t *cache); * Get the periodic cache cleaning interval to 'interval' seconds. */ -isc_uint32_t -dns_cache_getcachesize(dns_cache_t *cache); -/*%< - * Get the maximum cache size. - */ - const char * dns_cache_getname(dns_cache_t *cache); /*%< @@ -258,12 +252,12 @@ dns_cache_getname(dns_cache_t *cache); */ void -dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size); +dns_cache_setcachesize(dns_cache_t *cache, size_t size); /*%< * Set the maximum cache size. 0 means unlimited. */ -isc_uint32_t +size_t dns_cache_getcachesize(dns_cache_t *cache); /*%< * Get the maximum cache size. @@ -279,10 +273,28 @@ dns_cache_flush(dns_cache_t *cache); *\li #ISC_R_NOMEMORY */ +isc_result_t +dns_cache_flushnode(dns_cache_t *cache, dns_name_t *name, + isc_boolean_t tree); +/* + * Flush a given name from the cache. If 'tree' is true, then + * also flush all names under 'name'. + * + * Requires: + *\li 'cache' to be valid. + *\li 'name' to be valid. + * + * Returns: + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOMEMORY + *\li other error returns. + */ + isc_result_t dns_cache_flushname(dns_cache_t *cache, dns_name_t *name); /* - * Flushes a given name from the cache. + * Flush a given name from the cache. Equivalent to + * dns_cache_flushpartial(cache, name, ISC_FALSE). * * Requires: *\li 'cache' to be valid. diff --git a/contrib/bind9/lib/dns/include/dns/callbacks.h b/contrib/bind9/lib/dns/include/dns/callbacks.h index b686647b7d61..5e9cb717f81e 100644 --- a/contrib/bind9/lib/dns/include/dns/callbacks.h +++ b/contrib/bind9/lib/dns/include/dns/callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: callbacks.h,v 1.26 2011/12/09 23:47:05 tbox Exp $ */ #ifndef DNS_CALLBACKS_H #define DNS_CALLBACKS_H 1 @@ -41,6 +41,14 @@ struct dns_rdatacallbacks { * dns_load_master calls this when it has rdatasets to commit. */ dns_addrdatasetfunc_t add; + + /*% + * dns_master_load*() call this when loading a raw zonefile, + * to pass back information obtained from the file header + */ + dns_rawdatafunc_t rawdata; + dns_zone_t *zone; + /*% * dns_load_master / dns_rdata_fromtext call this to issue a error. */ diff --git a/contrib/bind9/lib/dns/include/dns/clientinfo.h b/contrib/bind9/lib/dns/include/dns/clientinfo.h new file mode 100644 index 000000000000..4f2b89cda43e --- /dev/null +++ b/contrib/bind9/lib/dns/include/dns/clientinfo.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: clientinfo.h,v 1.3 2011/10/11 23:46:45 tbox Exp $ */ + +#ifndef DNS_CLIENTINFO_H +#define DNS_CLIENTINFO_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file dns/clientinfo.h + * \brief + * The DNS clientinfo interface allows libdns to retrieve information + * about the client from the caller. + * + * The clientinfo interface is used by the DNS DB and DLZ interfaces; + * it allows databases to modify their answers on the basis of information + * about the client, such as source IP address. + * + * dns_clientinfo_t contains a pointer to an opaque structure containing + * client information in some form. dns_clientinfomethods_t contains a + * list of methods which operate on that opaque structure to return + * potentially useful data. Both structures also contain versioning + * information. + */ + +/***** + ***** Imports + *****/ + +#include +#include + +ISC_LANG_BEGINDECLS + +/***** + ***** Types + *****/ + +#define DNS_CLIENTINFO_VERSION 1 +typedef struct dns_clientinfo { + isc_uint16_t version; + void *data; +} dns_clientinfo_t; + +typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client, + isc_sockaddr_t **addrp); + +#define DNS_CLIENTINFOMETHODS_VERSION 1 +#define DNS_CLIENTINFOMETHODS_AGE 0 + +typedef struct dns_clientinfomethods { + isc_uint16_t version; + isc_uint16_t age; + dns_clientinfo_sourceip_t sourceip; +} dns_clientinfomethods_t; + +/***** + ***** Methods + *****/ +void +dns_clientinfomethods_init(dns_clientinfomethods_t *methods, + dns_clientinfo_sourceip_t sourceip); + +void +dns_clientinfo_init(dns_clientinfo_t *ci, void *data); + +ISC_LANG_ENDDECLS + +#endif /* DNS_CLIENTINFO_H */ diff --git a/contrib/bind9/lib/dns/include/dns/db.h b/contrib/bind9/lib/dns/include/dns/db.h index ef090a2b8616..66bc3e3481e1 100644 --- a/contrib/bind9/lib/dns/include/dns/db.h +++ b/contrib/bind9/lib/dns/include/dns/db.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: db.h,v 1.107.4.1 2011/10/23 20:12:08 vjs Exp $ */ #ifndef DNS_DB_H #define DNS_DB_H 1 @@ -59,6 +59,7 @@ #include #include +#include #include #include #include @@ -179,6 +180,20 @@ typedef struct dns_dbmethods { dns_rdataset_t *ardataset, dns_rpz_st_t *st, dns_name_t *query_qname); + isc_result_t (*findnodeext)(dns_db_t *db, dns_name_t *name, + isc_boolean_t create, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo, + dns_dbnode_t **nodep); + isc_result_t (*findext)(dns_db_t *db, dns_name_t *name, + dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, + isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset); } dns_dbmethods_t; typedef isc_result_t @@ -660,9 +675,19 @@ dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_result_t dns_db_findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, dns_dbnode_t **nodep); + +isc_result_t +dns_db_findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep); /*%< * Find the node with name 'name'. * + * dns_db_findnodeext() (findnode extended) also accepts parameters + * 'methods' and 'clientinfo', which, when provided, enable the database to + * retreive information about the client from the caller, and modify its + * response on the basis of that information. + * * Notes: * \li If 'create' is ISC_TRUE and no node with name 'name' exists, then * such a node will be created. @@ -699,9 +724,21 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); + +isc_result_t +dns_db_findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); /*%< * Find the best match for 'name' and 'type' in version 'version' of 'db'. * + * dns_db_findext() (find extended) also accepts parameters 'methods' + * and 'clientinfo', which when provided enable the database to retreive + * information about the client from the caller, and modify its response + * on the basis of this information. + * * Notes: * * \li If type == dns_rdataset_any, then rdataset will not be bound. @@ -733,6 +770,10 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * that it is correct. This only affects answers returned from the * cache. * + * \li In the #DNS_DBFIND_FORCENSEC3 option is set, then we are looking + * in the NSEC3 tree and not the main tree. Without this option being + * set NSEC3 records will not be found. + * * \li To respond to a query for SIG records, the caller should create a * rdataset iterator and extract the signatures from each rdataset. * @@ -1048,6 +1089,7 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset); + /*%< * Search for an rdataset of type 'type' at 'node' that are in version * 'version' of 'db'. If found, make 'rdataset' refer to it. diff --git a/contrib/bind9/lib/dns/include/dns/dispatch.h b/contrib/bind9/lib/dns/include/dns/dispatch.h index 3f881dfcf1d6..1235f7ca40f3 100644 --- a/contrib/bind9/lib/dns/include/dns/dispatch.h +++ b/contrib/bind9/lib/dns/include/dns/dispatch.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: dispatch.h,v 1.64 2011/07/28 23:47:58 tbox Exp $ */ #ifndef DNS_DISPATCH_H #define DNS_DISPATCH_H 1 @@ -54,6 +54,7 @@ #include #include +#include #include #include @@ -88,6 +89,18 @@ struct dns_dispatchevent { isc_uint32_t attributes; /*%< mirrored from socket.h */ }; +/*% + * This is a set of one or more dispatches which can be retrieved + * round-robin fashion. + */ +struct dns_dispatchset { + isc_mem_t *mctx; + dns_dispatch_t **dispatches; + int ndisp; + int cur; + isc_mutex_t lock; +}; + /*@{*/ /*% * Attributes for added dispatchers. @@ -245,6 +258,15 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, unsigned int buckets, unsigned int increment, unsigned int attributes, unsigned int mask, dns_dispatch_t **dispp); + +isc_result_t +dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, + isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, + unsigned int buffersize, + unsigned int maxbuffers, unsigned int maxrequests, + unsigned int buckets, unsigned int increment, + unsigned int attributes, unsigned int mask, + dns_dispatch_t **dispp, dns_dispatch_t *dup); /*%< * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find, * otherwise create a new UDP dispatch. @@ -496,6 +518,46 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event); * event != NULL */ +dns_dispatch_t * +dns_dispatchset_get(dns_dispatchset_t *dset); +/*%< + * Retrieve the next dispatch from dispatch set 'dset', and increment + * the round-robin counter. + * + * Requires: + *\li dset != NULL + */ + +isc_result_t +dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, + isc_taskmgr_t *taskmgr, dns_dispatch_t *source, + dns_dispatchset_t **dsetp, int n); +/*%< + * Given a valid dispatch 'source', create a dispatch set containing + * 'n' UDP dispatches, with the remainder filled out by clones of the + * source. + * + * Requires: + *\li source is a valid UDP dispatcher + *\li dsetp != NULL, *dsetp == NULL + */ + +void +dns_dispatchset_cancelall(dns_dispatchset_t *dset, isc_task_t *task); +/*%< + * Cancel socket operations for the dispatches in 'dset'. + */ + +void +dns_dispatchset_destroy(dns_dispatchset_t **dsetp); +/*%< + * Dereference all the dispatches in '*dsetp', free the dispatchset + * memory, and set *dsetp to NULL. + * + * Requires: + *\li dset is valid + */ + ISC_LANG_ENDDECLS #endif /* DNS_DISPATCH_H */ diff --git a/contrib/bind9/lib/dns/include/dns/dlz_dlopen.h b/contrib/bind9/lib/dns/include/dns/dlz_dlopen.h index 6ad7e7a33ae0..f87722c3db8e 100644 --- a/contrib/bind9/lib/dns/include/dns/dlz_dlopen.h +++ b/contrib/bind9/lib/dns/include/dns/dlz_dlopen.h @@ -30,7 +30,7 @@ ISC_LANG_BEGINDECLS * for the entry points of an external DLZ module for bind9. */ -#define DLZ_DLOPEN_VERSION 1 +#define DLZ_DLOPEN_VERSION 2 /* * dlz_dlopen_version() is required for all DLZ external drivers. It @@ -65,7 +65,9 @@ typedef isc_result_t dlz_dlopen_findzonedb_t (void *dbdata, typedef isc_result_t dlz_dlopen_lookup_t (const char *zone, const char *name, void *dbdata, - dns_sdlzlookup_t *lookup); + dns_sdlzlookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo); /* * dlz_dlopen_authority is optional() if dlz_dlopen_lookup() @@ -115,6 +117,15 @@ typedef void dlz_dlopen_closeversion_t (const char *zone, typedef isc_result_t dlz_dlopen_configure_t (dns_view_t *view, void *dbdata); +/* + * dlz_dlopen_setclientcallback() is optional, but must be supplied if you + * want to retrieve information about the client (e.g., source address) + * before sending a replay. + */ +typedef isc_result_t dlz_dlopen_setclientcallback_t (dns_view_t *view, + void *dbdata); + + /* * dlz_dlopen_ssumatch() is optional, but must be supplied if you want * to support dynamic updates diff --git a/contrib/bind9/lib/dns/include/dns/dnssec.h b/contrib/bind9/lib/dns/include/dns/dnssec.h index e986d406f617..e443f91b635b 100644 --- a/contrib/bind9/lib/dns/include/dns/dnssec.h +++ b/contrib/bind9/lib/dns/include/dns/dnssec.h @@ -132,12 +132,19 @@ isc_result_t dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_boolean_t ignoretime, isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild); + +isc_result_t +dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + isc_boolean_t ignoretime, unsigned int maxbits, + isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild); /*%< * Verifies the RRSIG record covering this rdataset signed by a specific * key. This does not determine if the key's owner is authorized to sign * this record, as this requires a resolver or database. * If 'ignoretime' is ISC_TRUE, temporal validity will not be checked. * + * 'maxbits' specifies the maximum number of rsa exponent bits accepted. + * * Requires: *\li 'name' (the owner name of the record) is a valid name *\li 'set' is a valid rdataset @@ -309,7 +316,7 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin, isc_result_t dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, dns_dnsseckeylist_t *removed, dns_name_t *origin, - dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk, + dns_ttl_t hint_ttl, dns_diff_t *diff, isc_boolean_t allzsk, isc_mem_t *mctx, void (*report)(const char *, ...)); /*%< * Update the list of keys in 'keys' with new key information in 'newkeys'. @@ -328,9 +335,11 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, * If 'allzsk' is true, we are allowing KSK-flagged keys to be used as * ZSKs. * - * 'ttl' is the TTL of the DNSKEY RRset; if it is longer than the - * time until a new key will be activated, then we have to delay the - * key's activation. + * 'hint_ttl' is the TTL to use for the DNSKEY RRset if there is no + * existing RRset, and if none of the keys to be added has a default TTL + * (in which case we would use the shortest one). If the TTL is longer + * than the time until a new key will be activated, then we have to delay + * the key's activation. * * 'report' points to a function for reporting status. * diff --git a/contrib/bind9/lib/dns/include/dns/events.h b/contrib/bind9/lib/dns/include/dns/events.h index 3a28ab2aec1c..fd2144f64937 100644 --- a/contrib/bind9/lib/dns/include/dns/events.h +++ b/contrib/bind9/lib/dns/include/dns/events.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: events.h,v 1.61 2011/10/28 06:20:06 each Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -74,6 +74,11 @@ #define DNS_EVENT_CLIENTREQDONE (ISC_EVENTCLASS_DNS + 44) #define DNS_EVENT_ADBGROWENTRIES (ISC_EVENTCLASS_DNS + 45) #define DNS_EVENT_ADBGROWNAMES (ISC_EVENTCLASS_DNS + 46) +#define DNS_EVENT_ZONESECURESERIAL (ISC_EVENTCLASS_DNS + 47) +#define DNS_EVENT_ZONESECUREDB (ISC_EVENTCLASS_DNS + 48) +#define DNS_EVENT_ZONELOAD (ISC_EVENTCLASS_DNS + 49) +#define DNS_EVENT_KEYDONE (ISC_EVENTCLASS_DNS + 50) +#define DNS_EVENT_SETNSEC3PARAM (ISC_EVENTCLASS_DNS + 51) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535) diff --git a/contrib/bind9/lib/dns/include/dns/journal.h b/contrib/bind9/lib/dns/include/dns/journal.h index d750fbef3dd7..68ba8b35ae91 100644 --- a/contrib/bind9/lib/dns/include/dns/journal.h +++ b/contrib/bind9/lib/dns/include/dns/journal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: journal.h,v 1.43 2011/12/22 07:32:41 each Exp $ */ #ifndef DNS_JOURNAL_H #define DNS_JOURNAL_H 1 @@ -46,6 +46,10 @@ ***/ #define DNS_JOURNALOPT_RESIGN 0x00000001 +#define DNS_JOURNAL_READ 0x00000000 /* ISC_FALSE */ +#define DNS_JOURNAL_CREATE 0x00000001 /* ISC_TRUE */ +#define DNS_JOURNAL_WRITE 0x00000002 + /*** *** Types ***/ @@ -72,7 +76,7 @@ ISC_LANG_BEGINDECLS isc_result_t dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, - dns_diffop_t op, dns_difftuple_t **tp); + dns_diffop_t op, dns_difftuple_t **tp); /*!< brief * Create a diff tuple for the current database SOA. * XXX this probably belongs somewhere else. @@ -95,16 +99,15 @@ dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, */ isc_result_t -dns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, +dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, dns_journal_t **journalp); /*%< * Open the journal file 'filename' and create a dns_journal_t object for it. * - * If 'write' is ISC_TRUE, the journal is open for writing. If it does - * not exist, it is created. - * - * If 'write' is ISC_FALSE, the journal is open for reading. If it does - * not exist, ISC_R_NOTFOUND is returned. + * DNS_JOURNAL_CREATE open the journal for reading and writing and create + * the journal if it does not exist. + * DNS_JOURNAL_WRITE open the journal for reading and writing. + * DNS_JOURNAL_READ open the journal for reading only. */ void @@ -267,12 +270,18 @@ dns_db_diff(isc_mem_t *mctx, dns_db_t *dba, dns_dbversion_t *dbvera, dns_db_t *dbb, dns_dbversion_t *dbverb, const char *journal_filename); + +isc_result_t +dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, + const char *journal_filename); /*%< - * Compare the databases 'dba' and 'dbb' and generate a journal + * Compare the databases 'dba' and 'dbb' and generate a diff/journal * entry containing the changes to make 'dba' from 'dbb' (note * the order). This journal entry will consist of a single, * possibly very large transaction. Append the journal - * entry to the journal file specified by 'journal_filename'. + * entry to the journal file specified by 'journal_filename' if + * non-NULL. */ isc_result_t @@ -284,6 +293,17 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial, * exists and is non-empty 'serial' must exist in the journal. */ +isc_boolean_t +dns_journal_get_sourceserial(dns_journal_t *j, isc_uint32_t *sourceserial); +void +dns_journal_set_sourceserial(dns_journal_t *j, isc_uint32_t sourceserial); +/*%< + * Get and set source serial. + * + * Returns: + * ISC_TRUE if sourceserial has previously been set. + */ + ISC_LANG_ENDDECLS #endif /* DNS_JOURNAL_H */ diff --git a/contrib/bind9/lib/dns/include/dns/log.h b/contrib/bind9/lib/dns/include/dns/log.h index 689b148eb8f3..3c4df8a45003 100644 --- a/contrib/bind9/lib/dns/include/dns/log.h +++ b/contrib/bind9/lib/dns/include/dns/log.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: log.h,v 1.47 2011/10/13 22:48:24 tbox Exp $ */ /*! \file dns/log.h * \author Principal Authors: DCL */ diff --git a/contrib/bind9/lib/dns/include/dns/master.h b/contrib/bind9/lib/dns/include/dns/master.h index a852ae4b2aa7..896c6e95ecd3 100644 --- a/contrib/bind9/lib/dns/include/dns/master.h +++ b/contrib/bind9/lib/dns/include/dns/master.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -66,18 +66,29 @@ ISC_LANG_BEGINDECLS * encoding, we directly read/write each field so that the encoded data * is always "packed", regardless of the hardware architecture. */ -#define DNS_RAWFORMAT_VERSION 0 +#define DNS_RAWFORMAT_VERSION 1 + +/* + * Flags to indicate the status of the data in the raw file header + */ +#define DNS_MASTERRAW_COMPAT 0x01 +#define DNS_MASTERRAW_SOURCESERIALSET 0x02 +#define DNS_MASTERRAW_LASTXFRINSET 0x04 /* Common header */ -typedef struct { +struct dns_masterrawheader { isc_uint32_t format; /* must be * dns_masterformat_raw */ isc_uint32_t version; /* compatibility for future * extensions */ isc_uint32_t dumptime; /* timestamp on creation - * (currently unused) - */ -} dns_masterrawheader_t; + * (currently unused) */ + isc_uint32_t flags; /* Flags */ + isc_uint32_t sourceserial; /* Source serial number (used + * by inline-signing zones) */ + isc_uint32_t lastxfrin; /* timestamp of last transfer + * (used by slave zones) */ +}; /* The structure for each RRset */ typedef struct { @@ -302,6 +313,12 @@ dns_loadctx_cancel(dns_loadctx_t *ctx); *\li 'ctx' to be valid */ +void +dns_master_initrawheader(dns_masterrawheader_t *header); +/*%< + * Initializes the header for a raw master file, setting all + * values to zero. + */ ISC_LANG_ENDDECLS #endif /* DNS_MASTER_H */ diff --git a/contrib/bind9/lib/dns/include/dns/masterdump.h b/contrib/bind9/lib/dns/include/dns/masterdump.h index f7e30f13d53e..8631248cc2ee 100644 --- a/contrib/bind9/lib/dns/include/dns/masterdump.h +++ b/contrib/bind9/lib/dns/include/dns/masterdump.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: masterdump.h,v 1.47 2011/12/08 23:46:49 tbox Exp $ */ #ifndef DNS_MASTERDUMP_H #define DNS_MASTERDUMP_H 1 @@ -220,13 +220,25 @@ dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, dns_masterformat_t format, FILE *f); + +isc_result_t +dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, + dns_masterformat_t format, + dns_masterrawheader_t *header, FILE *f); /*%< * Dump the database 'db' to the steam 'f' in the specified format by * 'format'. If the format is dns_masterformat_text (the RFC1035 format), * 'style' specifies the file style (e.g., &dns_master_style_default). * - * dns_master_dumptostream() is an old form of dns_master_dumptostream2(), + * dns_master_dumptostream() is an old form of dns_master_dumptostream3(), * which always specifies the dns_masterformat_text format. + * dns_master_dumptostream2() is an old form which always specifies + * a NULL header. + * + * If 'format' is dns_masterformat_raw, then 'header' can contain + * information to be written to the file header. * * Temporary dynamic memory may be allocated from 'mctx'. * @@ -256,6 +268,13 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename, isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp, dns_masterformat_t format); +isc_result_t +dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + isc_task_t *task, dns_dumpdonefunc_t done, void + *done_arg, dns_dumpctx_t **dctxp, + dns_masterformat_t format, dns_masterrawheader_t *header); + isc_result_t dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, @@ -267,14 +286,24 @@ dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, const dns_master_style_t *style, const char *filename, dns_masterformat_t format); +isc_result_t +dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + dns_masterformat_t format, dns_masterrawheader_t *header); + /*%< * Dump the database 'db' to the file 'filename' in the specified format by * 'format'. If the format is dns_masterformat_text (the RFC1035 format), * 'style' specifies the file style (e.g., &dns_master_style_default). * - * dns_master_dumpinc() and dns_master_dump() are old forms of _dumpinc2() - * and _dump2(), respectively, which always specify the dns_masterformat_text - * format. + * dns_master_dumpinc() and dns_master_dump() are old forms of _dumpinc3() + * and _dump3(), respectively, which always specify the dns_masterformat_text + * format. dns_master_dumpinc2() and dns_master_dump2() are old forms which + * always specify a NULL header. + * + * If 'format' is dns_masterformat_raw, then 'header' can contain + * information to be written to the file header. * * Temporary dynamic memory may be allocated from 'mctx'. * @@ -329,6 +358,12 @@ dns_master_stylecreate(dns_master_style_t **style, unsigned int flags, unsigned int line_length, unsigned int tab_width, isc_mem_t *mctx); +isc_result_t +dns_master_stylecreate2(dns_master_style_t **style, unsigned int flags, + unsigned int ttl_column, unsigned int class_column, + unsigned int type_column, unsigned int rdata_column, + unsigned int line_length, unsigned int tab_width, + unsigned int split_width, isc_mem_t *mctx); void dns_master_styledestroy(dns_master_style_t **style, isc_mem_t *mctx); diff --git a/contrib/bind9/lib/dns/include/dns/nsec.h b/contrib/bind9/lib/dns/include/dns/nsec.h index 510d96baec20..440ee4e01513 100644 --- a/contrib/bind9/lib/dns/include/dns/nsec.h +++ b/contrib/bind9/lib/dns/include/dns/nsec.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: nsec.h,v 1.14 2011/06/10 23:47:32 tbox Exp $ */ #ifndef DNS_NSEC_H #define DNS_NSEC_H 1 @@ -69,12 +69,35 @@ dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, isc_boolean_t *answer); /* * Report whether the DNSKEY RRset has a NSEC only algorithm. Unknown - * algorithms are assumed to support NSEC3. + * algorithms are assumed to support NSEC3. If DNSKEY is not found, + * *answer is set to ISC_FALSE, and ISC_R_NOTFOUND is returned. * * Requires: * 'answer' to be non NULL. */ +unsigned int +dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw, + unsigned int max_type); +/*%< + * Convert a raw bitmap into a compressed windowed bit map. 'map' and 'raw' + * may overlap. + * + * Returns the length of the compressed windowed bit map. + */ + +void +dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit); +/*%< + * Set type bit in raw 'array' to 'bit'. + */ + +isc_boolean_t +dns_nsec_isset(const unsigned char *array, unsigned int type); +/*%< + * Test if the corresponding 'type' bit is set in 'array'. + */ + isc_result_t dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name, dns_name_t *nsecname, dns_rdataset_t *nsecset, diff --git a/contrib/bind9/lib/dns/include/dns/nsec3.h b/contrib/bind9/lib/dns/include/dns/nsec3.h index 588dd053c06e..e4a22868a2db 100644 --- a/contrib/bind9/lib/dns/include/dns/nsec3.h +++ b/contrib/bind9/lib/dns/include/dns/nsec3.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008-2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: nsec3.h,v 1.14 2011/10/28 12:20:31 tbox Exp $ */ #ifndef DNS_NSEC3_H #define DNS_NSEC3_H 1 @@ -241,7 +241,8 @@ dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target, isc_result_t dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, - dns_zone_t *zone, dns_diff_t *diff); + dns_zone_t *zone, isc_boolean_t nonsec, + dns_diff_t *diff); /*%< * Mark NSEC3PARAM for deletion. diff --git a/contrib/bind9/lib/dns/include/dns/private.h b/contrib/bind9/lib/dns/include/dns/private.h index 7bc59b2cea6d..c4a2ae64f71b 100644 --- a/contrib/bind9/lib/dns/include/dns/private.h +++ b/contrib/bind9/lib/dns/include/dns/private.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: private.h,v 1.5 2011/10/28 12:20:31 tbox Exp $ */ #include #include @@ -50,6 +50,23 @@ dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, * \li other on error */ +isc_result_t +dns_private_totext(dns_rdata_t *privaterdata, isc_buffer_t *buffer); +/*%< + * Convert a private-type RR 'privaterdata' to human-readable form, + * and place the result in 'buffer'. The text should indicate + * which action the private-type record specifies and whether the + * action has been completed. + * + * Requires: + * \li 'privaterdata' is a valid rdata containing at least five bytes + * \li 'buffer' is a valid buffer + * + * Returns: + * \li ISC_R_SUCCESS + * \li other on error + */ + ISC_LANG_ENDDECLS #endif diff --git a/contrib/bind9/lib/dns/include/dns/rdata.h b/contrib/bind9/lib/dns/include/dns/rdata.h index 2a67dc905219..89ecaf800696 100644 --- a/contrib/bind9/lib/dns/include/dns/rdata.h +++ b/contrib/bind9/lib/dns/include/dns/rdata.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: rdata.h,v 1.80 2011/03/20 02:31:53 marka Exp $ */ #ifndef DNS_RDATA_H #define DNS_RDATA_H 1 @@ -169,6 +169,7 @@ struct dns_rdata { /*% Output explanatory comments. */ #define DNS_STYLEFLAG_COMMENT 0x00000002U +#define DNS_STYLEFLAG_RRCOMMENT 0x00000004U #define DNS_RDATA_DOWNCASE DNS_NAME_DOWNCASE #define DNS_RDATA_CHECKNAMES DNS_NAME_CHECKNAMES @@ -435,8 +436,8 @@ dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target); isc_result_t dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, unsigned int flags, - unsigned int width, const char *linebreak, - isc_buffer_t *target); + unsigned int width, unsigned int split_width, + const char *linebreak, isc_buffer_t *target); /*%< * Like dns_rdata_totext, but do formatted output suitable for * database dumps. This is intended for use by dns_db_dump(); @@ -458,6 +459,11 @@ dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, unsigned int flags, * comments next to things like the SOA timer fields. Some * comments (e.g., the SOA ones) are only printed when multiline * output is selected. + * + * base64 rdata text (e.g., DNSKEY records) will be split into chunks + * of 'split_width' characters. If split_width == 0, the text will + * not be split at all. If split_width == UINT_MAX (0xffffffff), then + * it is undefined and falls back to the default value of 'width' */ isc_result_t diff --git a/contrib/bind9/lib/dns/include/dns/rdataset.h b/contrib/bind9/lib/dns/include/dns/rdataset.h index b2b8370db051..31bcd15f1424 100644 --- a/contrib/bind9/lib/dns/include/dns/rdataset.h +++ b/contrib/bind9/lib/dns/include/dns/rdataset.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: rdataset.h,v 1.72 2011/06/08 22:13:51 each Exp $ */ #ifndef DNS_RDATASET_H #define DNS_RDATASET_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/resolver.h b/contrib/bind9/lib/dns/include/dns/resolver.h index 7f7d09317c8d..095269ea2dd2 100644 --- a/contrib/bind9/lib/dns/include/dns/resolver.h +++ b/contrib/bind9/lib/dns/include/dns/resolver.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: resolver.h,v 1.72 2011/12/05 17:10:51 each Exp $ */ #ifndef DNS_RESOLVER_H #define DNS_RESOLVER_H 1 @@ -126,7 +126,8 @@ typedef struct dns_fetchevent { isc_result_t dns_resolver_create(dns_view_t *view, - isc_taskmgr_t *taskmgr, unsigned int ntasks, + isc_taskmgr_t *taskmgr, + unsigned int ntasks, unsigned int ndisp, isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, unsigned int options, @@ -155,9 +156,11 @@ dns_resolver_create(dns_view_t *view, * *\li 'timermgr' is a valid timer manager. * - *\li 'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL. + *\li 'dispatchv4' is a dispatch with an IPv4 UDP socket, or is NULL. + * If not NULL, 'ndisp' clones of it will be created by the resolver. * - *\li 'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL. + *\li 'dispatchv6' is a dispatch with an IPv6 UDP socket, or is NULL. + * If not NULL, 'ndisp' clones of it will be created by the resolver. * *\li resp != NULL && *resp == NULL. * diff --git a/contrib/bind9/lib/dns/include/dns/result.h b/contrib/bind9/lib/dns/include/dns/result.h index 9a7d2c231179..12aacf9ba78a 100644 --- a/contrib/bind9/lib/dns/include/dns/result.h +++ b/contrib/bind9/lib/dns/include/dns/result.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: result.h,v 1.123 2011/03/21 07:22:14 each Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/rpz.h b/contrib/bind9/lib/dns/include/dns/rpz.h index ceea26d04ba5..e1d50a53b555 100644 --- a/contrib/bind9/lib/dns/include/dns/rpz.h +++ b/contrib/bind9/lib/dns/include/dns/rpz.h @@ -16,6 +16,7 @@ /* $Id$ */ + #ifndef DNS_RPZ_H #define DNS_RPZ_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/rriterator.h b/contrib/bind9/lib/dns/include/dns/rriterator.h index a3e8e479b920..c979f2249992 100644 --- a/contrib/bind9/lib/dns/include/dns/rriterator.h +++ b/contrib/bind9/lib/dns/include/dns/rriterator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: rriterator.h,v 1.4 2011/11/01 23:47:00 tbox Exp $ */ #ifndef DNS_RRITERATOR_H #define DNS_RRITERATOR_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/sdb.h b/contrib/bind9/lib/dns/include/dns/sdb.h index c57c4a1d038a..27519034f171 100644 --- a/contrib/bind9/lib/dns/include/dns/sdb.h +++ b/contrib/bind9/lib/dns/include/dns/sdb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: sdb.h,v 1.25 2011/10/11 23:46:45 tbox Exp $ */ #ifndef DNS_SDB_H #define DNS_SDB_H 1 @@ -35,6 +35,7 @@ #include +#include #include /*** @@ -58,10 +59,14 @@ typedef struct dns_sdballnodes dns_sdballnodes_t; typedef isc_result_t (*dns_sdblookupfunc_t)(const char *zone, const char *name, void *dbdata, - dns_sdblookup_t *); + dns_sdblookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo); typedef isc_result_t (*dns_sdblookup2func_t)(const dns_name_t *zone, const dns_name_t *name, - void *dbdata, dns_sdblookup_t *lookup); + void *dbdata, dns_sdblookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo); typedef isc_result_t (*dns_sdbauthorityfunc_t)(const char *zone, void *dbdata, dns_sdblookup_t *); diff --git a/contrib/bind9/lib/dns/include/dns/sdlz.h b/contrib/bind9/lib/dns/include/dns/sdlz.h index 375a99a6d69e..fbc6b95e70d1 100644 --- a/contrib/bind9/lib/dns/include/dns/sdlz.h +++ b/contrib/bind9/lib/dns/include/dns/sdlz.h @@ -57,6 +57,7 @@ #ifndef SDLZ_H #define SDLZ_H 1 +#include #include ISC_LANG_BEGINDECLS @@ -182,18 +183,23 @@ typedef isc_result_t typedef isc_result_t (*dns_sdlzlookupfunc_t)(const char *zone, const char *name, void *driverarg, - void *dbdata, dns_sdlzlookup_t *lookup); + void *dbdata, dns_sdlzlookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo); /*%< * Method prototype. Drivers implementing the SDLZ interface MUST - * supply a lookup method. This method is called when the DNS server - * is performing a query, after the find zone and before any other - * methods have been called. This function returns record DNS record + * supply a lookup method. This method is called when the + * DNS server is performing a query, after the find zone and before any + * other methods have been called. This function returns DNS record * information using the dns_sdlz_putrr and dns_sdlz_putsoa functions. * If this function supplies authority information for the DNS record * the authority method is not required. If it does not, the - * authority function is required. A SDLZ driver must implement a - * lookup method. + * authority function is required. + * + * The 'methods' and 'clientinfo' args allow an SDLZ driver to retrieve + * information about the querying client (such as source IP address) + * from the caller. */ typedef isc_result_t (*dns_sdlznewversion_t)(const char *zone, diff --git a/contrib/bind9/lib/dns/include/dns/time.h b/contrib/bind9/lib/dns/include/dns/time.h index b646ba80edbf..6a59c8a056ee 100644 --- a/contrib/bind9/lib/dns/include/dns/time.h +++ b/contrib/bind9/lib/dns/include/dns/time.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: time.h,v 1.19 2012/01/27 23:46:58 tbox Exp $ */ #ifndef DNS_TIME_H #define DNS_TIME_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/types.h b/contrib/bind9/lib/dns/include/dns/types.h index a0318256b6a4..76167c2f88da 100644 --- a/contrib/bind9/lib/dns/include/dns/types.h +++ b/contrib/bind9/lib/dns/include/dns/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -65,6 +65,7 @@ typedef struct dns_decompress dns_decompress_t; typedef struct dns_dispatch dns_dispatch_t; typedef struct dns_dispatchevent dns_dispatchevent_t; typedef struct dns_dispatchlist dns_dispatchlist_t; +typedef struct dns_dispatchset dns_dispatchset_t; typedef struct dns_dispatchmgr dns_dispatchmgr_t; typedef struct dns_dispentry dns_dispentry_t; typedef struct dns_dns64 dns_dns64_t; @@ -86,6 +87,7 @@ typedef struct dns_keytable dns_keytable_t; typedef isc_uint16_t dns_keytag_t; typedef struct dns_loadctx dns_loadctx_t; typedef struct dns_loadmgr dns_loadmgr_t; +typedef struct dns_masterrawheader dns_masterrawheader_t; typedef struct dns_message dns_message_t; typedef isc_uint16_t dns_messageid_t; typedef isc_region_t dns_label_t; @@ -333,6 +335,20 @@ typedef enum { dns_severity_fail } dns_severity_t; +/*% + * DNS Serial Number Update Method. + * + * \li _increment: Add one to the current serial, skipping 0. + * \li _unixtime: Set to the seconds since 00:00 Jan 1, 1970, + * if possible. + * \li _yyyymmvv: Set to Year, Month, Version, if possible. + * (Not yet implemented) + */ +typedef enum { + dns_updatemethod_increment = 0, + dns_updatemethod_unixtime +} dns_updatemethod_t; + /* * Functions. */ @@ -342,6 +358,9 @@ typedef void typedef void (*dns_loaddonefunc_t)(void *, isc_result_t); +typedef void +(*dns_rawdatafunc_t)(dns_zone_t *, dns_masterrawheader_t *); + typedef isc_result_t (*dns_addrdatasetfunc_t)(void *, dns_name_t *, dns_rdataset_t *); diff --git a/contrib/bind9/lib/dns/include/dns/update.h b/contrib/bind9/lib/dns/include/dns/update.h new file mode 100644 index 000000000000..2d2c491f38a3 --- /dev/null +++ b/contrib/bind9/lib/dns/include/dns/update.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: update.h,v 1.5 2011/08/30 23:46:53 tbox Exp $ */ + +#ifndef DNS_UPDATE_H +#define DNS_UPDATE_H 1 + +/*! \file dns/update.h */ + +/*** + *** Imports + ***/ + +#include + +#include +#include + +typedef struct { + void (*func)(void *arg, dns_zone_t *zone, int level, + const char *message); + void *arg; +} dns_update_log_t; + +ISC_LANG_BEGINDECLS + +/*** + *** Functions + ***/ + +isc_uint32_t +dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method); +/*%< + * Return the next serial number after 'serial', depending on the + * update method 'method': + * + *\li * dns_updatemethod_increment increments the serial number by one + *\li * dns_updatemethod_unixtime sets the serial number to the current + * time (seconds since UNIX epoch) if possible, or increments by one + * if not. + */ + +isc_result_t +dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *oldver, dns_dbversion_t *newver, + dns_diff_t *diff, isc_uint32_t sigvalidityinterval); + +ISC_LANG_ENDDECLS + +#endif /* DNS_UPDATE_H */ diff --git a/contrib/bind9/lib/dns/include/dns/view.h b/contrib/bind9/lib/dns/include/dns/view.h index d999fa1db604..d0c1931d27be 100644 --- a/contrib/bind9/lib/dns/include/dns/view.h +++ b/contrib/bind9/lib/dns/include/dns/view.h @@ -76,6 +76,7 @@ #include #include #include +#include ISC_LANG_BEGINDECLS @@ -141,7 +142,6 @@ struct dns_view { dns_rbt_t * answeracl_exclude; dns_rbt_t * denyanswernames; dns_rbt_t * answernames_exclude; - isc_boolean_t requestixfr; isc_boolean_t provideixfr; isc_boolean_t requestnsid; dns_ttl_t maxcachettl; @@ -157,6 +157,7 @@ struct dns_view { dns_name_t * dlv; dns_fixedname_t dlv_fixed; isc_uint16_t maxudp; + unsigned int maxbits; dns_v4_aaaa_t v4_aaaa; dns_acl_t * v4_aaaa_acl; dns_dns64list_t dns64; @@ -185,6 +186,7 @@ struct dns_view { dns_viewlist_t * viewlist; dns_zone_t * managed_keys; + dns_zone_t * redirect; #ifdef BIND9 /* File in which to store configuration for newly added zones */ @@ -312,7 +314,8 @@ dns_view_weakdetach(dns_view_t **targetp); isc_result_t dns_view_createresolver(dns_view_t *view, - isc_taskmgr_t *taskmgr, unsigned int ntasks, + isc_taskmgr_t *taskmgr, + unsigned int ntasks, unsigned int ndisp, isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, unsigned int options, @@ -730,14 +733,21 @@ dns_view_load(dns_view_t *view, isc_boolean_t stop); isc_result_t dns_view_loadnew(dns_view_t *view, isc_boolean_t stop); + +isc_result_t +dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg); /*%< * Load zones attached to this view. dns_view_load() loads * all zones whose master file has changed since the last * load; dns_view_loadnew() loads only zones that have never * been loaded. * + * dns_view_asyncload() loads zones asynchronously. When all zones + * in the view have finished loading, 'callback' is called with argument + * 'arg' to inform the caller. + * * If 'stop' is ISC_TRUE, stop on the first error and return it. - * If 'stop' is ISC_FALSE, ignore errors. + * If 'stop' is ISC_FALSE (or we are loading asynchronously), ignore errors. * * Requires: * @@ -841,9 +851,31 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly); */ isc_result_t -dns_view_flushname(dns_view_t *view, dns_name_t *); +dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree); /*%< - * Flush the given name from the view's cache (and ADB). + * Flush the given name from the view's cache (and optionally ADB/badcache). + * + * If 'tree' is true, flush 'name' and all names below it + * from the cache, but do not flush ADB. + * + * If 'tree' is false, flush 'name' frmo both the cache and ADB, + * but do not touch any other nodes. + * + * Requires: + *\li 'view' is valid. + *\li 'name' is valid. + * + * Returns: + *\li #ISC_R_SUCCESS + * other returns are failures. + */ + +isc_result_t +dns_view_flushname(dns_view_t *view, dns_name_t *name); +/*%< + * Flush the given name from the view's cache, ADB and badcache. + * Equivalent to dns_view_flushnode(view, name, ISC_FALSE). + * * * Requires: *\li 'view' is valid. @@ -859,7 +891,6 @@ dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name); /*%< * Add the given name to the delegation only table. * - * * Requires: *\li 'view' is valid. *\li 'name' is valid. diff --git a/contrib/bind9/lib/dns/include/dns/zone.h b/contrib/bind9/lib/dns/include/dns/zone.h index 6b9911d5897d..f91801f6fe3f 100644 --- a/contrib/bind9/lib/dns/include/dns/zone.h +++ b/contrib/bind9/lib/dns/include/dns/zone.h @@ -32,10 +32,12 @@ #include #include +#include #include #include #include #include +#include typedef enum { dns_zone_none, @@ -44,9 +46,16 @@ typedef enum { dns_zone_stub, dns_zone_staticstub, dns_zone_key, - dns_zone_dlz + dns_zone_dlz, + dns_zone_redirect } dns_zonetype_t; +typedef enum { + dns_zonestat_none = 0, + dns_zonestat_terse, + dns_zonestat_full +} dns_zonestat_level_t; + #define DNS_ZONEOPT_SERVERS 0x00000001U /*%< perform server checks */ #define DNS_ZONEOPT_PARENTS 0x00000002U /*%< perform parent checks */ #define DNS_ZONEOPT_CHILDREN 0x00000004U /*%< perform child checks */ @@ -94,6 +103,7 @@ typedef enum { #define DNS_ZONEKEY_MAINTAIN 0x00000002U /*%< publish/sign on schedule */ #define DNS_ZONEKEY_CREATE 0x00000004U /*%< make keys when needed */ #define DNS_ZONEKEY_FULLSIGN 0x00000008U /*%< roll to new keys immediately */ +#define DNS_ZONEKEY_NORESIGN 0x00000010U /*%< no automatic resigning */ #ifndef DNS_ZONE_MINREFRESH #define DNS_ZONE_MINREFRESH 300 /*%< 5 minutes */ @@ -287,6 +297,7 @@ dns_zone_loadnew(dns_zone_t *zone); isc_result_t dns_zone_loadandthaw(dns_zone_t *zone); + /*%< * Cause the database to be loaded from its backing store. * Confirm that the minimum requirements for the zone type are @@ -311,6 +322,25 @@ dns_zone_loadandthaw(dns_zone_t *zone); *\li Any result value from dns_db_load(). */ +isc_result_t +dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg); +/*%< + * Cause the database to be loaded from its backing store asynchronously. + * Other zone maintenance functions are suspended until this is complete. + * When finished, 'done' is called to inform the caller, with 'arg' as + * its first argument and 'zone' as its second. (Normally, 'arg' is + * expected to point to the zone table but is left undefined for testing + * purposes.) + */ + +isc_boolean_t +dns__zone_loadpending(dns_zone_t *zone); +/*%< + * Indicates whether the zone is waiting to be loaded asynchronously. + * (Not currently intended for use outside of this module and associated + * tests.) + */ + void dns_zone_attach(dns_zone_t *source, dns_zone_t **target); /*%< @@ -489,6 +519,10 @@ dns_zone_dumptostream(dns_zone_t *zone, FILE *fd); isc_result_t dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, const dns_master_style_t *style); +isc_result_t +dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, + const dns_master_style_t *style, + const isc_uint32_t rawversion); /*%< * Write the zone to stream 'fd' in the specified 'format'. * If the 'format' is dns_masterformat_text (RFC1035), 'style' also @@ -498,7 +532,11 @@ dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, * dns_zone_dumptostream2(), which always uses the dns_masterformat_text * format and the dns_master_style_default style. * - * Note that dns_zone_dumptostream2() is the most flexible form. It + * dns_zone_dumptostream2() is a backward-compatible form of + * dns_zone_dumptostream3(), which always uses the current + * default raw file format version. + * + * Note that dns_zone_dumptostream3() is the most flexible form. It * can also provide the functionality of dns_zone_fulldumptostream(). * * Require: @@ -558,10 +596,16 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, isc_result_t dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, isc_uint32_t count); +isc_result_t +dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify, + dns_name_t **keynames, isc_uint32_t count); /*%< * Set the list of additional servers to be notified when * a zone changes. To clear the list use 'count = 0'. * + * dns_zone_alsonotifywithkeys() allows each notify address to + * be associated with a TSIG key. + * * Require: *\li 'zone' to be a valid zone. *\li 'notify' to be non-NULL if count != 0. @@ -1404,6 +1448,18 @@ dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones); *\li zmgr->zonetasks has been initialized. */ +isc_result_t +dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep); +/*%< + * Allocate a new zone using a memory context from the + * zone manager's memory context pool. + * + * Require: + *\li 'zmgr' to be a valid zone manager. + *\li 'zonep' != NULL and '*zonep' == NULL. + */ + + isc_result_t dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone); /*%< @@ -1421,6 +1477,14 @@ dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr); * earliest convenience. */ +void +dns__zonemgr_run(isc_task_t *task, isc_event_t *event); +/*%< + * Event handler to call dns_zonemgr_forcemaint(); used to start + * zone operations from a unit test. Not intended for use outside + * libdns or related tests. + */ + void dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr); /*%< @@ -1647,9 +1711,13 @@ dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats); void dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats); + +void +dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats); /*%< - * Set an additional statistics set to zone. It is attached in the zone - * but is not counted in the zone module; only the caller updates the counters. + * Set additional statistics sets to zone. These are attached to the zone + * but are not counted in the zone module; only the caller updates the + * counters. * * Requires: * \li 'zone' to be a valid zone. @@ -1657,8 +1725,19 @@ dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats); *\li stats is a valid statistics. */ +#ifdef NEWSTATS +void +dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats); +#endif + isc_stats_t * dns_zone_getrequeststats(dns_zone_t *zone); + +#ifdef NEWSTATS +dns_stats_t * +dns_zone_getrcvquerystats(dns_zone_t *zone); +#endif + /*%< * Get the additional statistics for zone, if one is installed. * @@ -1893,6 +1972,107 @@ dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db); * Load the origin names for a writeable DLZ database. */ +isc_boolean_t +dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze); +/*% + * Return true iff the zone is "dynamic", in the sense that the zone's + * master file (if any) is written by the server, rather than being + * updated manually and read by the server. + * + * This is true for slave zones, stub zones, key zones, and zones that + * allow dynamic updates either by having an update policy ("ssutable") + * or an "allow-update" ACL with a value other than exactly "{ none; }". + * + * If 'ignore_freeze' is true, then the zone which has had updates disabled + * will still report itself to be dynamic. + * + * Requires: + * \li 'zone' to be valid. + */ + +isc_result_t +dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval); +/*% + * Sets the frequency, in minutes, with which the key repository will be + * checked to see if the keys for this zone have been updated. Any value + * higher than 1440 minutes (24 hours) will be silently reduced. A + * value of zero will return an out-of-range error. + * + * Requires: + * \li 'zone' to be valid. + */ + +isc_boolean_t +dns_zone_getrequestixfr(dns_zone_t *zone); +/*% + * Returns the true/false value of the request-ixfr option in the zone. + * + * Requires: + * \li 'zone' to be valid. + */ + +void +dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag); +/*% + * Sets the request-ixfr option for the zone. Either true or false. The + * default value is determined by the setting of this option in the view. + * + * Requires: + * \li 'zone' to be valid. + */ + +void +dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method); +/*% + * Sets the update method to use when incrementing the zone serial number + * due to a DDNS update. Valid options are dns_updatemethod_increment + * and dns_updatemethod_unixtime. + * + * Requires: + * \li 'zone' to be valid. + */ + +dns_updatemethod_t +dns_zone_getserialupdatemethod(dns_zone_t *zone); +/*% + * Returns the update method to be used when incrementing the zone serial + * number due to a DDNS update. + * + * Requires: + * \li 'zone' to be valid. + */ + +isc_result_t +dns_zone_link(dns_zone_t *zone, dns_zone_t *raw); + +void +dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw); + +isc_result_t +dns_zone_keydone(dns_zone_t *zone, const char *data); + +isc_result_t +dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags, + isc_uint16_t iter, isc_uint8_t saltlen, + unsigned char *salt, isc_boolean_t replace); +/*% + * Set the NSEC3 parameters for the zone. + * + * If 'replace' is ISC_TRUE, then the existing NSEC3 chain, if any, will + * be replaced with the new one. If 'hash' is zero, then the replacement + * chain will be NSEC rather than NSEC3. + * + * Requires: + * \li 'zone' to be valid. + */ + +void +dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header); +/*% + * Set the data to be included in the header when the zone is dumped in + * binary format. + */ + isc_result_t dns_zone_synckeyzone(dns_zone_t *zone); /*% @@ -1909,6 +2089,16 @@ dns_zone_rpz_enable(dns_zone_t *zone); isc_boolean_t dns_zone_get_rpz(dns_zone_t *zone); +void +dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level); + +dns_zonestat_level_t +dns_zone_getstatlevel(dns_zone_t *zone); +/*% + * Set and get the statistics reporting level for the zone; + * full, terse, or none. + */ + ISC_LANG_ENDDECLS #endif /* DNS_ZONE_H */ diff --git a/contrib/bind9/lib/dns/include/dns/zt.h b/contrib/bind9/lib/dns/include/dns/zt.h index 7d1e8bfdfd84..f91d7e8dbe0f 100644 --- a/contrib/bind9/lib/dns/include/dns/zt.h +++ b/contrib/bind9/lib/dns/include/dns/zt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: zt.h,v 1.40 2011/09/02 23:46:32 tbox Exp $ */ #ifndef DNS_ZT_H #define DNS_ZT_H 1 @@ -30,6 +30,21 @@ ISC_LANG_BEGINDECLS +typedef isc_result_t +(*dns_zt_allloaded_t)(void *arg); +/*%< + * Method prototype: when all pending zone loads are complete, + * the zone table can inform the caller via a callback function with + * this signature. + */ + +typedef isc_result_t +(*dns_zt_zoneloaded_t)(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task); +/*%< + * Method prototype: when a zone finishes loading, the zt object + * can be informed via a callback function with this signature. + */ + isc_result_t dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **zt); /*%< @@ -134,6 +149,9 @@ dns_zt_load(dns_zt_t *zt, isc_boolean_t stop); isc_result_t dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop); + +isc_result_t +dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg); /*%< * Load all zones in the table. If 'stop' is ISC_TRUE, * stop on the first error and return it. If 'stop' @@ -142,6 +160,10 @@ dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop); * dns_zt_loadnew() only loads zones that are not yet loaded. * dns_zt_load() also loads zones that are already loaded and * and whose master file has changed since the last load. + * dns_zt_asyncload() loads zones asynchronously; when all + * zones in the zone table have finished loaded (or failed due + * to errors), the caller is informed by calling 'alldone' + * with an argument of 'arg'. * * Requires: * \li 'zt' to be valid @@ -178,6 +200,16 @@ dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub, * any error code from 'action'. */ +isc_boolean_t +dns_zt_loadspending(dns_zt_t *zt); +/*%< + * Returns ISC_TRUE if and only if there are zones still waiting to + * be loaded in zone table 'zt'. + * + * Requires: + * \li 'zt' to be valid. + */ + ISC_LANG_ENDDECLS #endif /* DNS_ZT_H */ diff --git a/contrib/bind9/lib/dns/include/dst/dst.h b/contrib/bind9/lib/dns/include/dst/dst.h index 87d844bf2270..4724fc64c95e 100644 --- a/contrib/bind9/lib/dns/include/dst/dst.h +++ b/contrib/bind9/lib/dns/include/dst/dst.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: dst.h,v 1.34 2011/10/20 21:20:02 marka Exp $ */ #ifndef DST_DST_H #define DST_DST_H 1 @@ -239,9 +239,16 @@ dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig); isc_result_t dst_context_verify(dst_context_t *dctx, isc_region_t *sig); + +isc_result_t +dst_context_verify2(dst_context_t *dctx, unsigned int maxbits, + isc_region_t *sig); /*%< * Verifies the signature using the data and key stored in the context. * + * 'maxbits' specifies the maximum number of bits permitted in the RSA + * exponent. + * * Requires: * \li "dctx" is a valid context. * \li "sig" is a valid region. @@ -498,6 +505,14 @@ dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, * the context id. */ +#ifdef DST_KEY_INTERNAL +isc_result_t +dst_key_buildinternal(dns_name_t *name, unsigned int alg, + unsigned int bits, unsigned int flags, + unsigned int protocol, dns_rdataclass_t rdclass, + void *data, isc_mem_t *mctx, dst_key_t **keyp); +#endif + isc_result_t dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, @@ -518,6 +533,7 @@ dst_key_generate2(dns_name_t *name, unsigned int alg, dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp, void (*callback)(int)); + /*%< * Generate a DST key (or keypair) with the supplied parameters. The * interpretation of the "param" field depends on the algorithm: @@ -748,6 +764,26 @@ dst_key_setbits(dst_key_t *key, isc_uint16_t bits); * "key" is a valid key. */ +void +dst_key_setttl(dst_key_t *key, dns_ttl_t ttl); +/*%< + * Set the default TTL to use when converting the key + * to a KEY or DNSKEY RR. + * + * Requires: + * "key" is a valid key. + */ + +dns_ttl_t +dst_key_getttl(const dst_key_t *key); +/*%< + * Get the default TTL to use when converting the key + * to a KEY or DNSKEY RR. + * + * Requires: + * "key" is a valid key. + */ + isc_result_t dst_key_setflags(dst_key_t *key, isc_uint32_t flags); /* diff --git a/contrib/bind9/lib/dns/iptable.c b/contrib/bind9/lib/dns/iptable.c index e960d5c48cd1..701950533c9e 100644 --- a/contrib/bind9/lib/dns/iptable.c +++ b/contrib/bind9/lib/dns/iptable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2007-2009, 2013 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -36,7 +36,8 @@ dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target) { tab = isc_mem_get(mctx, sizeof(*tab)); if (tab == NULL) return (ISC_R_NOMEMORY); - tab->mctx = mctx; + tab->mctx = NULL; + isc_mem_attach(mctx, &tab->mctx); isc_refcount_init(&tab->refcount, 1); tab->radix = NULL; tab->magic = DNS_IPTABLE_MAGIC; @@ -184,5 +185,5 @@ destroy_iptable(dns_iptable_t *dtab) { isc_refcount_destroy(&dtab->refcount); dtab->magic = 0; - isc_mem_put(dtab->mctx, dtab, sizeof(*dtab)); + isc_mem_putanddetach(&dtab->mctx, dtab, sizeof(*dtab)); } diff --git a/contrib/bind9/lib/dns/journal.c b/contrib/bind9/lib/dns/journal.c index 1564a811ffed..022a3e280f83 100644 --- a/contrib/bind9/lib/dns/journal.c +++ b/contrib/bind9/lib/dns/journal.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: journal.c,v 1.120 2011/12/22 07:32:41 each Exp $ */ #include @@ -111,6 +111,8 @@ static isc_boolean_t bind8_compat = ISC_TRUE; /* XXX config */ if (result != ISC_R_SUCCESS) goto failure; \ } while (0) +#define JOURNAL_SERIALSET 0x01U + static isc_result_t index_to_disk(dns_journal_t *); static inline isc_uint32_t @@ -213,6 +215,9 @@ typedef union { journal_rawpos_t end; /*% Number of index entries following the header. */ unsigned char index_size[4]; + /*% Source serial number. */ + unsigned char sourceserial[4]; + unsigned char flags; } h; /* Pad the header to a fixed size. */ unsigned char pad[JOURNAL_HEADER_SIZE]; @@ -252,6 +257,8 @@ typedef struct { journal_pos_t begin; journal_pos_t end; isc_uint32_t index_size; + isc_uint32_t sourceserial; + isc_boolean_t serialset; } journal_header_t; /*% @@ -284,7 +291,7 @@ typedef struct { */ static journal_header_t -initial_journal_header = { ";BIND LOG V9\n", { 0, 0 }, { 0, 0 }, 0 }; +initial_journal_header = { ";BIND LOG V9\n", { 0, 0 }, { 0, 0 }, 0, 0, 0 }; #define JOURNAL_EMPTY(h) ((h)->begin.offset == (h)->end.offset) @@ -292,7 +299,8 @@ typedef enum { JOURNAL_STATE_INVALID, JOURNAL_STATE_READ, JOURNAL_STATE_WRITE, - JOURNAL_STATE_TRANSACTION + JOURNAL_STATE_TRANSACTION, + JOURNAL_STATE_INLINE } journal_state_t; struct dns_journal { @@ -353,16 +361,24 @@ journal_header_decode(journal_rawheader_t *raw, journal_header_t *cooked) { journal_pos_decode(&raw->h.begin, &cooked->begin); journal_pos_decode(&raw->h.end, &cooked->end); cooked->index_size = decode_uint32(raw->h.index_size); + cooked->sourceserial = decode_uint32(raw->h.sourceserial); + cooked->serialset = ISC_TF(raw->h.flags & JOURNAL_SERIALSET); } static void journal_header_encode(journal_header_t *cooked, journal_rawheader_t *raw) { + unsigned char flags = 0; + INSIST(sizeof(cooked->format) == sizeof(raw->h.format)); memset(raw->pad, 0, sizeof(raw->pad)); memcpy(raw->h.format, cooked->format, sizeof(raw->h.format)); journal_pos_encode(&raw->h.begin, &cooked->begin); journal_pos_encode(&raw->h.end, &cooked->end); encode_uint32(cooked->index_size, raw->h.index_size); + encode_uint32(cooked->sourceserial, raw->h.sourceserial); + if (cooked->serialset) + flags |= JOURNAL_SERIALSET; + raw->h.flags = flags; } /* @@ -540,7 +556,8 @@ journal_file_create(isc_mem_t *mctx, const char *filename) { static isc_result_t journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, - isc_boolean_t create, dns_journal_t **journalp) { + isc_boolean_t create, dns_journal_t **journalp) +{ FILE *fp = NULL; isc_result_t result; journal_rawheader_t rawheader; @@ -551,7 +568,8 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, if (j == NULL) return (ISC_R_NOMEMORY); - j->mctx = mctx; + j->mctx = NULL; + isc_mem_attach(mctx, &j->mctx); j->state = JOURNAL_STATE_INVALID; j->fp = NULL; j->filename = filename; @@ -662,18 +680,23 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, } if (j->fp != NULL) (void)isc_stdio_close(j->fp); - isc_mem_put(j->mctx, j, sizeof(*j)); + isc_mem_putanddetach(&j->mctx, j, sizeof(*j)); return (result); } isc_result_t -dns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, - dns_journal_t **journalp) { +dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, + dns_journal_t **journalp) +{ isc_result_t result; int namelen; char backup[1024]; + isc_boolean_t write, create; - result = journal_open(mctx, filename, write, write, journalp); + create = ISC_TF(mode & DNS_JOURNAL_CREATE); + write = ISC_TF(mode & (DNS_JOURNAL_WRITE|DNS_JOURNAL_CREATE)); + + result = journal_open(mctx, filename, write, create, journalp); if (result == ISC_R_NOTFOUND) { namelen = strlen(filename); if (namelen > 4 && strcmp(filename + namelen - 4, ".jnl") == 0) @@ -944,7 +967,8 @@ dns_journal_begin_transaction(dns_journal_t *j) { journal_rawxhdr_t hdr; REQUIRE(DNS_JOURNAL_VALID(j)); - REQUIRE(j->state == JOURNAL_STATE_WRITE); + REQUIRE(j->state == JOURNAL_STATE_WRITE || + j->state == JOURNAL_STATE_INLINE); /* * Find the file offset where the new transaction should @@ -1067,7 +1091,21 @@ dns_journal_commit(dns_journal_t *j) { journal_rawheader_t rawheader; REQUIRE(DNS_JOURNAL_VALID(j)); - REQUIRE(j->state == JOURNAL_STATE_TRANSACTION); + REQUIRE(j->state == JOURNAL_STATE_TRANSACTION || + j->state == JOURNAL_STATE_INLINE); + + /* + * Just write out a updated header. + */ + if (j->state == JOURNAL_STATE_INLINE) { + CHECK(journal_fsync(j)); + journal_header_encode(&j->header, &rawheader); + CHECK(journal_seek(j, 0)); + CHECK(journal_write(j, &rawheader, sizeof(rawheader))); + CHECK(journal_fsync(j)); + j->state = JOURNAL_STATE_WRITE; + return (ISC_R_SUCCESS); + } /* * Perform some basic consistency checks. @@ -1124,20 +1162,23 @@ dns_journal_commit(dns_journal_t *j) { */ CHECK(journal_fsync(j)); - /* - * Update the transaction header. - */ - CHECK(journal_seek(j, j->x.pos[0].offset)); - CHECK(journal_write_xhdr(j, (j->x.pos[1].offset - j->x.pos[0].offset) - - sizeof(journal_rawxhdr_t), - j->x.pos[0].serial, j->x.pos[1].serial)); + if (j->state == JOURNAL_STATE_TRANSACTION) { + isc_offset_t offset; + offset = (j->x.pos[1].offset - j->x.pos[0].offset) - + sizeof(journal_rawxhdr_t); + /* + * Update the transaction header. + */ + CHECK(journal_seek(j, j->x.pos[0].offset)); + CHECK(journal_write_xhdr(j, offset, j->x.pos[0].serial, + j->x.pos[1].serial)); + } /* * Update the journal header. */ - if (JOURNAL_EMPTY(&j->header)) { + if (JOURNAL_EMPTY(&j->header)) j->header.begin = j->x.pos[0]; - } j->header.end = j->x.pos[1]; journal_header_encode(&j->header, &rawheader); CHECK(journal_seek(j, 0)); @@ -1204,7 +1245,7 @@ dns_journal_destroy(dns_journal_t **journalp) { if (j->fp != NULL) (void)isc_stdio_close(j->fp); j->magic = 0; - isc_mem_put(j->mctx, j, sizeof(*j)); + isc_mem_putanddetach(&j->mctx, j, sizeof(*j)); *journalp = NULL; } @@ -1369,7 +1410,7 @@ dns_journal_rollforward2(isc_mem_t *mctx, dns_db_t *db, unsigned int options, REQUIRE(filename != NULL); j = NULL; - result = dns_journal_open(mctx, filename, ISC_FALSE, &j); + result = dns_journal_open(mctx, filename, DNS_JOURNAL_READ, &j); if (result == ISC_R_NOTFOUND) { isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no journal file, but that's OK"); @@ -1402,7 +1443,7 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) { REQUIRE(filename != NULL); j = NULL; - result = dns_journal_open(mctx, filename, ISC_FALSE, &j); + result = dns_journal_open(mctx, filename, DNS_JOURNAL_READ, &j); if (result == ISC_R_NOTFOUND) { isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no journal file"); return (DNS_R_NOJOURNAL); @@ -1415,6 +1456,8 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) { return (result); } + if (j->header.serialset) + fprintf(file, "Source serial = %u\n", j->header.sourceserial); dns_diff_init(j->mctx, &diff); /* @@ -1497,14 +1540,39 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) { /* * Miscellaneous accessors. */ -isc_uint32_t dns_journal_first_serial(dns_journal_t *j) { +isc_uint32_t +dns_journal_first_serial(dns_journal_t *j) { return (j->header.begin.serial); } -isc_uint32_t dns_journal_last_serial(dns_journal_t *j) { +isc_uint32_t +dns_journal_last_serial(dns_journal_t *j) { return (j->header.end.serial); } +void +dns_journal_set_sourceserial(dns_journal_t *j, isc_uint32_t sourceserial) { + + REQUIRE(j->state == JOURNAL_STATE_WRITE || + j->state == JOURNAL_STATE_INLINE || + j->state == JOURNAL_STATE_TRANSACTION); + + j->header.sourceserial = sourceserial; + j->header.serialset = ISC_TRUE; + if (j->state == JOURNAL_STATE_WRITE) + j->state = JOURNAL_STATE_INLINE; +} + +isc_boolean_t +dns_journal_get_sourceserial(dns_journal_t *j, isc_uint32_t *sourceserial) { + REQUIRE(sourceserial != NULL); + + if (!j->header.serialset) + return (ISC_FALSE); + *sourceserial = j->header.sourceserial; + return (ISC_TRUE); +} + /**************************************************************************/ /* * Iteration support. @@ -1860,8 +1928,7 @@ dns_diff_subtract(dns_diff_t diff[2], dns_diff_t *r) { } static isc_result_t -diff_namespace(isc_mem_t *mctx, - dns_db_t *dba, dns_dbversion_t *dbvera, +diff_namespace(dns_db_t *dba, dns_dbversion_t *dbvera, dns_db_t *dbb, dns_dbversion_t *dbverb, unsigned int options, dns_diff_t *resultdiff) { @@ -1877,8 +1944,8 @@ diff_namespace(isc_mem_t *mctx, db[0] = dba, db[1] = dbb; ver[0] = dbvera, ver[1] = dbverb; - dns_diff_init(mctx, &diff[0]); - dns_diff_init(mctx, &diff[1]); + dns_diff_init(resultdiff->mctx, &diff[0]); + dns_diff_init(resultdiff->mctx, &diff[1]); dns_fixedname_init(&fixname[0]); dns_fixedname_init(&fixname[1]); @@ -1956,8 +2023,11 @@ diff_namespace(isc_mem_t *mctx, failure: dns_dbiterator_destroy(&dbit[1]); + cleanup_iterator: dns_dbiterator_destroy(&dbit[0]); + dns_diff_clear(&diff[0]); + dns_diff_clear(&diff[1]); return (result); } @@ -1968,33 +2038,48 @@ diff_namespace(isc_mem_t *mctx, * possibly very large transaction. */ isc_result_t -dns_db_diff(isc_mem_t *mctx, - dns_db_t *dba, dns_dbversion_t *dbvera, - dns_db_t *dbb, dns_dbversion_t *dbverb, - const char *journal_filename) +dns_db_diff(isc_mem_t *mctx, dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, const char *filename) +{ + isc_result_t result; + dns_diff_t diff; + + dns_diff_init(mctx, &diff); + + result = dns_db_diffx(&diff, dba, dbvera, dbb, dbverb, filename); + + dns_diff_clear(&diff); + + return (result); +} + +isc_result_t +dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, const char *filename) { isc_result_t result; dns_journal_t *journal = NULL; - dns_diff_t resultdiff; - result = dns_journal_open(mctx, journal_filename, ISC_TRUE, &journal); - if (result != ISC_R_SUCCESS) - return (result); - - dns_diff_init(mctx, &resultdiff); - - CHECK(diff_namespace(mctx, dba, dbvera, dbb, dbverb, - DNS_DB_NONSEC3, &resultdiff)); - CHECK(diff_namespace(mctx, dba, dbvera, dbb, dbverb, - DNS_DB_NSEC3ONLY, &resultdiff)); - if (ISC_LIST_EMPTY(resultdiff.tuples)) { - isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes"); - } else { - CHECK(dns_journal_write_transaction(journal, &resultdiff)); + if (filename != NULL) { + result = dns_journal_open(diff->mctx, filename, + DNS_JOURNAL_CREATE, &journal); + if (result != ISC_R_SUCCESS) + return (result); } + + CHECK(diff_namespace(dba, dbvera, dbb, dbverb, DNS_DB_NONSEC3, diff)); + CHECK(diff_namespace(dba, dbvera, dbb, dbverb, DNS_DB_NSEC3ONLY, diff)); + + if (journal != NULL) { + if (ISC_LIST_EMPTY(diff->tuples)) + isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes"); + else + CHECK(dns_journal_write_transaction(journal, diff)); + } + failure: - dns_diff_clear(&resultdiff); - dns_journal_destroy(&journal); + if (journal != NULL) + dns_journal_destroy(&journal); return (result); } @@ -2145,6 +2230,8 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial, new->header.begin.offset = indexend; new->header.end.serial = j->header.end.serial; new->header.end.offset = indexend + copy_length; + new->header.sourceserial = j->header.sourceserial; + new->header.serialset = j->header.serialset; /* * Update the journal header. diff --git a/contrib/bind9/lib/dns/key.c b/contrib/bind9/lib/dns/key.c index bf9b16c170c4..ccac157c13f0 100644 --- a/contrib/bind9/lib/dns/key.c +++ b/contrib/bind9/lib/dns/key.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: key.c,v 1.11 2011/10/20 21:20:02 marka Exp $ */ #include @@ -177,4 +177,16 @@ dst_key_getbits(const dst_key_t *key) { return (key->key_bits); } +void +dst_key_setttl(dst_key_t *key, dns_ttl_t ttl) { + REQUIRE(VALID_KEY(key)); + key->key_ttl = ttl; +} + +dns_ttl_t +dst_key_getttl(const dst_key_t *key) { + REQUIRE(VALID_KEY(key)); + return (key->key_ttl); +} + /*! \file */ diff --git a/contrib/bind9/lib/dns/keytable.c b/contrib/bind9/lib/dns/keytable.c index 309e9dd2d8d5..c49847f326ad 100644 --- a/contrib/bind9/lib/dns/keytable.c +++ b/contrib/bind9/lib/dns/keytable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -67,7 +67,8 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) { if (result != ISC_R_SUCCESS) goto cleanup_lock; - keytable->mctx = mctx; + keytable->mctx = NULL; + isc_mem_attach(mctx, &keytable->mctx); keytable->active_nodes = 0; keytable->references = 1; keytable->magic = KEYTABLE_MAGIC; @@ -82,7 +83,7 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) { dns_rbt_destroy(&keytable->table); cleanup_keytable: - isc_mem_put(mctx, keytable, sizeof(*keytable)); + isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable)); return (result); } @@ -137,7 +138,8 @@ dns_keytable_detach(dns_keytable_t **keytablep) { isc_rwlock_destroy(&keytable->rwlock); DESTROYLOCK(&keytable->lock); keytable->magic = 0; - isc_mem_put(keytable->mctx, keytable, sizeof(*keytable)); + isc_mem_putanddetach(&keytable->mctx, + keytable, sizeof(*keytable)); } *keytablep = NULL; diff --git a/contrib/bind9/lib/dns/log.c b/contrib/bind9/lib/dns/log.c index d286d103e63c..c4d644e3899f 100644 --- a/contrib/bind9/lib/dns/log.c +++ b/contrib/bind9/lib/dns/log.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ +/* $Id: log.c,v 1.49 2011/10/13 22:48:24 tbox Exp $ */ /*! \file */ diff --git a/contrib/bind9/lib/dns/lookup.c b/contrib/bind9/lib/dns/lookup.c index d5fc7aae4767..9387a955cd3f 100644 --- a/contrib/bind9/lib/dns/lookup.c +++ b/contrib/bind9/lib/dns/lookup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -356,7 +356,7 @@ static void levent_destroy(isc_event_t *event) { dns_lookupevent_t *levent; isc_mem_t *mctx; - + REQUIRE(event->ev_type == DNS_EVENT_LOOKUPDONE); mctx = event->ev_destroy_arg; levent = (dns_lookupevent_t *)event; @@ -393,7 +393,8 @@ dns_lookup_create(isc_mem_t *mctx, dns_name_t *name, dns_rdatatype_t type, lookup = isc_mem_get(mctx, sizeof(*lookup)); if (lookup == NULL) return (ISC_R_NOMEMORY); - lookup->mctx = mctx; + lookup->mctx = NULL; + isc_mem_attach(mctx, &lookup->mctx); lookup->options = options; ievent = isc_event_allocate(mctx, lookup, DNS_EVENT_LOOKUPDONE, @@ -452,7 +453,7 @@ dns_lookup_create(isc_mem_t *mctx, dns_name_t *name, dns_rdatatype_t type, isc_task_detach(&lookup->task); cleanup_lookup: - isc_mem_put(mctx, lookup, sizeof(*lookup)); + isc_mem_putanddetach(&mctx, lookup, sizeof(*lookup)); return (result); } @@ -491,7 +492,7 @@ dns_lookup_destroy(dns_lookup_t **lookupp) { DESTROYLOCK(&lookup->lock); lookup->magic = 0; - isc_mem_put(lookup->mctx, lookup, sizeof(*lookup)); + isc_mem_putanddetach(&lookup->mctx, lookup, sizeof(*lookup)); *lookupp = NULL; } diff --git a/contrib/bind9/lib/dns/master.c b/contrib/bind9/lib/dns/master.c index 1b7460c45673..d0c175876f5c 100644 --- a/contrib/bind9/lib/dns/master.c +++ b/contrib/bind9/lib/dns/master.c @@ -133,6 +133,7 @@ struct dns_loadctx { /* Members specific to the raw format: */ FILE *f; isc_boolean_t first; + dns_masterrawheader_t header; /* Which fixed buffers we are using? */ unsigned int loop_cnt; /*% records per quantum, @@ -597,6 +598,7 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, lctx->f = NULL; lctx->first = ISC_TRUE; + dns_master_initrawheader(&lctx->header); lctx->loop_cnt = (done != NULL) ? 100 : 0; lctx->callbacks = callbacks; @@ -2105,50 +2107,74 @@ load_raw(dns_loadctx_t *lctx) { int target_size = TSIZ; isc_buffer_t target, buf; unsigned char *target_mem = NULL; + dns_masterrawheader_t header; dns_decompress_t dctx; REQUIRE(DNS_LCTX_VALID(lctx)); callbacks = lctx->callbacks; dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); + dns_master_initrawheader(&header); + if (lctx->first) { - dns_masterrawheader_t header; - isc_uint32_t format, version, dumptime; - size_t hdrlen = sizeof(format) + sizeof(version) + - sizeof(dumptime); + unsigned char data[sizeof(header)]; + size_t commonlen = + sizeof(header.format) + sizeof(header.version); + size_t remainder; - INSIST(hdrlen <= sizeof(header)); - isc_buffer_init(&target, &header, sizeof(header)); + INSIST(commonlen <= sizeof(header)); + isc_buffer_init(&target, data, sizeof(data)); - result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL); + result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_stdio_read failed: %s", isc_result_totext(result)); return (result); } - isc_buffer_add(&target, hdrlen); - format = isc_buffer_getuint32(&target); - if (format != dns_masterformat_raw) { + isc_buffer_add(&target, commonlen); + header.format = isc_buffer_getuint32(&target); + if (header.format != dns_masterformat_raw) { (*callbacks->error)(callbacks, "dns_master_load: " "file format mismatch"); return (ISC_R_NOTIMPLEMENTED); } - version = isc_buffer_getuint32(&target); - if (version > DNS_RAWFORMAT_VERSION) { + header.version = isc_buffer_getuint32(&target); + switch (header.version) { + case 0: + remainder = sizeof(header.dumptime); + break; + case DNS_RAWFORMAT_VERSION: + remainder = sizeof(header) - commonlen; + break; + default: (*callbacks->error)(callbacks, "dns_master_load: " "unsupported file format version"); return (ISC_R_NOTIMPLEMENTED); } - /* Empty read: currently, we do not use dumptime */ - dumptime = isc_buffer_getuint32(&target); - POST(dumptime); + result = isc_stdio_read(data + commonlen, 1, remainder, + lctx->f, NULL); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_stdio_read failed: %s", + isc_result_totext(result)); + return (result); + } + + isc_buffer_add(&target, remainder); + header.dumptime = isc_buffer_getuint32(&target); + if (header.version == DNS_RAWFORMAT_VERSION) { + header.flags = isc_buffer_getuint32(&target); + header.sourceserial = isc_buffer_getuint32(&target); + header.lastxfrin = isc_buffer_getuint32(&target); + } lctx->first = ISC_FALSE; + lctx->header = header; } ISC_LIST_INIT(head); @@ -2383,6 +2409,9 @@ load_raw(dns_loadctx_t *lctx) { } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) result = lctx->result; + if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL) + (*callbacks->rawdata)(callbacks->zone, &header); + cleanup: if (rdata != NULL) isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata)); @@ -2969,3 +2998,8 @@ dns_loadctx_cancel(dns_loadctx_t *lctx) { lctx->canceled = ISC_TRUE; UNLOCK(&lctx->lock); } + +void +dns_master_initrawheader(dns_masterrawheader_t *header) { + memset(header, 0, sizeof(dns_masterrawheader_t)); +} diff --git a/contrib/bind9/lib/dns/masterdump.c b/contrib/bind9/lib/dns/masterdump.c index a10e6f2d559e..2717658e691a 100644 --- a/contrib/bind9/lib/dns/masterdump.c +++ b/contrib/bind9/lib/dns/masterdump.c @@ -74,6 +74,7 @@ struct dns_master_style { unsigned int rdata_column; unsigned int line_length; unsigned int tab_width; + unsigned int split_width; }; /*% @@ -108,15 +109,16 @@ dns_master_style_default = { DNS_STYLEFLAG_OMIT_TTL | DNS_STYLEFLAG_TTL | DNS_STYLEFLAG_COMMENT | + DNS_STYLEFLAG_RRCOMMENT | DNS_STYLEFLAG_MULTILINE, - 24, 24, 24, 32, 80, 8 + 24, 24, 24, 32, 80, 8, UINT_MAX }; LIBDNS_EXTERNAL_DATA const dns_master_style_t dns_master_style_full = { DNS_STYLEFLAG_COMMENT | DNS_STYLEFLAG_RESIGN, - 46, 46, 46, 64, 120, 8 + 46, 46, 46, 64, 120, 8, UINT_MAX }; LIBDNS_EXTERNAL_DATA const dns_master_style_t @@ -126,8 +128,9 @@ dns_master_style_explicitttl = { DNS_STYLEFLAG_REL_OWNER | DNS_STYLEFLAG_REL_DATA | DNS_STYLEFLAG_COMMENT | + DNS_STYLEFLAG_RRCOMMENT | DNS_STYLEFLAG_MULTILINE, - 24, 32, 32, 40, 80, 8 + 24, 32, 32, 40, 80, 8, UINT_MAX }; LIBDNS_EXTERNAL_DATA const dns_master_style_t @@ -137,13 +140,13 @@ dns_master_style_cache = { DNS_STYLEFLAG_MULTILINE | DNS_STYLEFLAG_TRUST | DNS_STYLEFLAG_NCACHE, - 24, 32, 32, 40, 80, 8 + 24, 32, 32, 40, 80, 8, UINT_MAX }; LIBDNS_EXTERNAL_DATA const dns_master_style_t dns_master_style_simple = { 0, - 24, 32, 32, 40, 80, 8 + 24, 32, 32, 40, 80, 8, UINT_MAX }; /*% @@ -152,7 +155,7 @@ dns_master_style_simple = { LIBDNS_EXTERNAL_DATA const dns_master_style_t dns_master_style_debug = { DNS_STYLEFLAG_REL_OWNER, - 24, 32, 40, 48, 80, 8 + 24, 32, 40, 48, 80, 8, UINT_MAX }; @@ -185,6 +188,7 @@ struct dns_dumpctx { char *file; char *tmpfile; dns_masterformat_t format; + dns_masterrawheader_t header; isc_result_t (*dumpsets)(isc_mem_t *mctx, dns_name_t *name, dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx, @@ -373,7 +377,7 @@ ncache_summary(dns_rdataset_t *rdataset, isc_boolean_t omit_final_dot, dns_rdataset_current(&rds, &rdata); CHECK(str_totext(" ", target)); CHECK(dns_rdata_tofmttext(&rdata, dns_rootname, - 0, 0, " ", target)); + 0, 0, 0, " ", target)); CHECK(str_totext("\n", target)); } } @@ -533,6 +537,7 @@ rdataset_totext(dns_rdataset_t *rdataset, ctx->style.flags, ctx->style.line_length - ctx->style.rdata_column, + ctx->style.split_width, ctx->linebreak, target)); @@ -1146,21 +1151,53 @@ dns_dumpctx_cancel(dns_dumpctx_t *dctx) { UNLOCK(&dctx->lock); } +static isc_result_t +flushandsync(FILE *f, isc_result_t result, const char *temp) { + isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS); + + if (result == ISC_R_SUCCESS) + result = isc_stdio_flush(f); + if (result != ISC_R_SUCCESS && logit) { + if (temp != NULL) + isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, + "dumping to master file: %s: flush: %s", + temp, isc_result_totext(result)); + else + isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, + "dumping to stream: flush: %s", + isc_result_totext(result)); + logit = ISC_FALSE; + } + + if (result == ISC_R_SUCCESS) + result = isc_stdio_sync(f); + if (result != ISC_R_SUCCESS && logit) { + if (temp != NULL) + isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, + "dumping to master file: %s: fsync: %s", + temp, isc_result_totext(result)); + else + isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, + "dumping to stream: fsync: %s", + isc_result_totext(result)); + } + return (result); +} + static isc_result_t closeandrename(FILE *f, isc_result_t result, const char *temp, const char *file) { isc_result_t tresult; isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS); - if (result == ISC_R_SUCCESS) - result = isc_stdio_sync(f); - if (result != ISC_R_SUCCESS && logit) { - isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR, - "dumping master file: %s: fsync: %s", - temp, isc_result_totext(result)); + result = flushandsync(f, result, temp); + if (result != ISC_R_SUCCESS) logit = ISC_FALSE; - } + tresult = isc_stdio_close(f); if (result == ISC_R_SUCCESS) result = tresult; @@ -1208,7 +1245,8 @@ dump_quantum(isc_task_t *task, isc_event_t *event) { dctx->tmpfile, dctx->file); if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) result = tresult; - } + } else + result = flushandsync(dctx->f, result, NULL); (dctx->done)(dctx->done_arg, result); isc_event_free(&event); dns_dumpctx_detach(&dctx); @@ -1229,7 +1267,7 @@ task_send(dns_dumpctx_t *dctx) { static isc_result_t dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, FILE *f, dns_dumpctx_t **dctxp, - dns_masterformat_t format) + dns_masterformat_t format, dns_masterrawheader_t *header) { dns_dumpctx_t *dctx; isc_result_t result; @@ -1253,6 +1291,10 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, dctx->file = NULL; dctx->tmpfile = NULL; dctx->format = format; + if (header == NULL) + dns_master_initrawheader(&dctx->header); + else + dctx->header = *header; switch (format) { case dns_masterformat_text: @@ -1320,7 +1362,7 @@ dumptostreaminc(dns_dumpctx_t *dctx) { dns_fixedname_t fixname; unsigned int nodes; dns_masterrawheader_t rawheader; - isc_uint32_t now32; + isc_uint32_t rawversion, now32; isc_time_t start; bufmem = isc_mem_get(dctx->mctx, initial_buffer_length); @@ -1355,8 +1397,6 @@ dumptostreaminc(dns_dumpctx_t *dctx) { r.base = (unsigned char *)&rawheader; r.length = sizeof(rawheader); isc_buffer_region(&buffer, &r); - isc_buffer_putuint32(&buffer, dns_masterformat_raw); - isc_buffer_putuint32(&buffer, DNS_RAWFORMAT_VERSION); #if !defined(STDTIME_ON_32BITS) || (STDTIME_ON_32BITS + 0) != 1 /* * We assume isc_stdtime_t is a 32-bit integer, @@ -1375,7 +1415,22 @@ dumptostreaminc(dns_dumpctx_t *dctx) { #else now32 = dctx->now; #endif + rawversion = 1; + if ((dctx->header.flags & DNS_MASTERRAW_COMPAT) != 0) + rawversion = 0; + isc_buffer_putuint32(&buffer, dns_masterformat_raw); + isc_buffer_putuint32(&buffer, rawversion); isc_buffer_putuint32(&buffer, now32); + + if (rawversion == 1) { + isc_buffer_putuint32(&buffer, + dctx->header.flags); + isc_buffer_putuint32(&buffer, + dctx->header.sourceserial); + isc_buffer_putuint32(&buffer, + dctx->header.lastxfrin); + } + INSIST(isc_buffer_usedlength(&buffer) <= sizeof(rawheader)); result = isc_stdio_write(buffer.base, 1, @@ -1494,7 +1549,7 @@ dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db, REQUIRE(done != NULL); result = dumpctx_create(mctx, db, version, style, f, &dctx, - dns_masterformat_text); + dns_masterformat_text, NULL); if (result != ISC_R_SUCCESS) return (result); isc_task_attach(task, &dctx->task); @@ -1521,8 +1576,8 @@ dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db, const dns_master_style_t *style, FILE *f) { - return (dns_master_dumptostream2(mctx, db, version, style, - dns_masterformat_text, f)); + return (dns_master_dumptostream3(mctx, db, version, style, + dns_masterformat_text, NULL, f)); } isc_result_t @@ -1530,17 +1585,31 @@ dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, dns_masterformat_t format, FILE *f) +{ + return (dns_master_dumptostream3(mctx, db, version, style, + format, NULL, f)); +} + +isc_result_t +dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, + dns_masterformat_t format, + dns_masterrawheader_t *header, FILE *f) { dns_dumpctx_t *dctx = NULL; isc_result_t result; - result = dumpctx_create(mctx, db, version, style, f, &dctx, format); + result = dumpctx_create(mctx, db, version, style, f, &dctx, + format, header); if (result != ISC_R_SUCCESS) return (result); result = dumptostreaminc(dctx); INSIST(result != DNS_R_CONTINUE); dns_dumpctx_detach(&dctx); + + result = flushandsync(f, result, NULL); return (result); } @@ -1587,9 +1656,9 @@ dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp) { - return (dns_master_dumpinc2(mctx, db, version, style, filename, task, + return (dns_master_dumpinc3(mctx, db, version, style, filename, task, done, done_arg, dctxp, - dns_masterformat_text)); + dns_masterformat_text, NULL)); } isc_result_t @@ -1597,6 +1666,17 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename, isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp, dns_masterformat_t format) +{ + return (dns_master_dumpinc3(mctx, db, version, style, filename, task, + done, done_arg, dctxp, format, NULL)); +} + +isc_result_t +dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, + dns_dumpctx_t **dctxp, dns_masterformat_t format, + dns_masterrawheader_t *header) { FILE *f = NULL; isc_result_t result; @@ -1612,7 +1692,8 @@ dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) goto cleanup; - result = dumpctx_create(mctx, db, version, style, f, &dctx, format); + result = dumpctx_create(mctx, db, version, style, f, &dctx, + format, header); if (result != ISC_R_SUCCESS) { (void)isc_stdio_close(f); (void)isc_file_remove(tempname); @@ -1648,14 +1729,23 @@ isc_result_t dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename) { - return (dns_master_dump2(mctx, db, version, style, filename, - dns_masterformat_text)); + return (dns_master_dump3(mctx, db, version, style, filename, + dns_masterformat_text, NULL)); } isc_result_t dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, const dns_master_style_t *style, const char *filename, dns_masterformat_t format) +{ + return (dns_master_dump3(mctx, db, version, style, filename, + format, NULL)); +} + +isc_result_t +dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, const char *filename, + dns_masterformat_t format, dns_masterrawheader_t *header) { FILE *f = NULL; isc_result_t result; @@ -1666,7 +1756,8 @@ dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) return (result); - result = dumpctx_create(mctx, db, version, style, f, &dctx, format); + result = dumpctx_create(mctx, db, version, style, f, &dctx, + format, header); if (result != ISC_R_SUCCESS) goto cleanup; @@ -1776,6 +1867,19 @@ dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags, unsigned int type_column, unsigned int rdata_column, unsigned int line_length, unsigned int tab_width, isc_mem_t *mctx) +{ + return (dns_master_stylecreate2(stylep, flags, ttl_column, + class_column, type_column, + rdata_column, line_length, + tab_width, 0xffffffff, mctx)); +} + +isc_result_t +dns_master_stylecreate2(dns_master_style_t **stylep, unsigned int flags, + unsigned int ttl_column, unsigned int class_column, + unsigned int type_column, unsigned int rdata_column, + unsigned int line_length, unsigned int tab_width, + unsigned int split_width, isc_mem_t *mctx) { dns_master_style_t *style; @@ -1791,6 +1895,7 @@ dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags, style->rdata_column = rdata_column; style->line_length = line_length; style->tab_width = tab_width; + style->split_width = split_width; *stylep = style; return (ISC_R_SUCCESS); diff --git a/contrib/bind9/lib/dns/message.c b/contrib/bind9/lib/dns/message.c index d36edbae3b14..53efc5a1beb5 100644 --- a/contrib/bind9/lib/dns/message.c +++ b/contrib/bind9/lib/dns/message.c @@ -732,7 +732,9 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) for (i = 0; i < DNS_SECTION_MAX; i++) ISC_LIST_INIT(m->sections[i]); - m->mctx = mctx; + + m->mctx = NULL; + isc_mem_attach(mctx, &m->mctx); ISC_LIST_INIT(m->scratchpad); ISC_LIST_INIT(m->cleanup); @@ -786,7 +788,7 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) if (m->rdspool != NULL) isc_mempool_destroy(&m->rdspool); m->magic = 0; - isc_mem_put(mctx, m, sizeof(dns_message_t)); + isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t)); return (ISC_R_NOMEMORY); } @@ -815,7 +817,7 @@ dns_message_destroy(dns_message_t **msgp) { isc_mempool_destroy(&msg->namepool); isc_mempool_destroy(&msg->rdspool); msg->magic = 0; - isc_mem_put(msg->mctx, msg, sizeof(dns_message_t)); + isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t)); } static isc_result_t diff --git a/contrib/bind9/lib/dns/nsec.c b/contrib/bind9/lib/dns/nsec.c index 41b5dc3293ea..e446806b4e6a 100644 --- a/contrib/bind9/lib/dns/nsec.c +++ b/contrib/bind9/lib/dns/nsec.c @@ -42,28 +42,61 @@ goto failure; \ } while (0) -static void -set_bit(unsigned char *array, unsigned int index, unsigned int bit) { +void +dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit) { unsigned int shift, mask; - shift = 7 - (index % 8); + shift = 7 - (type % 8); mask = 1 << shift; if (bit != 0) - array[index / 8] |= mask; + array[type / 8] |= mask; else - array[index / 8] &= (~mask & 0xFF); + array[type / 8] &= (~mask & 0xFF); } -static unsigned int -bit_isset(unsigned char *array, unsigned int index) { +isc_boolean_t +dns_nsec_isset(const unsigned char *array, unsigned int type) { unsigned int byte, shift, mask; - byte = array[index / 8]; - shift = 7 - (index % 8); + byte = array[type / 8]; + shift = 7 - (type % 8); mask = 1 << shift; - return ((byte & mask) != 0); + return (ISC_TF(byte & mask)); +} + +unsigned int +dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw, + unsigned int max_type) +{ + unsigned char *start = map; + unsigned int window; + int octet; + + if (raw == NULL) + return (0); + + for (window = 0; window < 256; window++) { + if (window * 256 > max_type) + break; + for (octet = 31; octet >= 0; octet--) + if (*(raw + octet) != 0) + break; + if (octet < 0) { + raw += 32; + continue; + } + *map++ = window; + *map++ = octet + 1; + /* + * Note: potential overlapping move. + */ + memmove(map, raw, octet + 1); + map += octet + 1; + raw += 32; + } + return (map - start); } isc_result_t @@ -74,8 +107,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, isc_result_t result; dns_rdataset_t rdataset; isc_region_t r; - unsigned int i, window; - int octet; + unsigned int i; unsigned char *nsec_bits, *bm; unsigned int max_type; @@ -91,8 +123,8 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, */ bm = r.base + r.length + 512; nsec_bits = r.base + r.length; - set_bit(bm, dns_rdatatype_rrsig, 1); - set_bit(bm, dns_rdatatype_nsec, 1); + dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1); + dns_nsec_setbit(bm, dns_rdatatype_nsec, 1); max_type = dns_rdatatype_nsec; dns_rdataset_init(&rdataset); rdsiter = NULL; @@ -109,7 +141,7 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, rdataset.type != dns_rdatatype_rrsig) { if (rdataset.type > max_type) max_type = rdataset.type; - set_bit(bm, rdataset.type, 1); + dns_nsec_setbit(bm, rdataset.type, 1); } dns_rdataset_disassociate(&rdataset); } @@ -117,12 +149,12 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, /* * At zone cuts, deny the existence of glue in the parent zone. */ - if (bit_isset(bm, dns_rdatatype_ns) && - ! bit_isset(bm, dns_rdatatype_soa)) { + if (dns_nsec_isset(bm, dns_rdatatype_ns) && + ! dns_nsec_isset(bm, dns_rdatatype_soa)) { for (i = 0; i <= max_type; i++) { - if (bit_isset(bm, i) && + if (dns_nsec_isset(bm, i) && ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i)) - set_bit(bm, i, 0); + dns_nsec_setbit(bm, i, 0); } } @@ -130,22 +162,8 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_NOMORE) return (result); - for (window = 0; window < 256; window++) { - if (window * 256 > max_type) - break; - for (octet = 31; octet >= 0; octet--) - if (bm[window * 32 + octet] != 0) - break; - if (octet < 0) - continue; - nsec_bits[0] = window; - nsec_bits[1] = octet + 1; - /* - * Note: potential overlapping move. - */ - memmove(&nsec_bits[2], &bm[window * 32], octet + 1); - nsec_bits += 3 + octet; - } + nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type); + r.length = nsec_bits - r.base; INSIST(r.length <= DNS_NSEC_BUFFERSIZE); dns_rdata_fromregion(rdata, @@ -156,7 +174,6 @@ dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, return (ISC_R_SUCCESS); } - isc_result_t dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, dns_name_t *target, dns_ttl_t ttl) @@ -217,8 +234,8 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) { if ((window + 1) * 256 <= type) continue; if (type < (window * 256) + len * 8) - present = ISC_TF(bit_isset(&nsecstruct.typebits[i], - type % 256)); + present = ISC_TF(dns_nsec_isset(&nsecstruct.typebits[i], + type % 256)); break; } dns_rdata_freestruct(&nsecstruct); @@ -246,10 +263,8 @@ dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, 0, 0, &rdataset, NULL); dns_db_detachnode(db, &node); - if (result == ISC_R_NOTFOUND) { + if (result == ISC_R_NOTFOUND) *answer = ISC_FALSE; - return (ISC_R_SUCCESS); - } if (result != ISC_R_SUCCESS) return (result); for (result = dns_rdataset_first(&rdataset); diff --git a/contrib/bind9/lib/dns/nsec3.c b/contrib/bind9/lib/dns/nsec3.c index 7ec6b4cb881d..935f515d23ed 100644 --- a/contrib/bind9/lib/dns/nsec3.c +++ b/contrib/bind9/lib/dns/nsec3.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -50,32 +51,9 @@ #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0) +#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0) #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) -static void -set_bit(unsigned char *array, unsigned int index, unsigned int bit) { - unsigned int shift, mask; - - shift = 7 - (index % 8); - mask = 1 << shift; - - if (bit != 0) - array[index / 8] |= mask; - else - array[index / 8] &= (~mask & 0xFF); -} - -static unsigned int -bit_isset(unsigned char *array, unsigned int index) { - unsigned int byte, shift, mask; - - byte = array[index / 8]; - shift = 7 - (index % 8); - mask = 1 << shift; - - return ((byte & mask) != 0); -} - isc_result_t dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, unsigned int hashalg, @@ -87,8 +65,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, isc_result_t result; dns_rdataset_t rdataset; isc_region_t r; - unsigned int i, window; - int octet; + unsigned int i; isc_boolean_t found; isc_boolean_t found_ns; isc_boolean_t need_rrsig; @@ -156,7 +133,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, rdataset.type != dns_rdatatype_rrsig) { if (rdataset.type > max_type) max_type = rdataset.type; - set_bit(bm, rdataset.type, 1); + dns_nsec_setbit(bm, rdataset.type, 1); /* * Work out if we need to set the RRSIG bit for * this node. We set the RRSIG bit if either of @@ -179,18 +156,18 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, if ((found && !found_ns) || need_rrsig) { if (dns_rdatatype_rrsig > max_type) max_type = dns_rdatatype_rrsig; - set_bit(bm, dns_rdatatype_rrsig, 1); + dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1); } /* * At zone cuts, deny the existence of glue in the parent zone. */ - if (bit_isset(bm, dns_rdatatype_ns) && - ! bit_isset(bm, dns_rdatatype_soa)) { + if (dns_nsec_isset(bm, dns_rdatatype_ns) && + ! dns_nsec_isset(bm, dns_rdatatype_soa)) { for (i = 0; i <= max_type; i++) { - if (bit_isset(bm, i) && + if (dns_nsec_isset(bm, i) && ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i)) - set_bit(bm, i, 0); + dns_nsec_setbit(bm, i, 0); } } @@ -199,22 +176,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, return (result); collapse_bitmap: - for (window = 0; window < 256; window++) { - if (window * 256 > max_type) - break; - for (octet = 31; octet >= 0; octet--) - if (bm[window * 32 + octet] != 0) - break; - if (octet < 0) - continue; - nsec_bits[0] = window; - nsec_bits[1] = octet + 1; - /* - * Note: potentially overlapping move. - */ - memmove(&nsec_bits[2], &bm[window * 32], octet + 1); - nsec_bits += 3 + octet; - } + nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type); r.length = nsec_bits - r.base; INSIST(r.length <= DNS_NSEC3_BUFFERSIZE); dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r); @@ -249,8 +211,8 @@ dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) { if ((window + 1) * 256 <= type) continue; if (type < (window * 256) + len * 8) - present = ISC_TF(bit_isset(&nsec3.typebits[i], - type % 256)); + present = ISC_TF(dns_nsec_isset(&nsec3.typebits[i], + type % 256)); break; } dns_rdata_freestruct(&nsec3); @@ -1054,7 +1016,8 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, #ifdef BIND9 isc_result_t dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, - dns_zone_t *zone, dns_diff_t *diff) + dns_zone_t *zone, isc_boolean_t nonsec, + dns_diff_t *diff) { dns_dbnode_t *node = NULL; dns_difftuple_t *tuple = NULL; @@ -1098,7 +1061,9 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3param_toprivate(&rdata, &private, privatetype, buf, sizeof(buf)); - buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; + buf[2] = DNS_NSEC3FLAG_REMOVE; + if (nonsec) + buf[2] |= DNS_NSEC3FLAG_NONSEC; CHECK(rr_exists(db, ver, origin, &private, &flag)); @@ -1129,6 +1094,7 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { + dns_rdata_reset(&rdata); dns_rdataset_current(&rdataset, &rdata); INSIST(rdata.length <= sizeof(buf)); memcpy(buf, rdata.data, rdata.length); @@ -1138,10 +1104,9 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, * <0(1), hash(1), flags(1), iterations(2), saltlen(1)> */ if (rdata.length < 6 || buf[0] != 0 || - buf[2] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) { - dns_rdata_reset(&rdata); + (buf[2] & DNS_NSEC3FLAG_REMOVE) != 0 || + (nonsec && (buf[2] & DNS_NSEC3FLAG_NONSEC) != 0)) continue; - } CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin, 0, &rdata, &tuple)); @@ -1149,7 +1114,9 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, INSIST(tuple == NULL); rdata.data = buf; - buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; + buf[2] = DNS_NSEC3FLAG_REMOVE; + if (nonsec) + buf[2] |= DNS_NSEC3FLAG_NONSEC; CHECK(rr_exists(db, ver, origin, &rdata, &flag)); @@ -1159,7 +1126,6 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, CHECK(do_one_tuple(&tuple, db, ver, diff)); INSIST(tuple == NULL); } - dns_rdata_reset(&rdata); } if (result != ISC_R_NOMORE) goto failure; diff --git a/contrib/bind9/lib/dns/openssldh_link.c b/contrib/bind9/lib/dns/openssldh_link.c index 9fe9bb52524f..36b8a412a3ee 100644 --- a/contrib/bind9/lib/dns/openssldh_link.c +++ b/contrib/bind9/lib/dns/openssldh_link.c @@ -634,6 +634,7 @@ static dst_func_t openssldh_functions = { NULL, /*%< adddata */ NULL, /*%< openssldh_sign */ NULL, /*%< openssldh_verify */ + NULL, /*%< openssldh_verify2 */ openssldh_computesecret, openssldh_compare, openssldh_paramcompare, diff --git a/contrib/bind9/lib/dns/openssldsa_link.c b/contrib/bind9/lib/dns/openssldsa_link.c index 66d47bb604a4..8bea1c09e05e 100644 --- a/contrib/bind9/lib/dns/openssldsa_link.c +++ b/contrib/bind9/lib/dns/openssldsa_link.c @@ -624,6 +624,7 @@ static dst_func_t openssldsa_functions = { openssldsa_adddata, openssldsa_sign, openssldsa_verify, + NULL, /*%< verify2 */ NULL, /*%< computesecret */ openssldsa_compare, NULL, /*%< paramcompare */ diff --git a/contrib/bind9/lib/dns/opensslecdsa_link.c b/contrib/bind9/lib/dns/opensslecdsa_link.c index 1cf30f839ab9..c3f5061b7546 100644 --- a/contrib/bind9/lib/dns/opensslecdsa_link.c +++ b/contrib/bind9/lib/dns/opensslecdsa_link.c @@ -572,6 +572,7 @@ static dst_func_t opensslecdsa_functions = { opensslecdsa_adddata, opensslecdsa_sign, opensslecdsa_verify, + NULL, /*%< verify2 */ NULL, /*%< computesecret */ opensslecdsa_compare, NULL, /*%< paramcompare */ diff --git a/contrib/bind9/lib/dns/opensslgost_link.c b/contrib/bind9/lib/dns/opensslgost_link.c index 098e31243df4..1ce4405eb21d 100644 --- a/contrib/bind9/lib/dns/opensslgost_link.c +++ b/contrib/bind9/lib/dns/opensslgost_link.c @@ -373,6 +373,7 @@ static dst_func_t opensslgost_functions = { opensslgost_adddata, opensslgost_sign, opensslgost_verify, + NULL, /*%< verify2 */ NULL, /*%< computesecret */ opensslgost_compare, NULL, /*%< paramcompare */ diff --git a/contrib/bind9/lib/dns/opensslrsa_link.c b/contrib/bind9/lib/dns/opensslrsa_link.c index 2430f2429135..fa7412cbddbd 100644 --- a/contrib/bind9/lib/dns/opensslrsa_link.c +++ b/contrib/bind9/lib/dns/opensslrsa_link.c @@ -55,6 +55,13 @@ #include #endif +/* + * Limit the size of public exponents. + */ +#ifndef RSA_MAX_PUBEXP_BITS +#define RSA_MAX_PUBEXP_BITS 35 +#endif + /* * We don't use configure for windows so enforce the OpenSSL version * here. Unlike with configure we don't support overriding this test. @@ -503,12 +510,14 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { } static isc_result_t -opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { +opensslrsa_verify2(dst_context_t *dctx, int maxbits, const isc_region_t *sig) { dst_key_t *key = dctx->key; int status = 0; #if USE_EVP EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; EVP_PKEY *pkey = key->keydata.pkey; + RSA *rsa; + int bits; #else /* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */ unsigned char digest[ISC_SHA512_DIGESTLENGTH]; @@ -528,6 +537,14 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { dctx->key->key_alg == DST_ALG_RSASHA512); #if USE_EVP + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa == NULL) + return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + bits = BN_num_bits(rsa->e); + RSA_free(rsa); + if (bits > maxbits && maxbits != 0) + return (DST_R_VERIFYFAILURE); + status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey); switch (status) { case 1: @@ -540,6 +557,9 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { DST_R_VERIFYFAILURE)); } #else + if (BN_num_bits(rsa->e) > maxbits && maxbits != 0) + return (DST_R_VERIFYFAILURE); + switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: { @@ -652,6 +672,11 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { #endif } +static isc_result_t +opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { + return (opensslrsa_verify2(dctx, 0, sig)); +} + static isc_boolean_t opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) { int status; @@ -764,7 +789,7 @@ opensslrsa_generate(dst_key_t *key, int exp, void (*callback)(int)) { BN_set_bit(e, 0); BN_set_bit(e, 16); } else { - /* F5 0x100000001 */ + /* (phased-out) F5 0x100000001 */ BN_set_bit(e, 0); BN_set_bit(e, 32); } @@ -1219,6 +1244,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); + if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) + DST_RET(ISC_R_RANGE); if (pubrsa != NULL) RSA_free(pubrsa); key->key_size = EVP_PKEY_bits(pkey); @@ -1301,6 +1328,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); + if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) + DST_RET(ISC_R_RANGE); key->key_size = BN_num_bits(rsa->n); if (pubrsa != NULL) RSA_free(pubrsa); @@ -1319,7 +1348,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { RSA_free(rsa); if (pubrsa != NULL) RSA_free(pubrsa); - opensslrsa_destroy(key); + key->keydata.generic = NULL; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); @@ -1374,6 +1403,8 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); + if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) + DST_RET(ISC_R_RANGE); if (pubrsa != NULL) RSA_free(pubrsa); key->key_size = EVP_PKEY_bits(pkey); @@ -1409,6 +1440,7 @@ static dst_func_t opensslrsa_functions = { opensslrsa_adddata, opensslrsa_sign, opensslrsa_verify, + opensslrsa_verify2, NULL, /*%< computesecret */ opensslrsa_compare, NULL, /*%< paramcompare */ diff --git a/contrib/bind9/lib/dns/private.c b/contrib/bind9/lib/dns/private.c index b0cb96f5ee04..6521279f2d9b 100644 --- a/contrib/bind9/lib/dns/private.c +++ b/contrib/bind9/lib/dns/private.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -44,6 +44,7 @@ #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0) +#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0) #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0) #define CHECK(x) do { \ @@ -149,7 +150,7 @@ dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, } /* - * Look to see if we also need to be creating a NSEC3 chains. + * Look to see if we also need to be creating a NSEC3 chain. */ if (dns_rdataset_isassociated(&nsecset)) { if (build_nsec != NULL) @@ -293,3 +294,78 @@ dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, dns_db_detachnode(db, &node); return (result); } + +isc_result_t +dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) { + isc_result_t result; + + if (private->length < 5) + return (ISC_R_NOTFOUND); + + if (private->data[0] == 0) { + unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE]; + unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3param_t nsec3param; + isc_boolean_t remove, init, nonsec; + isc_buffer_t b; + + if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf, + sizeof(nsec3buf))) + CHECK(ISC_R_FAILURE); + + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); + + remove = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0); + init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0); + nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0); + + nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE| + DNS_NSEC3FLAG_REMOVE| + DNS_NSEC3FLAG_INITIAL| + DNS_NSEC3FLAG_NONSEC); + + if (init) + isc_buffer_putstr(buf, "Pending NSEC3 chain "); + else if (remove) + isc_buffer_putstr(buf, "Removing NSEC3 chain "); + else + isc_buffer_putstr(buf, "Creating NSEC3 chain "); + + dns_rdata_reset(&rdata); + isc_buffer_init(&b, newbuf, sizeof(newbuf)); + CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in, + dns_rdatatype_nsec3param, + &nsec3param, &b)); + + CHECK(dns_rdata_totext(&rdata, NULL, buf)); + + if (remove && !nonsec) + isc_buffer_putstr(buf, " / creating NSEC chain"); + } else if (private->length == 5) { + unsigned char alg = private->data[0]; + dns_keytag_t keyid = (private->data[2] | private->data[1] << 8); + char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE]; + isc_boolean_t remove = ISC_TF(private->data[3] != 0); + isc_boolean_t complete = ISC_TF(private->data[4] != 0); + + if (remove && complete) + isc_buffer_putstr(buf, "Done removing signatures for "); + else if (remove) + isc_buffer_putstr(buf, "Removing signatures for "); + else if (complete) + isc_buffer_putstr(buf, "Done signing with "); + else + isc_buffer_putstr(buf, "Signing with "); + + dns_secalg_format(alg, algbuf, sizeof(algbuf)); + sprintf(keybuf, "key %d/%s", keyid, algbuf); + isc_buffer_putstr(buf, keybuf); + } else + return (ISC_R_NOTFOUND); + + isc_buffer_putuint8(buf, 0); + result = ISC_R_SUCCESS; + failure: + return (result); +} diff --git a/contrib/bind9/lib/dns/rbt.c b/contrib/bind9/lib/dns/rbt.c index eb95d14fbc22..7381b4a325b3 100644 --- a/contrib/bind9/lib/dns/rbt.c +++ b/contrib/bind9/lib/dns/rbt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -248,7 +248,8 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *), if (rbt == NULL) return (ISC_R_NOMEMORY); - rbt->mctx = mctx; + rbt->mctx = NULL; + isc_mem_attach(mctx, &rbt->mctx); rbt->data_deleter = deleter; rbt->deleter_arg = deleter_arg; rbt->root = NULL; @@ -259,7 +260,7 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *), #ifdef DNS_RBT_USEHASH result = inithash(rbt); if (result != ISC_R_SUCCESS) { - isc_mem_put(mctx, rbt, sizeof(*rbt)); + isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt)); return (result); } #endif @@ -299,7 +300,7 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) { rbt->magic = 0; - isc_mem_put(rbt->mctx, rbt, sizeof(*rbt)); + isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt)); *rbtp = NULL; return (ISC_R_SUCCESS); } diff --git a/contrib/bind9/lib/dns/rbtdb.c b/contrib/bind9/lib/dns/rbtdb.c index f6f96ab9315a..bff52b87ef9d 100644 --- a/contrib/bind9/lib/dns/rbtdb.c +++ b/contrib/bind9/lib/dns/rbtdb.c @@ -4553,7 +4553,8 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep, */ #ifdef BIND9 static isc_result_t -rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) { +rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) +{ dns_rbtdb_t *rbtdb; isc_result_t result; @@ -7464,8 +7465,10 @@ static dns_dbmethods_t zone_methods = { rpz_findips, #else NULL, - NULL + NULL, #endif + NULL, + NULL }; static dns_dbmethods_t cache_methods = { @@ -7506,6 +7509,8 @@ static dns_dbmethods_t cache_methods = { isdnssec, getrrsetstats, NULL, + NULL, + NULL, NULL }; diff --git a/contrib/bind9/lib/dns/rdata.c b/contrib/bind9/lib/dns/rdata.c index 3865f42fe086..a83dab462ce5 100644 --- a/contrib/bind9/lib/dns/rdata.c +++ b/contrib/bind9/lib/dns/rdata.c @@ -15,6 +15,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/* $Id$ */ + /*! \file */ #include @@ -878,7 +880,8 @@ dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) isc_result_t dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, unsigned int flags, unsigned int width, - const char *linebreak, isc_buffer_t *target) + unsigned int split_width, const char *linebreak, + isc_buffer_t *target) { dns_rdata_textctx_t tctx; @@ -889,11 +892,16 @@ dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, */ tctx.origin = origin; tctx.flags = flags; - if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) { + if (split_width == 0xffffffff) tctx.width = width; + else + tctx.width = split_width; + + if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) tctx.linebreak = linebreak; - } else { - tctx.width = 60; /* Used for hex word length only. */ + else { + if (split_width == 0xffffffff) + tctx.width = 60; /* Used for hex word length only. */ tctx.linebreak = " "; } return (rdata_totext(rdata, &tctx, target)); @@ -1409,7 +1417,8 @@ multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { if (n > tregion.length) return (ISC_R_NOSPACE); - memcpy(tregion.base, sregion.base, n); + if (tregion.base != sregion.base) + memcpy(tregion.base, sregion.base, n); isc_buffer_forward(source, n); isc_buffer_add(target, n); isc_buffer_activeregion(source, &sregion); diff --git a/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c b/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c index 0046ed052ac4..3f91f91c009a 100644 --- a/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c +++ b/contrib/bind9/lib/dns/rdata/any_255/tsig_250.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -202,8 +202,11 @@ totext_any_tsig(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sigr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sigr, 60, "", target)); + else + RETERR(isc_base64_totext(&sigr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ) ", target)); else @@ -236,7 +239,10 @@ totext_any_tsig(ARGS_TOTEXT) { /* * Other. */ - return (isc_base64_totext(&sr, 60, " ", target)); + if (tctx->width == 0) /* No splitting */ + return (isc_base64_totext(&sr, 60, "", target)); + else + return (isc_base64_totext(&sr, 60, " ", target)); } static inline isc_result_t diff --git a/contrib/bind9/lib/dns/rdata/generic/cert_37.c b/contrib/bind9/lib/dns/rdata/generic/cert_37.c index 2a447a67a268..a03290a60a02 100644 --- a/contrib/bind9/lib/dns/rdata/generic/cert_37.c +++ b/contrib/bind9/lib/dns/rdata/generic/cert_37.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -109,8 +109,11 @@ totext_cert(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); return (ISC_R_SUCCESS); diff --git a/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c b/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c index 97f37f7d9ed4..5751ad894527 100644 --- a/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c +++ b/contrib/bind9/lib/dns/rdata/generic/dlv_32769.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007, 2009, 2010, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2006, 2007, 2009-2013 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -137,7 +137,11 @@ totext_dlv(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); return (ISC_R_SUCCESS); diff --git a/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c b/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c index b7eeb34f2b02..688e7ac5e18f 100644 --- a/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c +++ b/contrib/bind9/lib/dns/rdata/generic/dnskey_48.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -76,7 +76,8 @@ totext_dnskey(ARGS_TOTEXT) { char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; - char namebuf[DNS_NAME_FORMATSIZE]; + char algbuf[DNS_NAME_FORMATSIZE]; + const char *keyinfo; REQUIRE(rdata->type == 48); REQUIRE(rdata->length != 0); @@ -89,6 +90,13 @@ totext_dnskey(ARGS_TOTEXT) { sprintf(buf, "%u", flags); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); + if ((flags & DNS_KEYFLAG_KSK) != 0) { + if (flags & DNS_KEYFLAG_REVOKE) + keyinfo = "revoked KSK"; + else + keyinfo = "KSK"; + } else + keyinfo = "ZSK"; /* protocol */ sprintf(buf, "%u", sr.base[0]); @@ -106,23 +114,28 @@ totext_dnskey(ARGS_TOTEXT) { if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 && + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 && algorithm == DNS_KEYALG_PRIVATEDNS) { dns_name_t name; dns_name_init(&name, NULL); dns_name_fromregion(&name, &sr); - dns_name_format(&name, namebuf, sizeof(namebuf)); - } else - namebuf[0] = 0; + dns_name_format(&name, algbuf, sizeof(algbuf)); + } else { + dns_secalg_format((dns_secalg_t) algorithm, algbuf, + sizeof(algbuf)); + } /* key */ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 0, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) RETERR(str_totext(tctx->linebreak, target)); else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ", target)); @@ -130,18 +143,17 @@ totext_dnskey(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(")", target)); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) { + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; - RETERR(str_totext(" ; key id = ", target)); + RETERR(str_totext(" ; ", target)); + RETERR(str_totext(keyinfo, target)); + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(algbuf, target)); + RETERR(str_totext("; key id = ", target)); dns_rdata_toregion(rdata, &tmpr); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); - if (algorithm == DNS_KEYALG_PRIVATEDNS) { - RETERR(str_totext(tctx->linebreak, target)); - RETERR(str_totext("; alg = ", target)); - RETERR(str_totext(namebuf, target)); - } } return (ISC_R_SUCCESS); } diff --git a/contrib/bind9/lib/dns/rdata/generic/ds_43.c b/contrib/bind9/lib/dns/rdata/generic/ds_43.c index 20bac85ccac0..dd47c8d5e83e 100644 --- a/contrib/bind9/lib/dns/rdata/generic/ds_43.c +++ b/contrib/bind9/lib/dns/rdata/generic/ds_43.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -137,7 +137,11 @@ totext_ds(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); return (ISC_R_SUCCESS); diff --git a/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c b/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c index 7e65e655d290..1d2508c42e25 100644 --- a/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c +++ b/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c @@ -190,8 +190,11 @@ totext_ipseckey(ARGS_TOTEXT) { */ if (region.length > 0U) { RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(®ion, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(®ion, 60, "", target)); + else + RETERR(isc_base64_totext(®ion, tctx->width - 2, + tctx->linebreak, target)); } if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) diff --git a/contrib/bind9/lib/dns/rdata/generic/key_25.c b/contrib/bind9/lib/dns/rdata/generic/key_25.c index 26ca9a9b82da..1d0ba83a9b31 100644 --- a/contrib/bind9/lib/dns/rdata/generic/key_25.c +++ b/contrib/bind9/lib/dns/rdata/generic/key_25.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -106,7 +106,7 @@ totext_key(ARGS_TOTEXT) { if ((flags & 0xc000) == 0xc000) return (ISC_R_SUCCESS); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0 && + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 && algorithm == DNS_KEYALG_PRIVATEDNS) { dns_name_t name; dns_name_init(&name, NULL); @@ -119,10 +119,13 @@ totext_key(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) RETERR(str_totext(tctx->linebreak, target)); else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ", target)); @@ -130,7 +133,7 @@ totext_key(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(")", target)); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) { + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; RETERR(str_totext(" ; key id = ", target)); diff --git a/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c b/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c index 317e1a87246a..a2d83f456e49 100644 --- a/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c +++ b/contrib/bind9/lib/dns/rdata/generic/keydata_65533.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -89,6 +89,8 @@ totext_keydata(ARGS_TOTEXT) { unsigned int flags; unsigned char algorithm; unsigned long when; + char algbuf[DNS_NAME_FORMATSIZE]; + const char *keyinfo; REQUIRE(rdata->type == 65533); REQUIRE(rdata->length != 0); @@ -119,6 +121,13 @@ totext_keydata(ARGS_TOTEXT) { sprintf(buf, "%u", flags); RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); + if ((flags & DNS_KEYFLAG_KSK) != 0) { + if (flags & DNS_KEYFLAG_REVOKE) + keyinfo = "revoked KSK"; + else + keyinfo = "KSK"; + } else + keyinfo = "ZSK"; /* protocol */ sprintf(buf, "%u", sr.base[0]); @@ -140,10 +149,13 @@ totext_keydata(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) RETERR(str_totext(tctx->linebreak, target)); else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ", target)); @@ -151,10 +163,16 @@ totext_keydata(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(")", target)); - if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) { + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; - RETERR(str_totext(" ; key id = ", target)); + RETERR(str_totext(" ; ", target)); + RETERR(str_totext(keyinfo, target)); + dns_secalg_format((dns_secalg_t) algorithm, algbuf, + sizeof(algbuf)); + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(algbuf, target)); + RETERR(str_totext("; key id = ", target)); dns_rdata_toregion(rdata, &tmpr); /* Skip over refresh, addhd, and removehd */ isc_region_consume(&tmpr, 12); diff --git a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c b/contrib/bind9/lib/dns/rdata/generic/naptr_35.c similarity index 92% rename from contrib/bind9/lib/dns/rdata/in_1/naptr_35.c rename to contrib/bind9/lib/dns/rdata/generic/naptr_35.c index e5df80b0c7b7..83439a59293e 100644 --- a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c +++ b/contrib/bind9/lib/dns/rdata/generic/naptr_35.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -21,8 +21,8 @@ /* RFC2915 */ -#ifndef RDATA_IN_1_NAPTR_35_C -#define RDATA_IN_1_NAPTR_35_C +#ifndef RDATA_GENERIC_NAPTR_35_C +#define RDATA_GENERIC_NAPTR_35_C #define RRTYPE_NAPTR_ATTRIBUTES (0) @@ -121,14 +121,13 @@ txt_valid_regex(const unsigned char *txt) { } static inline isc_result_t -fromtext_in_naptr(ARGS_FROMTEXT) { +fromtext_naptr(ARGS_FROMTEXT) { isc_token_t token; dns_name_t name; isc_buffer_t buffer; unsigned char *regex; REQUIRE(type == 35); - REQUIRE(rdclass == 1); UNUSED(type); UNUSED(rdclass); @@ -188,7 +187,7 @@ fromtext_in_naptr(ARGS_FROMTEXT) { } static inline isc_result_t -totext_in_naptr(ARGS_TOTEXT) { +totext_naptr(ARGS_TOTEXT) { isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -197,7 +196,6 @@ totext_in_naptr(ARGS_TOTEXT) { unsigned short num; REQUIRE(rdata->type == 35); - REQUIRE(rdata->rdclass == 1); REQUIRE(rdata->length != 0); dns_name_init(&name, NULL); @@ -250,13 +248,12 @@ totext_in_naptr(ARGS_TOTEXT) { } static inline isc_result_t -fromwire_in_naptr(ARGS_FROMWIRE) { +fromwire_naptr(ARGS_FROMWIRE) { dns_name_t name; isc_region_t sr; unsigned char *regex; REQUIRE(type == 35); - REQUIRE(rdclass == 1); UNUSED(type); UNUSED(rdclass); @@ -298,13 +295,12 @@ fromwire_in_naptr(ARGS_FROMWIRE) { } static inline isc_result_t -towire_in_naptr(ARGS_TOWIRE) { +towire_naptr(ARGS_TOWIRE) { dns_name_t name; dns_offsets_t offsets; isc_region_t sr; REQUIRE(rdata->type == 35); - REQUIRE(rdata->rdclass == 1); REQUIRE(rdata->length != 0); dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); @@ -342,7 +338,7 @@ towire_in_naptr(ARGS_TOWIRE) { } static inline int -compare_in_naptr(ARGS_COMPARE) { +compare_naptr(ARGS_COMPARE) { dns_name_t name1; dns_name_t name2; isc_region_t region1; @@ -352,7 +348,6 @@ compare_in_naptr(ARGS_COMPARE) { REQUIRE(rdata1->type == rdata2->type); REQUIRE(rdata1->rdclass == rdata2->rdclass); REQUIRE(rdata1->type == 35); - REQUIRE(rdata1->rdclass == 1); REQUIRE(rdata1->length != 0); REQUIRE(rdata2->length != 0); @@ -411,12 +406,11 @@ compare_in_naptr(ARGS_COMPARE) { } static inline isc_result_t -fromstruct_in_naptr(ARGS_FROMSTRUCT) { - dns_rdata_in_naptr_t *naptr = source; +fromstruct_naptr(ARGS_FROMSTRUCT) { + dns_rdata_naptr_t *naptr = source; isc_region_t region; REQUIRE(type == 35); - REQUIRE(rdclass == 1); REQUIRE(source != NULL); REQUIRE(naptr->common.rdtype == type); REQUIRE(naptr->common.rdclass == rdclass); @@ -440,14 +434,13 @@ fromstruct_in_naptr(ARGS_FROMSTRUCT) { } static inline isc_result_t -tostruct_in_naptr(ARGS_TOSTRUCT) { - dns_rdata_in_naptr_t *naptr = target; +tostruct_naptr(ARGS_TOSTRUCT) { + dns_rdata_naptr_t *naptr = target; isc_region_t r; isc_result_t result; dns_name_t name; REQUIRE(rdata->type == 35); - REQUIRE(rdata->rdclass == 1); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); @@ -511,11 +504,10 @@ tostruct_in_naptr(ARGS_TOSTRUCT) { } static inline void -freestruct_in_naptr(ARGS_FREESTRUCT) { - dns_rdata_in_naptr_t *naptr = source; +freestruct_naptr(ARGS_FREESTRUCT) { + dns_rdata_naptr_t *naptr = source; REQUIRE(source != NULL); - REQUIRE(naptr->common.rdclass == 1); REQUIRE(naptr->common.rdtype == 35); if (naptr->mctx == NULL) @@ -532,7 +524,7 @@ freestruct_in_naptr(ARGS_FREESTRUCT) { } static inline isc_result_t -additionaldata_in_naptr(ARGS_ADDLDATA) { +additionaldata_naptr(ARGS_ADDLDATA) { dns_name_t name; dns_offsets_t offsets; isc_region_t sr; @@ -541,7 +533,6 @@ additionaldata_in_naptr(ARGS_ADDLDATA) { char *cp; REQUIRE(rdata->type == 35); - REQUIRE(rdata->rdclass == 1); /* * Order, preference. @@ -590,14 +581,13 @@ additionaldata_in_naptr(ARGS_ADDLDATA) { } static inline isc_result_t -digest_in_naptr(ARGS_DIGEST) { +digest_naptr(ARGS_DIGEST) { isc_region_t r1, r2; unsigned int length, n; isc_result_t result; dns_name_t name; REQUIRE(rdata->type == 35); - REQUIRE(rdata->rdclass == 1); dns_rdata_toregion(rdata, &r1); r2 = r1; @@ -649,10 +639,9 @@ digest_in_naptr(ARGS_DIGEST) { } static inline isc_boolean_t -checkowner_in_naptr(ARGS_CHECKOWNER) { +checkowner_naptr(ARGS_CHECKOWNER) { REQUIRE(type == 35); - REQUIRE(rdclass == 1); UNUSED(name); UNUSED(type); @@ -663,10 +652,9 @@ checkowner_in_naptr(ARGS_CHECKOWNER) { } static inline isc_boolean_t -checknames_in_naptr(ARGS_CHECKNAMES) { +checknames_naptr(ARGS_CHECKNAMES) { REQUIRE(rdata->type == 35); - REQUIRE(rdata->rdclass == 1); UNUSED(rdata); UNUSED(owner); @@ -676,8 +664,8 @@ checknames_in_naptr(ARGS_CHECKNAMES) { } static inline int -casecompare_in_naptr(ARGS_COMPARE) { - return (compare_in_naptr(rdata1, rdata2)); +casecompare_naptr(ARGS_COMPARE) { + return (compare_naptr(rdata1, rdata2)); } -#endif /* RDATA_IN_1_NAPTR_35_C */ +#endif /* RDATA_GENERIC_NAPTR_35_C */ diff --git a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.h b/contrib/bind9/lib/dns/rdata/generic/naptr_35.h similarity index 82% rename from contrib/bind9/lib/dns/rdata/in_1/naptr_35.h rename to contrib/bind9/lib/dns/rdata/generic/naptr_35.h index 04e8d691a582..f88c52336f82 100644 --- a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.h +++ b/contrib/bind9/lib/dns/rdata/generic/naptr_35.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,15 +15,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#ifndef IN_1_NAPTR_35_H -#define IN_1_NAPTR_35_H 1 +#ifndef GENERIC_NAPTR_35_H +#define GENERIC_NAPTR_35_H 1 /* $Id$ */ /*! * \brief Per RFC2915 */ -typedef struct dns_rdata_in_naptr { +typedef struct dns_rdata_naptr { dns_rdatacommon_t common; isc_mem_t *mctx; isc_uint16_t order; @@ -35,6 +35,6 @@ typedef struct dns_rdata_in_naptr { char *regexp; isc_uint8_t regexp_len; dns_name_t replacement; -} dns_rdata_in_naptr_t; +} dns_rdata_naptr_t; -#endif /* IN_1_NAPTR_35_H */ +#endif /* GENERIC_NAPTR_35_H */ diff --git a/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c b/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c index 96b2dc8f5feb..19b94efa06dc 100644 --- a/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c +++ b/contrib/bind9/lib/dns/rdata/generic/nsec3_50.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -142,32 +142,32 @@ totext_nsec3(ARGS_TOTEXT) { unsigned char flags; char buf[sizeof("65535 ")]; isc_uint32_t iterations; + isc_boolean_t first; REQUIRE(rdata->type == 50); REQUIRE(rdata->length != 0); - UNUSED(tctx); - dns_rdata_toregion(rdata, &sr); + /* Hash */ hash = uint8_fromregion(&sr); isc_region_consume(&sr, 1); - - flags = uint8_fromregion(&sr); - isc_region_consume(&sr, 1); - - iterations = uint16_fromregion(&sr); - isc_region_consume(&sr, 2); - sprintf(buf, "%u ", hash); RETERR(str_totext(buf, target)); + /* Flags */ + flags = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); sprintf(buf, "%u ", flags); RETERR(str_totext(buf, target)); + /* Iterations */ + iterations = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); sprintf(buf, "%u ", iterations); RETERR(str_totext(buf, target)); + /* Salt */ j = uint8_fromregion(&sr); isc_region_consume(&sr, 1); INSIST(j <= sr.length); @@ -177,10 +177,14 @@ totext_nsec3(ARGS_TOTEXT) { sr.length = j; RETERR(isc_hex_totext(&sr, 1, "", target)); sr.length = i - j; - RETERR(str_totext(" ", target)); } else - RETERR(str_totext("- ", target)); + RETERR(str_totext("-", target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + + /* Next hash */ j = uint8_fromregion(&sr); isc_region_consume(&sr, 1); INSIST(j <= sr.length); @@ -190,7 +194,16 @@ totext_nsec3(ARGS_TOTEXT) { RETERR(isc_base32hex_totext(&sr, 1, "", target)); sr.length = i - j; + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) + RETERR(str_totext(" ", target)); + + /* Types covered */ + first = ISC_TRUE; for (i = 0; i < sr.length; i += len) { + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + RETERR(str_totext(tctx->linebreak, target)); + first = ISC_TRUE; + } INSIST(i + 2 <= sr.length); window = sr.base[i]; len = sr.base[i + 1]; @@ -205,7 +218,9 @@ totext_nsec3(ARGS_TOTEXT) { if ((sr.base[i + j] & (0x80 >> k)) == 0) continue; t = window * 256 + j * 8 + k; - RETERR(str_totext(" ", target)); + if (!first) + RETERR(str_totext(" ", target)); + first = ISC_FALSE; if (dns_rdatatype_isknown(t)) { RETERR(dns_rdatatype_totext(t, target)); } else { @@ -216,6 +231,10 @@ totext_nsec3(ARGS_TOTEXT) { } } } + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + return (ISC_R_SUCCESS); } diff --git a/contrib/bind9/lib/dns/rdata/generic/nsec3_50.h b/contrib/bind9/lib/dns/rdata/generic/nsec3_50.h index 69a1141da007..5f2afb863b93 100644 --- a/contrib/bind9/lib/dns/rdata/generic/nsec3_50.h +++ b/contrib/bind9/lib/dns/rdata/generic/nsec3_50.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -46,7 +46,16 @@ typedef struct dns_rdata_nsec3 { #define DNS_NSEC3FLAG_OPTOUT 0x01U /*% - * Non-standard, NSEC3PARAM only. + * The following flags are used in the private-type record (implemented in + * lib/dns/private.c) which is used to store NSEC3PARAM data during the + * time when it is not legal to have an actual NSEC3PARAM record in the + * zone. They are defined here because the private-type record uses the + * same flags field for the OPTOUT flag above and for the private flags + * below. XXX: This should be considered for refactoring. + */ + +/*% + * Non-standard, private type only. * * Create a corresponding NSEC3 chain. * Once the NSEC3 chain is complete this flag will be removed to signal @@ -55,13 +64,14 @@ typedef struct dns_rdata_nsec3 { * This flag is automatically set when a NSEC3PARAM record is added to * the zone via UPDATE. * - * NSEC3PARAM records with this flag set are supposed to be ignored by - * RFC 5155 compliant nameservers. + * NSEC3PARAM records containing this flag should never be published, + * but if they are, they should be ignored by RFC 5155 compliant + * nameservers. */ #define DNS_NSEC3FLAG_CREATE 0x80U /*% - * Non-standard, NSEC3PARAM only. + * Non-standard, private type only. * * The corresponding NSEC3 set is to be removed once the NSEC chain * has been generated. @@ -69,24 +79,39 @@ typedef struct dns_rdata_nsec3 { * This flag is automatically set when the last active NSEC3PARAM record * is removed from the zone via UPDATE. * - * NSEC3PARAM records with this flag set are supposed to be ignored by - * RFC 5155 compliant nameservers. + * NSEC3PARAM records containing this flag should never be published, + * but if they are, they should be ignored by RFC 5155 compliant + * nameservers. */ #define DNS_NSEC3FLAG_REMOVE 0x40U /*% - * Non-standard, NSEC3PARAM only. + * Non-standard, private type only. * - * Used to identify NSEC3PARAM records added in this UPDATE request. + * When set with the CREATE flag, a corresponding NSEC3 chain will be + * created when the zone becomes capable of supporting one (i.e., when it + * has a DNSKEY RRset containing at least one NSEC3-capable algorithm). + * Without this flag, NSEC3 chain creation would be attempted immediately, + * fail, and the private type record would be removed. With it, the NSEC3 + * parameters are stored until they can be used. When the zone has the + * necessary prerequisites for NSEC3, then the INITIAL flag can be cleared, + * and the record will be cleaned up normally. + * + * NSEC3PARAM records containing this flag should never be published, but + * if they are, they should be ignored by RFC 5155 compliant nameservers. */ -#define DNS_NSEC3FLAG_UPDATE 0x20U +#define DNS_NSEC3FLAG_INITIAL 0x20U /*% - * Non-standard, NSEC3PARAM only. + * Non-standard, private type only. * * Prevent the creation of a NSEC chain before the last NSEC3 chain * is removed. This will normally only be set when the zone is * transitioning from secure with NSEC3 chains to insecure. + * + * NSEC3PARAM records containing this flag should never be published, + * but if they are, they should be ignored by RFC 5155 compliant + * nameservers. */ #define DNS_NSEC3FLAG_NONSEC 0x10U diff --git a/contrib/bind9/lib/dns/rdata/generic/opt_41.c b/contrib/bind9/lib/dns/rdata/generic/opt_41.c index fa349f1f5808..4b51804317cc 100644 --- a/contrib/bind9/lib/dns/rdata/generic/opt_41.c +++ b/contrib/bind9/lib/dns/rdata/generic/opt_41.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -76,8 +76,12 @@ totext_opt(ARGS_TOTEXT) { RETERR(str_totext(tctx->linebreak, target)); or = r; or.length = length; - RETERR(isc_base64_totext(&or, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&or, 60, "", target)); + else + RETERR(isc_base64_totext(&or, tctx->width - 2, + tctx->linebreak, + target)); isc_region_consume(&r, length); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); diff --git a/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c b/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c index 82dfce69d31e..58a327c02ed7 100644 --- a/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c +++ b/contrib/bind9/lib/dns/rdata/generic/rrsig_46.c @@ -181,7 +181,10 @@ totext_rrsig(ARGS_TOTEXT) { isc_region_consume(&sr, 4); sprintf(buf, "%lu", ttl); RETERR(str_totext(buf, target)); - RETERR(str_totext(" ", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); /* * Sig exp. @@ -189,10 +192,7 @@ totext_rrsig(ARGS_TOTEXT) { exp = uint32_fromregion(&sr); isc_region_consume(&sr, 4); RETERR(dns_time32_totext(exp, target)); - - if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) - RETERR(str_totext(" (", target)); - RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext(" ", target)); /* * Time signed. @@ -223,8 +223,11 @@ totext_rrsig(ARGS_TOTEXT) { * Sig. */ RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); diff --git a/contrib/bind9/lib/dns/rdata/generic/sig_24.c b/contrib/bind9/lib/dns/rdata/generic/sig_24.c index 3cdd17a06b8a..803a864067f0 100644 --- a/contrib/bind9/lib/dns/rdata/generic/sig_24.c +++ b/contrib/bind9/lib/dns/rdata/generic/sig_24.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -227,8 +227,11 @@ totext_sig(ARGS_TOTEXT) { * Sig. */ RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); diff --git a/contrib/bind9/lib/dns/rdata/generic/soa_6.c b/contrib/bind9/lib/dns/rdata/generic/soa_6.c index a86761035751..ac0a38f7c19e 100644 --- a/contrib/bind9/lib/dns/rdata/generic/soa_6.c +++ b/contrib/bind9/lib/dns/rdata/generic/soa_6.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -102,7 +102,7 @@ totext_soa(ARGS_TOTEXT) { multiline = ISC_TF((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0); if (multiline) - comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0); + comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0); else comment = ISC_FALSE; diff --git a/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c b/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c index 03d5127133c6..d553cd40380d 100644 --- a/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c +++ b/contrib/bind9/lib/dns/rdata/generic/sshfp_44.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007, 2009, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2006, 2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -95,7 +95,11 @@ totext_sshfp(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); return (ISC_R_SUCCESS); diff --git a/contrib/bind9/lib/dns/rdata/generic/tkey_249.c b/contrib/bind9/lib/dns/rdata/generic/tkey_249.c index 3afee1308245..6f1ec0253881 100644 --- a/contrib/bind9/lib/dns/rdata/generic/tkey_249.c +++ b/contrib/bind9/lib/dns/rdata/generic/tkey_249.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -201,8 +201,11 @@ totext_tkey(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&dr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&dr, 60, "", target)); + else + RETERR(isc_base64_totext(&dr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" ) ", target)); else @@ -227,8 +230,11 @@ totext_tkey(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" (", target)); RETERR(str_totext(tctx->linebreak, target)); - RETERR(isc_base64_totext(&dr, tctx->width - 2, - tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&dr, 60, "", target)); + else + RETERR(isc_base64_totext(&dr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext(" )", target)); } diff --git a/contrib/bind9/lib/dns/rdata/generic/uri_256.c b/contrib/bind9/lib/dns/rdata/generic/uri_256.c index aa5b1946dc82..799eb694e666 100644 --- a/contrib/bind9/lib/dns/rdata/generic/uri_256.c +++ b/contrib/bind9/lib/dns/rdata/generic/uri_256.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: uri_256.c,v 1.2 2011/03/03 14:10:27 fdupont Exp $ */ +/* $Id$ */ #ifndef GENERIC_URI_256_C #define GENERIC_URI_256_C 1 diff --git a/contrib/bind9/lib/dns/rdata/generic/uri_256.h b/contrib/bind9/lib/dns/rdata/generic/uri_256.h index 5061c03c6528..13c8fd238b89 100644 --- a/contrib/bind9/lib/dns/rdata/generic/uri_256.h +++ b/contrib/bind9/lib/dns/rdata/generic/uri_256.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,7 +17,7 @@ #ifndef GENERIC_URI_256_H #define GENERIC_URI_256_H 1 -/* $Id: uri_256.h,v 1.2 2011/03/03 14:10:27 fdupont Exp $ */ +/* $Id$ */ typedef struct dns_rdata_uri { dns_rdatacommon_t common; diff --git a/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c b/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c index 1ec75ecacfb5..7575da0d1930 100644 --- a/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c +++ b/contrib/bind9/lib/dns/rdata/in_1/dhcid_49.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -52,8 +52,11 @@ totext_in_dhcid(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) RETERR(str_totext("( " /*)*/, target)); - RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, - target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { RETERR(str_totext(/* ( */ " )", target)); if (rdata->length > 2) { diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c index e21d97e1e66b..27d15b9329cd 100644 --- a/contrib/bind9/lib/dns/resolver.c +++ b/contrib/bind9/lib/dns/resolver.c @@ -26,8 +26,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -160,6 +161,7 @@ typedef struct query { isc_buffer_t buffer; isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; + isc_socketevent_t sendevent; unsigned int options; unsigned int attributes; unsigned int sends; @@ -393,11 +395,10 @@ struct dns_resolver { isc_boolean_t frozen; unsigned int options; dns_dispatchmgr_t * dispatchmgr; - dns_dispatch_t * dispatchv4; + dns_dispatchset_t * dispatches4; isc_boolean_t exclusivev4; - dns_dispatch_t * dispatchv6; + dns_dispatchset_t * dispatches6; isc_boolean_t exclusivev6; - unsigned int ndisps; unsigned int nbuckets; fctxbucket_t * buckets; isc_uint32_t lame_ttl; @@ -424,7 +425,6 @@ struct dns_resolver { unsigned int activebuckets; isc_boolean_t priming; unsigned int spillat; /* clients-per-query */ - unsigned int nextdisp; /* Bad cache. */ dns_badcache_t ** badcache; @@ -1218,7 +1218,8 @@ process_sendevent(resquery_t *query, isc_event_t *event) { } } - isc_event_free(&event); + if (event->ev_type == ISC_SOCKEVENT_CONNECT) + isc_event_free(&event); if (retry) { /* @@ -1413,14 +1414,14 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, if (!have_addr) { switch (pf) { case PF_INET: - result = - dns_dispatch_getlocaladdress(res->dispatchv4, - &addr); + result = dns_dispatch_getlocaladdress( + res->dispatches4->dispatches[0], + &addr); break; case PF_INET6: - result = - dns_dispatch_getlocaladdress(res->dispatchv6, - &addr); + result = dns_dispatch_getlocaladdress( + res->dispatches6->dispatches[0], + &addr); break; default: result = ISC_R_NOTIMPLEMENTED; @@ -1476,13 +1477,15 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, } else { switch (isc_sockaddr_pf(&addrinfo->sockaddr)) { case PF_INET: - dns_dispatch_attach(res->dispatchv4, - &query->dispatch); + dns_dispatch_attach( + dns_resolver_dispatchv4(res), + &query->dispatch); query->exclusivesocket = res->exclusivev4; break; case PF_INET6: - dns_dispatch_attach(res->dispatchv6, - &query->dispatch); + dns_dispatch_attach( + dns_resolver_dispatchv6(res), + &query->dispatch); query->exclusivesocket = res->exclusivev6; break; default: @@ -1975,8 +1978,11 @@ resquery_send(resquery_t *query) { * XXXRTH Make sure we don't send to ourselves! We should probably * prune out these addresses when we get them from the ADB. */ - result = isc_socket_sendto(socket, &r, task, resquery_senddone, - query, address, NULL); + ISC_EVENT_INIT(&query->sendevent, sizeof(query->sendevent), 0, NULL, + ISC_SOCKEVENT_SENDDONE, resquery_senddone, query, + NULL, NULL, NULL); + result = isc_socket_sendto2(socket, &r, task, address, NULL, + &query->sendevent, 0); if (result != ISC_R_SUCCESS) { if (connecting) { /* @@ -2510,9 +2516,9 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port, */ if (need_alternate != NULL && !*need_alternate && unshared && - ((res->dispatchv4 == NULL && + ((res->dispatches4 == NULL && find->result_v6 != DNS_R_NXDOMAIN) || - (res->dispatchv6 == NULL && + (res->dispatches6 == NULL && find->result_v4 != DNS_R_NXDOMAIN))) *need_alternate = ISC_TRUE; } else { @@ -2527,9 +2533,9 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port, * an alternative server. */ if (need_alternate != NULL && !*need_alternate && - ((res->dispatchv4 == NULL && + ((res->dispatches4 == NULL && find->result_v6 == DNS_R_NXRRSET) || - (res->dispatchv6 == NULL && + (res->dispatches6 == NULL && find->result_v4 == DNS_R_NXRRSET))) *need_alternate = ISC_TRUE; dns_adb_destroyfind(&find); @@ -2627,9 +2633,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { while (sa != NULL) { if ((isc_sockaddr_pf(sa) == AF_INET && - fctx->res->dispatchv4 == NULL) || + fctx->res->dispatches4 == NULL) || (isc_sockaddr_pf(sa) == AF_INET6 && - fctx->res->dispatchv6 == NULL)) { + fctx->res->dispatches6 == NULL)) { sa = ISC_LIST_NEXT(sa, link); continue; } @@ -2677,9 +2683,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { */ stdoptions |= DNS_ADBFIND_AVOIDFETCHES; } - if (res->dispatchv4 != NULL) + if (res->dispatches4 != NULL) stdoptions |= DNS_ADBFIND_INET; - if (res->dispatchv6 != NULL) + if (res->dispatches6 != NULL) stdoptions |= DNS_ADBFIND_INET6; isc_stdtime_get(&now); @@ -2712,7 +2718,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { if (need_alternate) { int family; alternate_t *a; - family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET; + family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET; for (a = ISC_LIST_HEAD(fctx->res->alternates); a != NULL; a = ISC_LIST_NEXT(a, link)) { @@ -7567,10 +7573,10 @@ destroy(dns_resolver_t *res) { } isc_mem_put(res->mctx, res->buckets, res->nbuckets * sizeof(fctxbucket_t)); - if (res->dispatchv4 != NULL) - dns_dispatch_detach(&res->dispatchv4); - if (res->dispatchv6 != NULL) - dns_dispatch_detach(&res->dispatchv6); + if (res->dispatches4 != NULL) + dns_dispatchset_destroy(&res->dispatches4); + if (res->dispatches6 != NULL) + dns_dispatchset_destroy(&res->dispatches6); while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) { ISC_LIST_UNLINK(res->alternates, a, link); if (!a->isaddress) @@ -7660,7 +7666,8 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) { isc_result_t dns_resolver_create(dns_view_t *view, - isc_taskmgr_t *taskmgr, unsigned int ntasks, + isc_taskmgr_t *taskmgr, + unsigned int ntasks, unsigned int ndisp, isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, unsigned int options, @@ -7682,6 +7689,7 @@ dns_resolver_create(dns_view_t *view, REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(ntasks > 0); + REQUIRE(ndisp > 0); REQUIRE(resp != NULL && *resp == NULL); REQUIRE(dispatchmgr != NULL); REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL); @@ -7712,8 +7720,6 @@ dns_resolver_create(dns_view_t *view, res->spillattimer = NULL; res->zero_no_soa_ttl = ISC_FALSE; res->query_timeout = DEFAULT_QUERY_TIMEOUT; - res->ndisps = 0; - res->nextdisp = 0; /* meaningless at this point, but init it */ res->nbuckets = ntasks; res->activebuckets = ntasks; res->buckets = isc_mem_get(view->mctx, @@ -7756,17 +7762,19 @@ dns_resolver_create(dns_view_t *view, buckets_created++; } - res->dispatchv4 = NULL; + res->dispatches4 = NULL; if (dispatchv4 != NULL) { - dns_dispatch_attach(dispatchv4, &res->dispatchv4); + dns_dispatchset_create(view->mctx, socketmgr, taskmgr, + dispatchv4, &res->dispatches4, ndisp); dispattr = dns_dispatch_getattributes(dispatchv4); res->exclusivev4 = ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0); } - res->dispatchv6 = NULL; + res->dispatches6 = NULL; if (dispatchv6 != NULL) { - dns_dispatch_attach(dispatchv6, &res->dispatchv6); + dns_dispatchset_create(view->mctx, socketmgr, taskmgr, + dispatchv6, &res->dispatches6, ndisp); dispattr = dns_dispatch_getattributes(dispatchv6); res->exclusivev6 = ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0); @@ -7842,10 +7850,10 @@ dns_resolver_create(dns_view_t *view, DESTROYLOCK(&res->lock); cleanup_dispatches: - if (res->dispatchv6 != NULL) - dns_dispatch_detach(&res->dispatchv6); - if (res->dispatchv4 != NULL) - dns_dispatch_detach(&res->dispatchv4); + if (res->dispatches6 != NULL) + dns_dispatchset_destroy(&res->dispatches6); + if (res->dispatches4 != NULL) + dns_dispatchset_destroy(&res->dispatches4); cleanup_buckets: for (i = 0; i < buckets_created; i++) { @@ -8034,7 +8042,6 @@ void dns_resolver_shutdown(dns_resolver_t *res) { unsigned int i; fetchctx_t *fctx; - isc_socket_t *sock; isc_result_t result; REQUIRE(VALID_RESOLVER(res)); @@ -8053,15 +8060,13 @@ dns_resolver_shutdown(dns_resolver_t *res) { fctx != NULL; fctx = ISC_LIST_NEXT(fctx, link)) fctx_shutdown(fctx); - if (res->dispatchv4 != NULL && !res->exclusivev4) { - sock = dns_dispatch_getsocket(res->dispatchv4); - isc_socket_cancel(sock, res->buckets[i].task, - ISC_SOCKCANCEL_ALL); + if (res->dispatches4 != NULL && !res->exclusivev4) { + dns_dispatchset_cancelall(res->dispatches4, + res->buckets[i].task); } - if (res->dispatchv6 != NULL && !res->exclusivev6) { - sock = dns_dispatch_getsocket(res->dispatchv6); - isc_socket_cancel(sock, res->buckets[i].task, - ISC_SOCKCANCEL_ALL); + if (res->dispatches6 != NULL && !res->exclusivev6) { + dns_dispatchset_cancelall(res->dispatches6, + res->buckets[i].task); } res->buckets[i].exiting = ISC_TRUE; if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) { @@ -8444,13 +8449,13 @@ dns_resolver_dispatchmgr(dns_resolver_t *resolver) { dns_dispatch_t * dns_resolver_dispatchv4(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); - return (resolver->dispatchv4); + return (dns_dispatchset_get(resolver->dispatches4)); } dns_dispatch_t * dns_resolver_dispatchv6(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); - return (resolver->dispatchv6); + return (dns_dispatchset_get(resolver->dispatches6)); } isc_socketmgr_t * diff --git a/contrib/bind9/lib/dns/sdb.c b/contrib/bind9/lib/dns/sdb.c index 526ce87537b8..191fda219f46 100644 --- a/contrib/bind9/lib/dns/sdb.c +++ b/contrib/bind9/lib/dns/sdb.c @@ -728,8 +728,9 @@ destroynode(dns_sdbnode_t *node) { } static isc_result_t -findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, - dns_dbnode_t **nodep) +findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_dbnode_t **nodep) { dns_sdb_t *sdb = (dns_sdb_t *)db; dns_sdbnode_t *node = NULL; @@ -786,10 +787,11 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, MAYBE_LOCK(sdb); if (imp->methods->lookup2 != NULL) result = imp->methods->lookup2(&sdb->common.origin, name, - sdb->dbdata, node); + sdb->dbdata, node, methods, + clientinfo); else result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, - node); + node, methods, clientinfo); MAYBE_UNLOCK(sdb); if (result != ISC_R_SUCCESS && !(result == ISC_R_NOTFOUND && @@ -814,10 +816,11 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, } static isc_result_t -find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, - dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, - dns_dbnode_t **nodep, dns_name_t *foundname, - dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { dns_sdb_t *sdb = (dns_sdb_t *)db; dns_dbnode_t *node = NULL; @@ -857,7 +860,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * Look up the next label. */ dns_name_getlabelsequence(name, nlabels - i, i, xname); - result = findnode(db, xname, ISC_FALSE, &node); + result = findnodeext(db, xname, ISC_FALSE, methods, + clientinfo, &node); if (result == ISC_R_NOTFOUND) { /* * No data at zone apex? @@ -1264,8 +1268,8 @@ static dns_dbmethods_t sdb_methods = { newversion, attachversion, closeversion, - findnode, - find, + NULL, + NULL, findzonecut, attachnode, detachnode, @@ -1282,17 +1286,19 @@ static dns_dbmethods_t sdb_methods = { ispersistent, overmem, settask, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* getoriginnode */ + NULL, /* transfernode */ + NULL, /* getnsec3parameters */ + NULL, /* findnsec3node */ + NULL, /* setsigningtime */ + NULL, /* getsigningtime */ + NULL, /* resigned */ + NULL, /* isdnssec */ + NULL, /* getrrsetstats */ + NULL, /* rpz_enabled */ + NULL, /* rpz_findips */ + findnodeext, + findext }; static isc_result_t diff --git a/contrib/bind9/lib/dns/sdlz.c b/contrib/bind9/lib/dns/sdlz.c index 6e518d1ecbcb..9d4e615802fa 100644 --- a/contrib/bind9/lib/dns/sdlz.c +++ b/contrib/bind9/lib/dns/sdlz.c @@ -538,8 +538,9 @@ destroynode(dns_sdlznode_t *node) { } static isc_result_t -findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, - dns_dbnode_t **nodep) +findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_dbnode_t **nodep) { dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; dns_sdlznode_t *node = NULL; @@ -598,17 +599,18 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, /* try to lookup the host (namestr) */ result = sdlz->dlzimp->methods->lookup(zonestr, namestr, sdlz->dlzimp->driverarg, - sdlz->dbdata, node); + sdlz->dbdata, node, + methods, clientinfo); /* * if the host (namestr) was not found, try to lookup a * "wildcard" host. */ - if (result != ISC_R_SUCCESS && !create) { + if (result != ISC_R_SUCCESS && !create) result = sdlz->dlzimp->methods->lookup(zonestr, "*", sdlz->dlzimp->driverarg, - sdlz->dbdata, node); - } + sdlz->dbdata, node, + methods, clientinfo); MAYBE_UNLOCK(sdlz->dlzimp); @@ -651,6 +653,13 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, return (ISC_R_SUCCESS); } +static isc_result_t +findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_dbnode_t **nodep) +{ + return (findnodeext(db, name, create, NULL, NULL, nodep)); +} + static isc_result_t findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, @@ -825,10 +834,11 @@ findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } static isc_result_t -find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, - dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, - dns_dbnode_t **nodep, dns_name_t *foundname, - dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; dns_dbnode_t *node = NULL; @@ -867,7 +877,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * Look up the next label. */ dns_name_getlabelsequence(name, nlabels - i, i, xname); - result = findnode(db, xname, ISC_FALSE, &node); + result = findnodeext(db, xname, ISC_FALSE, + methods, clientinfo, &node); if (result != ISC_R_SUCCESS) { result = DNS_R_NXDOMAIN; continue; @@ -879,8 +890,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, */ if (i < nlabels) { result = findrdataset(db, node, version, - dns_rdatatype_dname, - 0, now, rdataset, sigrdataset); + dns_rdatatype_dname, 0, now, + rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { result = DNS_R_DNAME; break; @@ -893,8 +904,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, */ if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { result = findrdataset(db, node, version, - dns_rdatatype_ns, - 0, now, rdataset, sigrdataset); + dns_rdatatype_ns, 0, now, + rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { if (i == nlabels && type == dns_rdatatype_any) { @@ -933,8 +944,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, /* * Look for the qtype. */ - result = findrdataset(db, node, version, type, - 0, now, rdataset, sigrdataset); + result = findrdataset(db, node, version, type, 0, now, + rdataset, sigrdataset); if (result == ISC_R_SUCCESS) break; @@ -943,8 +954,8 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, */ if (type != dns_rdatatype_cname) { result = findrdataset(db, node, version, - dns_rdatatype_cname, - 0, now, rdataset, sigrdataset); + dns_rdatatype_cname, 0, now, + rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { result = DNS_R_CNAME; break; @@ -979,6 +990,16 @@ find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, return (result); } +static isc_result_t +find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) +{ + return (findext(db, name, version, type, options, now, nodep, + foundname, NULL, NULL, rdataset, sigrdataset)); +} + static isc_result_t allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) @@ -1194,7 +1215,8 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { if (sdlz->dlzimp->methods->newversion == NULL) return (ISC_R_NOTIMPLEMENTED); - result = findnode(db, &sdlz->common.origin, ISC_FALSE, nodep); + result = findnodeext(db, &sdlz->common.origin, ISC_FALSE, + NULL, NULL, nodep); if (result != ISC_R_SUCCESS) sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed : %s", isc_result_totext(result)); @@ -1230,16 +1252,18 @@ static dns_dbmethods_t sdlzdb_methods = { overmem, settask, getoriginnode, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL + NULL, /* transfernode */ + NULL, /* getnsec3parameters */ + NULL, /* findnsec3node */ + NULL, /* setsigningtime */ + NULL, /* getsigningtime */ + NULL, /* resigned */ + NULL, /* isdnssec */ + NULL, /* getrrsetstats */ + NULL, /* rpz_enabled */ + NULL, /* rpz_findips */ + findnodeext, + findext }; /* diff --git a/contrib/bind9/lib/dns/update.c b/contrib/bind9/lib/dns/update.c new file mode 100644 index 000000000000..14ffcc2234d8 --- /dev/null +++ b/contrib/bind9/lib/dns/update.c @@ -0,0 +1,1865 @@ +/* + * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/**************************************************************************/ + +/*% + * Log level for tracing dynamic update protocol requests. + */ +#define LOGLEVEL_PROTOCOL ISC_LOG_INFO + +/*% + * Log level for low-level debug tracing. + */ +#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8) + +/*% + * Check an operation for failure. These macros all assume that + * the function using them has a 'result' variable and a 'failure' + * label. + */ +#define CHECK(op) \ + do { result = (op); \ + if (result != ISC_R_SUCCESS) goto failure; \ + } while (0) + +/*% + * Fail unconditionally with result 'code', which must not + * be ISC_R_SUCCESS. The reason for failure presumably has + * been logged already. + * + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". + */ + +#define FAIL(code) \ + do { \ + result = (code); \ + if (result != ISC_R_SUCCESS) goto failure; \ + } while (0) + +/*% + * Fail unconditionally and log as a client error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". + */ +#define FAILC(code, msg) \ + do { \ + const char *_what = "failed"; \ + result = (code); \ + switch (result) { \ + case DNS_R_NXDOMAIN: \ + case DNS_R_YXDOMAIN: \ + case DNS_R_YXRRSET: \ + case DNS_R_NXRRSET: \ + _what = "unsuccessful"; \ + } \ + update_log(log, zone, LOGLEVEL_PROTOCOL, \ + "update %s: %s (%s)", _what, \ + msg, isc_result_totext(result)); \ + if (result != ISC_R_SUCCESS) goto failure; \ + } while (0) + +#define FAILN(code, name, msg) \ + do { \ + const char *_what = "failed"; \ + result = (code); \ + switch (result) { \ + case DNS_R_NXDOMAIN: \ + case DNS_R_YXDOMAIN: \ + case DNS_R_YXRRSET: \ + case DNS_R_NXRRSET: \ + _what = "unsuccessful"; \ + } \ + if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \ + char _nbuf[DNS_NAME_FORMATSIZE]; \ + dns_name_format(name, _nbuf, sizeof(_nbuf)); \ + update_log(log, zone, LOGLEVEL_PROTOCOL, \ + "update %s: %s: %s (%s)", _what, _nbuf, \ + msg, isc_result_totext(result)); \ + } \ + if (result != ISC_R_SUCCESS) goto failure; \ + } while (0) + +#define FAILNT(code, name, type, msg) \ + do { \ + const char *_what = "failed"; \ + result = (code); \ + switch (result) { \ + case DNS_R_NXDOMAIN: \ + case DNS_R_YXDOMAIN: \ + case DNS_R_YXRRSET: \ + case DNS_R_NXRRSET: \ + _what = "unsuccessful"; \ + } \ + if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \ + char _nbuf[DNS_NAME_FORMATSIZE]; \ + char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \ + dns_name_format(name, _nbuf, sizeof(_nbuf)); \ + dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \ + update_log(log, zone, LOGLEVEL_PROTOCOL, \ + "update %s: %s/%s: %s (%s)", \ + _what, _nbuf, _tbuf, msg, \ + isc_result_totext(result)); \ + } \ + if (result != ISC_R_SUCCESS) goto failure; \ + } while (0) + +/*% + * Fail unconditionally and log as a server error. + * The test against ISC_R_SUCCESS is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". + */ +#define FAILS(code, msg) \ + do { \ + result = (code); \ + update_log(log, zone, LOGLEVEL_PROTOCOL, \ + "error: %s: %s", \ + msg, isc_result_totext(result)); \ + if (result != ISC_R_SUCCESS) goto failure; \ + } while (0) + +/**************************************************************************/ + +typedef struct rr rr_t; + +struct rr { + /* dns_name_t name; */ + isc_uint32_t ttl; + dns_rdata_t rdata; +}; + +typedef struct update_event update_event_t; + +/**************************************************************************/ + +static void +update_log(dns_update_log_t *callback, dns_zone_t *zone, + int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); + +static void +update_log(dns_update_log_t *callback, dns_zone_t *zone, + int level, const char *fmt, ...) +{ + va_list ap; + char message[4096]; + + if (callback == NULL) + return; + + if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) + return; + + + va_start(ap, fmt); + vsnprintf(message, sizeof(message), fmt, ap); + va_end(ap); + + (callback->func)(callback->arg, zone, level, message); +} + +/*% + * Update a single RR in version 'ver' of 'db' and log the + * update in 'diff'. + * + * Ensures: + * \li '*tuple' == NULL. Either the tuple is freed, or its + * ownership has been transferred to the diff. + */ +static isc_result_t +do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, + dns_diff_t *diff) +{ + dns_diff_t temp_diff; + isc_result_t result; + + /* + * Create a singleton diff. + */ + dns_diff_init(diff->mctx, &temp_diff); + temp_diff.resign = diff->resign; + ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); + + /* + * Apply it to the database. + */ + result = dns_diff_apply(&temp_diff, db, ver); + ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); + if (result != ISC_R_SUCCESS) { + dns_difftuple_free(tuple); + return (result); + } + + /* + * Merge it into the current pending journal entry. + */ + dns_diff_appendminimal(diff, tuple); + + /* + * Do not clear temp_diff. + */ + return (ISC_R_SUCCESS); +} + +static isc_result_t +update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, + dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, + dns_rdata_t *rdata) +{ + dns_difftuple_t *tuple = NULL; + isc_result_t result; + result = dns_difftuple_create(diff->mctx, op, + name, ttl, rdata, &tuple); + if (result != ISC_R_SUCCESS) + return (result); + return (do_one_tuple(&tuple, db, ver, diff)); +} + +/**************************************************************************/ +/* + * Callback-style iteration over rdatasets and rdatas. + * + * foreach_rrset() can be used to iterate over the RRsets + * of a name and call a callback function with each + * one. Similarly, foreach_rr() can be used to iterate + * over the individual RRs at name, optionally restricted + * to RRs of a given type. + * + * The callback functions are called "actions" and take + * two arguments: a void pointer for passing arbitrary + * context information, and a pointer to the current RRset + * or RR. By convention, their names end in "_action". + */ + +/* + * XXXRTH We might want to make this public somewhere in libdns. + */ + +/*% + * Function type for foreach_rrset() iterator actions. + */ +typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset); + +/*% + * Function type for foreach_rr() iterator actions. + */ +typedef isc_result_t rr_func(void *data, rr_t *rr); + +/*% + * Internal context struct for foreach_node_rr(). + */ +typedef struct { + rr_func * rr_action; + void * rr_action_data; +} foreach_node_rr_ctx_t; + +/*% + * Internal helper function for foreach_node_rr(). + */ +static isc_result_t +foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) { + isc_result_t result; + foreach_node_rr_ctx_t *ctx = data; + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + rr_t rr = { 0, DNS_RDATA_INIT }; + + dns_rdataset_current(rdataset, &rr.rdata); + rr.ttl = rdataset->ttl; + result = (*ctx->rr_action)(ctx->rr_action_data, &rr); + if (result != ISC_R_SUCCESS) + return (result); + } + if (result != ISC_R_NOMORE) + return (result); + return (ISC_R_SUCCESS); +} + +/*% + * For each rdataset of 'name' in 'ver' of 'db', call 'action' + * with the rdataset and 'action_data' as arguments. If the name + * does not exist, do nothing. + * + * If 'action' returns an error, abort iteration and return the error. + */ +static isc_result_t +foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + rrset_func *action, void *action_data) +{ + isc_result_t result; + dns_dbnode_t *node; + dns_rdatasetiter_t *iter; + + node = NULL; + result = dns_db_findnode(db, name, ISC_FALSE, &node); + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + return (result); + + iter = NULL; + result = dns_db_allrdatasets(db, node, ver, + (isc_stdtime_t) 0, &iter); + if (result != ISC_R_SUCCESS) + goto cleanup_node; + + for (result = dns_rdatasetiter_first(iter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(iter)) + { + dns_rdataset_t rdataset; + + dns_rdataset_init(&rdataset); + dns_rdatasetiter_current(iter, &rdataset); + + result = (*action)(action_data, &rdataset); + + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup_iterator; + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + + cleanup_iterator: + dns_rdatasetiter_destroy(&iter); + + cleanup_node: + dns_db_detachnode(db, &node); + + return (result); +} + +/*% + * For each RR of 'name' in 'ver' of 'db', call 'action' + * with the RR and 'action_data' as arguments. If the name + * does not exist, do nothing. + * + * If 'action' returns an error, abort iteration + * and return the error. + */ +static isc_result_t +foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + rr_func *rr_action, void *rr_action_data) +{ + foreach_node_rr_ctx_t ctx; + ctx.rr_action = rr_action; + ctx.rr_action_data = rr_action_data; + return (foreach_rrset(db, ver, name, + foreach_node_rr_action, &ctx)); +} + + +/*% + * For each of the RRs specified by 'db', 'ver', 'name', 'type', + * (which can be dns_rdatatype_any to match any type), and 'covers', call + * 'action' with the RR and 'action_data' as arguments. If the name + * does not exist, or if no RRset of the given type exists at the name, + * do nothing. + * + * If 'action' returns an error, abort iteration and return the error. + */ +static isc_result_t +foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action, + void *rr_action_data) +{ + + isc_result_t result; + dns_dbnode_t *node; + dns_rdataset_t rdataset; + + if (type == dns_rdatatype_any) + return (foreach_node_rr(db, ver, name, + rr_action, rr_action_data)); + + node = NULL; + if (type == dns_rdatatype_nsec3 || + (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3)) + result = dns_db_findnsec3node(db, name, ISC_FALSE, &node); + else + result = dns_db_findnode(db, name, ISC_FALSE, &node); + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + return (result); + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, ver, type, covers, + (isc_stdtime_t) 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + goto cleanup_node; + } + if (result != ISC_R_SUCCESS) + goto cleanup_node; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) + { + rr_t rr = { 0, DNS_RDATA_INIT }; + dns_rdataset_current(&rdataset, &rr.rdata); + rr.ttl = rdataset.ttl; + result = (*rr_action)(rr_action_data, &rr); + if (result != ISC_R_SUCCESS) + goto cleanup_rdataset; + } + if (result != ISC_R_NOMORE) + goto cleanup_rdataset; + result = ISC_R_SUCCESS; + + cleanup_rdataset: + dns_rdataset_disassociate(&rdataset); + cleanup_node: + dns_db_detachnode(db, &node); + + return (result); +} + +/**************************************************************************/ +/* + * Various tests on the database contents (for prerequisites, etc). + */ + +/*% + * Function type for predicate functions that compare a database RR 'db_rr' + * against an update RR 'update_rr'. + */ +typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr); + +/*% + * Helper function for rrset_exists(). + */ +static isc_result_t +rrset_exists_action(void *data, rr_t *rr) { + UNUSED(data); + UNUSED(rr); + return (ISC_R_EXISTS); +} + +/*% + * Utility macro for RR existence checking functions. + * + * If the variable 'result' has the value ISC_R_EXISTS or + * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE, + * respectively, and return success. + * + * If 'result' has any other value, there was a failure. + * Return the failure result code and do not set *exists. + * + * This would be more readable as "do { if ... } while(0)", + * but that form generates tons of warnings on Solaris 2.6. + */ +#define RETURN_EXISTENCE_FLAG \ + return ((result == ISC_R_EXISTS) ? \ + (*exists = ISC_TRUE, ISC_R_SUCCESS) : \ + ((result == ISC_R_SUCCESS) ? \ + (*exists = ISC_FALSE, ISC_R_SUCCESS) : \ + result)) + +/*% + * Set '*exists' to true iff an rrset of the given type exists, + * to false otherwise. + */ +static isc_result_t +rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_rdatatype_t type, dns_rdatatype_t covers, + isc_boolean_t *exists) +{ + isc_result_t result; + result = foreach_rr(db, ver, name, type, covers, + rrset_exists_action, NULL); + RETURN_EXISTENCE_FLAG; +} + +/*% + * Set '*visible' to true if the RRset exists and is part of the + * visible zone. Otherwise '*visible' is set to false unless a + * error occurs. + */ +static isc_result_t +rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_rdatatype_t type, isc_boolean_t *visible) +{ + isc_result_t result; + dns_fixedname_t fixed; + + dns_fixedname_init(&fixed); + result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD, + (isc_stdtime_t) 0, NULL, + dns_fixedname_name(&fixed), NULL, NULL); + switch (result) { + case ISC_R_SUCCESS: + *visible = ISC_TRUE; + break; + /* + * Glue, obscured, deleted or replaced records. + */ + case DNS_R_DELEGATION: + case DNS_R_DNAME: + case DNS_R_CNAME: + case DNS_R_NXDOMAIN: + case DNS_R_NXRRSET: + case DNS_R_EMPTYNAME: + case DNS_R_COVERINGNSEC: + *visible = ISC_FALSE; + result = ISC_R_SUCCESS; + break; + default: + break; + } + return (result); +} + +/*% + * Context struct and helper function for name_exists(). + */ + +static isc_result_t +name_exists_action(void *data, dns_rdataset_t *rrset) { + UNUSED(data); + UNUSED(rrset); + return (ISC_R_EXISTS); +} + +/*% + * Set '*exists' to true iff the given name exists, to false otherwise. + */ +static isc_result_t +name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + isc_boolean_t *exists) +{ + isc_result_t result; + result = foreach_rrset(db, ver, name, + name_exists_action, NULL); + RETURN_EXISTENCE_FLAG; +} + +/**************************************************************************/ +/* + * Checking of "RRset exists (value dependent)" prerequisites. + * + * In the RFC2136 section 3.2.5, this is the pseudocode involving + * a variable called "temp", a mapping of tuples to rrsets. + * + * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t" + * where each tuple has op==DNS_DIFFOP_EXISTS. + */ + +/*% + * A comparison function defining the sorting order for the entries + * in the "temp" data structure. The major sort key is the owner name, + * followed by the type and rdata. + */ +static int +temp_order(const void *av, const void *bv) { + dns_difftuple_t const * const *ap = av; + dns_difftuple_t const * const *bp = bv; + dns_difftuple_t const *a = *ap; + dns_difftuple_t const *b = *bp; + int r; + r = dns_name_compare(&a->name, &b->name); + if (r != 0) + return (r); + r = (b->rdata.type - a->rdata.type); + if (r != 0) + return (r); + r = dns_rdata_casecompare(&a->rdata, &b->rdata); + return (r); +} + +/**************************************************************************/ +/* + * Conditional deletion of RRs. + */ + +/*% + * Context structure for delete_if(). + */ + +typedef struct { + rr_predicate *predicate; + dns_db_t *db; + dns_dbversion_t *ver; + dns_diff_t *diff; + dns_name_t *name; + dns_rdata_t *update_rr; +} conditional_delete_ctx_t; + +/*% + * Predicate functions for delete_if(). + */ + +/*% + * Return true always. + */ +static isc_boolean_t +true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { + UNUSED(update_rr); + UNUSED(db_rr); + return (ISC_TRUE); +} + +/*% + * Return true if the record is a RRSIG. + */ +static isc_boolean_t +rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { + UNUSED(update_rr); + return ((db_rr->type == dns_rdatatype_rrsig) ? + ISC_TRUE : ISC_FALSE); +} + +/*% + * Internal helper function for delete_if(). + */ +static isc_result_t +delete_if_action(void *data, rr_t *rr) { + conditional_delete_ctx_t *ctx = data; + if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) { + isc_result_t result; + result = update_one_rr(ctx->db, ctx->ver, ctx->diff, + DNS_DIFFOP_DEL, ctx->name, + rr->ttl, &rr->rdata); + return (result); + } else { + return (ISC_R_SUCCESS); + } +} + +/*% + * Conditionally delete RRs. Apply 'predicate' to the RRs + * specified by 'db', 'ver', 'name', and 'type' (which can + * be dns_rdatatype_any to match any type). Delete those + * RRs for which the predicate returns true, and log the + * deletions in 'diff'. + */ +static isc_result_t +delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver, + dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, + dns_rdata_t *update_rr, dns_diff_t *diff) +{ + conditional_delete_ctx_t ctx; + ctx.predicate = predicate; + ctx.db = db; + ctx.ver = ver; + ctx.diff = diff; + ctx.name = name; + ctx.update_rr = update_rr; + return (foreach_rr(db, ver, name, type, covers, + delete_if_action, &ctx)); +} + +/**************************************************************************/ +/* + * Incremental updating of NSECs and RRSIGs. + */ + +/*% + * We abuse the dns_diff_t type to represent a set of domain names + * affected by the update. + */ +static isc_result_t +namelist_append_name(dns_diff_t *list, dns_name_t *name) { + isc_result_t result; + dns_difftuple_t *tuple = NULL; + static dns_rdata_t dummy_rdata = DNS_RDATA_INIT; + + CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0, + &dummy_rdata, &tuple)); + dns_diff_append(list, &tuple); + failure: + return (result); +} + +static isc_result_t +namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected) +{ + isc_result_t result; + dns_fixedname_t fixedname; + dns_name_t *child; + dns_dbiterator_t *dbit = NULL; + + dns_fixedname_init(&fixedname); + child = dns_fixedname_name(&fixedname); + + CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit)); + + for (result = dns_dbiterator_seek(dbit, name); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbit)) + { + dns_dbnode_t *node = NULL; + CHECK(dns_dbiterator_current(dbit, &node, child)); + dns_db_detachnode(db, &node); + if (! dns_name_issubdomain(child, name)) + break; + CHECK(namelist_append_name(affected, child)); + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + failure: + if (dbit != NULL) + dns_dbiterator_destroy(&dbit); + return (result); +} + + + +/*% + * Helper function for non_nsec_rrset_exists(). + */ +static isc_result_t +is_non_nsec_action(void *data, dns_rdataset_t *rrset) { + UNUSED(data); + if (!(rrset->type == dns_rdatatype_nsec || + rrset->type == dns_rdatatype_nsec3 || + (rrset->type == dns_rdatatype_rrsig && + (rrset->covers == dns_rdatatype_nsec || + rrset->covers == dns_rdatatype_nsec3)))) + return (ISC_R_EXISTS); + return (ISC_R_SUCCESS); +} + +/*% + * Check whether there is an rrset other than a NSEC or RRSIG NSEC, + * i.e., anything that justifies the continued existence of a name + * after a secure update. + * + * If such an rrset exists, set '*exists' to ISC_TRUE. + * Otherwise, set it to ISC_FALSE. + */ +static isc_result_t +non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, + dns_name_t *name, isc_boolean_t *exists) +{ + isc_result_t result; + result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL); + RETURN_EXISTENCE_FLAG; +} + +/*% + * A comparison function for sorting dns_diff_t:s by name. + */ +static int +name_order(const void *av, const void *bv) { + dns_difftuple_t const * const *ap = av; + dns_difftuple_t const * const *bp = bv; + dns_difftuple_t const *a = *ap; + dns_difftuple_t const *b = *bp; + return (dns_name_compare(&a->name, &b->name)); +} + +static isc_result_t +uniqify_name_list(dns_diff_t *list) { + isc_result_t result; + dns_difftuple_t *p, *q; + + CHECK(dns_diff_sort(list, name_order)); + + p = ISC_LIST_HEAD(list->tuples); + while (p != NULL) { + do { + q = ISC_LIST_NEXT(p, link); + if (q == NULL || ! dns_name_equal(&p->name, &q->name)) + break; + ISC_LIST_UNLINK(list->tuples, q, link); + dns_difftuple_free(&q); + } while (1); + p = ISC_LIST_NEXT(p, link); + } + failure: + return (result); +} + +static isc_result_t +is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure) +{ + isc_result_t result; + dns_fixedname_t foundname; + dns_fixedname_init(&foundname); + result = dns_db_find(db, name, ver, dns_rdatatype_any, + DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD, + (isc_stdtime_t) 0, NULL, + dns_fixedname_name(&foundname), + NULL, NULL); + if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) { + *flag = ISC_TRUE; + *cut = ISC_FALSE; + if (unsecure != NULL) + *unsecure = ISC_FALSE; + return (ISC_R_SUCCESS); + } else if (result == DNS_R_ZONECUT) { + *flag = ISC_TRUE; + *cut = ISC_TRUE; + if (unsecure != NULL) { + /* + * We are at the zonecut. Check to see if there + * is a DS RRset. + */ + if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0, + (isc_stdtime_t) 0, NULL, + dns_fixedname_name(&foundname), + NULL, NULL) == DNS_R_NXRRSET) + *unsecure = ISC_TRUE; + else + *unsecure = ISC_FALSE; + } + return (ISC_R_SUCCESS); + } else if (result == DNS_R_GLUE || result == DNS_R_DNAME || + result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) { + *flag = ISC_FALSE; + *cut = ISC_FALSE; + if (unsecure != NULL) + *unsecure = ISC_FALSE; + return (ISC_R_SUCCESS); + } else { + /* + * Silence compiler. + */ + *flag = ISC_FALSE; + *cut = ISC_FALSE; + if (unsecure != NULL) + *unsecure = ISC_FALSE; + return (result); + } +} + +/*% + * Find the next/previous name that has a NSEC record. + * In other words, skip empty database nodes and names that + * have had their NSECs removed because they are obscured by + * a zone cut. + */ +static isc_result_t +next_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname, + isc_boolean_t forward) +{ + isc_result_t result; + dns_dbiterator_t *dbit = NULL; + isc_boolean_t has_nsec = ISC_FALSE; + unsigned int wraps = 0; + isc_boolean_t secure = dns_db_issecure(db); + + CHECK(dns_db_createiterator(db, 0, &dbit)); + + CHECK(dns_dbiterator_seek(dbit, oldname)); + do { + dns_dbnode_t *node = NULL; + + if (forward) + result = dns_dbiterator_next(dbit); + else + result = dns_dbiterator_prev(dbit); + if (result == ISC_R_NOMORE) { + /* + * Wrap around. + */ + if (forward) + CHECK(dns_dbiterator_first(dbit)); + else + CHECK(dns_dbiterator_last(dbit)); + wraps++; + if (wraps == 2) { + update_log(log, zone, ISC_LOG_ERROR, + "secure zone with no NSECs"); + result = DNS_R_BADZONE; + goto failure; + } + } + CHECK(dns_dbiterator_current(dbit, &node, newname)); + dns_db_detachnode(db, &node); + + /* + * The iterator may hold the tree lock, and + * rrset_exists() calls dns_db_findnode() which + * may try to reacquire it. To avoid deadlock + * we must pause the iterator first. + */ + CHECK(dns_dbiterator_pause(dbit)); + if (secure) { + CHECK(rrset_exists(db, ver, newname, + dns_rdatatype_nsec, 0, &has_nsec)); + } else { + dns_fixedname_t ffound; + dns_name_t *found; + dns_fixedname_init(&ffound); + found = dns_fixedname_name(&ffound); + result = dns_db_find(db, newname, ver, + dns_rdatatype_soa, + DNS_DBFIND_NOWILD, 0, NULL, found, + NULL, NULL); + if (result == ISC_R_SUCCESS || + result == DNS_R_EMPTYNAME || + result == DNS_R_NXRRSET || + result == DNS_R_CNAME || + (result == DNS_R_DELEGATION && + dns_name_equal(newname, found))) { + has_nsec = ISC_TRUE; + result = ISC_R_SUCCESS; + } else if (result != DNS_R_NXDOMAIN) + break; + } + } while (! has_nsec); + failure: + if (dbit != NULL) + dns_dbiterator_destroy(&dbit); + + return (result); +} + +/*% + * Add a NSEC record for "name", recording the change in "diff". + * The existing NSEC is removed. + */ +static isc_result_t +add_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl, + dns_diff_t *diff) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + unsigned char buffer[DNS_NSEC_BUFFERSIZE]; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_difftuple_t *tuple = NULL; + dns_fixedname_t fixedname; + dns_name_t *target; + + dns_fixedname_init(&fixedname); + target = dns_fixedname_name(&fixedname); + + /* + * Find the successor name, aka NSEC target. + */ + CHECK(next_active(log, zone, db, ver, name, target, ISC_TRUE)); + + /* + * Create the NSEC RDATA. + */ + CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); + dns_rdata_init(&rdata); + CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata)); + dns_db_detachnode(db, &node); + + /* + * Delete the old NSEC and record the change. + */ + CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0, + NULL, diff)); + /* + * Add the new NSEC and record the change. + */ + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, + nsecttl, &rdata, &tuple)); + CHECK(do_one_tuple(&tuple, db, ver, diff)); + INSIST(tuple == NULL); + + failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} + +/*% + * Add a placeholder NSEC record for "name", recording the change in "diff". + */ +static isc_result_t +add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_diff_t *diff) +{ + isc_result_t result; + dns_difftuple_t *tuple = NULL; + isc_region_t r; + unsigned char data[1] = { 0 }; /* The root domain, no bits. */ + dns_rdata_t rdata = DNS_RDATA_INIT; + + r.base = data; + r.length = sizeof(data); + dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r); + CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, + &rdata, &tuple)); + CHECK(do_one_tuple(&tuple, db, ver, diff)); + failure: + return (result); +} + +static isc_result_t +find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, + isc_mem_t *mctx, unsigned int maxkeys, + dst_key_t **keys, unsigned int *nkeys) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + const char *directory = dns_zone_getkeydirectory(zone); + CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); + CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), + directory, mctx, maxkeys, keys, nkeys)); + failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} + +/*% + * Add RRSIG records for an RRset, recording the change in "diff". + */ +static isc_result_t +add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, + dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, + isc_stdtime_t inception, isc_stdtime_t expire, + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t sig_rdata = DNS_RDATA_INIT; + isc_buffer_t buffer; + unsigned char data[1024]; /* XXX */ + unsigned int i, j; + isc_boolean_t added_sig = ISC_FALSE; + isc_mem_t *mctx = diff->mctx; + + dns_rdataset_init(&rdataset); + isc_buffer_init(&buffer, data, sizeof(data)); + + /* Get the rdataset to sign. */ + if (type == dns_rdatatype_nsec3) + CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); + else + CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); + CHECK(dns_db_findrdataset(db, node, ver, type, 0, + (isc_stdtime_t) 0, &rdataset, NULL)); + dns_db_detachnode(db, &node); + +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) +#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0) +#define ALG(x) dst_key_alg(x) + + /* + * If we are honoring KSK flags then we need to check that we + * have both KSK and non-KSK keys that are not revoked per + * algorithm. + */ + for (i = 0; i < nkeys; i++) { + isc_boolean_t both = ISC_FALSE; + + if (!dst_key_isprivate(keys[i])) + continue; + + if (check_ksk && !REVOKE(keys[i])) { + isc_boolean_t have_ksk, have_nonksk; + if (KSK(keys[i])) { + have_ksk = ISC_TRUE; + have_nonksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_nonksk = ISC_TRUE; + } + for (j = 0; j < nkeys; j++) { + if (j == i || ALG(keys[i]) != ALG(keys[j])) + continue; + if (REVOKE(keys[j])) + continue; + if (KSK(keys[j])) + have_ksk = ISC_TRUE; + else + have_nonksk = ISC_TRUE; + both = have_ksk && have_nonksk; + if (both) + break; + } + } + + if (both) { + if (type == dns_rdatatype_dnskey) { + if (!KSK(keys[i]) && keyset_kskonly) + continue; + } else if (KSK(keys[i])) + continue; + } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) + continue; + + /* Calculate the signature, creating a RRSIG RDATA. */ + CHECK(dns_dnssec_sign(name, &rdataset, keys[i], + &inception, &expire, + mctx, &buffer, &sig_rdata)); + + /* Update the database and journal with the RRSIG. */ + /* XXX inefficient - will cause dataset merging */ + CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name, + rdataset.ttl, &sig_rdata)); + dns_rdata_reset(&sig_rdata); + isc_buffer_init(&buffer, data, sizeof(data)); + added_sig = ISC_TRUE; + } + if (!added_sig) { + update_log(log, zone, ISC_LOG_ERROR, + "found no active private keys, " + "unable to generate any signatures"); + result = ISC_R_NOTFOUND; + } + + failure: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} + +/* + * Delete expired RRsigs and any RRsigs we are about to re-sign. + * See also zone.c:del_sigs(). + */ +static isc_result_t +del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys) +{ + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned int i; + dns_rdata_rrsig_t rrsig; + isc_boolean_t found; + + dns_rdataset_init(&rdataset); + + result = dns_db_findnode(db, name, ISC_FALSE, &node); + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + goto failure; + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, + dns_rdatatype_dnskey, (isc_stdtime_t) 0, + &rdataset, NULL); + dns_db_detachnode(db, &node); + + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &rrsig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + found = ISC_FALSE; + for (i = 0; i < nkeys; i++) { + if (rrsig.keyid == dst_key_id(keys[i])) { + found = ISC_TRUE; + if (!dst_key_isprivate(keys[i])) { + /* + * The re-signing code in zone.c + * will mark this as offline. + * Just skip the record for now. + */ + break; + } + result = update_one_rr(db, ver, diff, + DNS_DIFFOP_DEL, name, + rdataset.ttl, &rdata); + break; + } + } + /* + * If there is not a matching DNSKEY then delete the RRSIG. + */ + if (!found) + result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, + name, rdataset.ttl, &rdata); + dns_rdata_reset(&rdata); + if (result != ISC_R_SUCCESS) + break; + } + dns_rdataset_disassociate(&rdataset); + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; +failure: + if (node != NULL) + dns_db_detachnode(db, &node); + return (result); +} + +static isc_result_t +add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut, + dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, + isc_stdtime_t inception, isc_stdtime_t expire, + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) +{ + isc_result_t result; + dns_dbnode_t *node; + dns_rdatasetiter_t *iter; + + node = NULL; + result = dns_db_findnode(db, name, ISC_FALSE, &node); + if (result == ISC_R_NOTFOUND) + return (ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + return (result); + + iter = NULL; + result = dns_db_allrdatasets(db, node, ver, + (isc_stdtime_t) 0, &iter); + if (result != ISC_R_SUCCESS) + goto cleanup_node; + + for (result = dns_rdatasetiter_first(iter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(iter)) + { + dns_rdataset_t rdataset; + dns_rdatatype_t type; + isc_boolean_t flag; + + dns_rdataset_init(&rdataset); + dns_rdatasetiter_current(iter, &rdataset); + type = rdataset.type; + dns_rdataset_disassociate(&rdataset); + + /* + * We don't need to sign unsigned NSEC records at the cut + * as they are handled elsewhere. + */ + if ((type == dns_rdatatype_rrsig) || + (cut && type != dns_rdatatype_ds)) + continue; + result = rrset_exists(db, ver, name, dns_rdatatype_rrsig, + type, &flag); + if (result != ISC_R_SUCCESS) + goto cleanup_iterator; + if (flag) + continue;; + result = add_sigs(log, zone, db, ver, name, type, diff, + keys, nkeys, inception, expire, + check_ksk, keyset_kskonly); + if (result != ISC_R_SUCCESS) + goto cleanup_iterator; + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + + cleanup_iterator: + dns_rdatasetiter_destroy(&iter); + + cleanup_node: + dns_db_detachnode(db, &node); + + return (result); +} + +/*% + * Update RRSIG, NSEC and NSEC3 records affected by an update. The original + * update, including the SOA serial update but excluding the RRSIG & NSEC + * changes, is in "diff" and has already been applied to "newver" of "db". + * The database version prior to the update is "oldver". + * + * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver" + * and added (as a minimal diff) to "diff". + * + * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds. + */ +isc_result_t +dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *oldver, dns_dbversion_t *newver, + dns_diff_t *diff, isc_uint32_t sigvalidityinterval) +{ + isc_result_t result; + dns_difftuple_t *t; + dns_diff_t diffnames; + dns_diff_t affected; + dns_diff_t sig_diff; + dns_diff_t nsec_diff; + dns_diff_t nsec_mindiff; + isc_boolean_t flag, build_nsec, build_nsec3; + dst_key_t *zone_keys[DNS_MAXZONEKEYS]; + unsigned int nkeys = 0; + unsigned int i; + isc_stdtime_t now, inception, expire; + dns_ttl_t nsecttl; + dns_rdata_soa_t soa; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t rdataset; + dns_dbnode_t *node = NULL; + isc_boolean_t check_ksk, keyset_kskonly; + isc_boolean_t unsecure; + isc_boolean_t cut; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); + + dns_diff_init(diff->mctx, &diffnames); + dns_diff_init(diff->mctx, &affected); + + dns_diff_init(diff->mctx, &sig_diff); + sig_diff.resign = dns_zone_getsigresigninginterval(zone); + dns_diff_init(diff->mctx, &nsec_diff); + dns_diff_init(diff->mctx, &nsec_mindiff); + + result = find_zone_keys(zone, db, newver, diff->mctx, + DNS_MAXZONEKEYS, zone_keys, &nkeys); + if (result != ISC_R_SUCCESS) { + update_log(log, zone, ISC_LOG_ERROR, + "could not get zone keys for secure dynamic update"); + goto failure; + } + + isc_stdtime_get(&now); + inception = now - 3600; /* Allow for some clock skew. */ + expire = now + sigvalidityinterval; + + /* + * Do we look at the KSK flag on the DNSKEY to determining which + * keys sign which RRsets? First check the zone option then + * check the keys flags to make sure at least one has a ksk set + * and one doesn't. + */ + check_ksk = ISC_TF((dns_zone_getoptions(zone) & + DNS_ZONEOPT_UPDATECHECKKSK) != 0); + keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) & + DNS_ZONEOPT_DNSKEYKSKONLY) != 0); + + /* + * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field. + */ + CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); + dns_rdataset_init(&rdataset); + CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0, + (isc_stdtime_t) 0, &rdataset, NULL)); + CHECK(dns_rdataset_first(&rdataset)); + dns_rdataset_current(&rdataset, &rdata); + CHECK(dns_rdata_tostruct(&rdata, &soa, NULL)); + nsecttl = soa.minimum; + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + + /* + * Find all RRsets directly affected by the update, and + * update their RRSIGs. Also build a list of names affected + * by the update in "diffnames". + */ + CHECK(dns_diff_sort(diff, temp_order)); + + t = ISC_LIST_HEAD(diff->tuples); + while (t != NULL) { + dns_name_t *name = &t->name; + /* Now "name" is a new, unique name affected by the update. */ + + CHECK(namelist_append_name(&diffnames, name)); + + while (t != NULL && dns_name_equal(&t->name, name)) { + dns_rdatatype_t type; + type = t->rdata.type; + + /* + * Now "name" and "type" denote a new unique RRset + * affected by the update. + */ + + /* Don't sign RRSIGs. */ + if (type == dns_rdatatype_rrsig) + goto skip; + + /* + * Delete all old RRSIGs covering this type, since they + * are all invalid when the signed RRset has changed. + * We may not be able to recreate all of them - tough. + * Special case changes to the zone's DNSKEY records + * to support offline KSKs. + */ + if (type == dns_rdatatype_dnskey) + del_keysigs(db, newver, name, &sig_diff, + zone_keys, nkeys); + else + CHECK(delete_if(true_p, db, newver, name, + dns_rdatatype_rrsig, type, + NULL, &sig_diff)); + + /* + * If this RRset is still visible after the update, + * add a new signature for it. + */ + CHECK(rrset_visible(db, newver, name, type, &flag)); + if (flag) { + CHECK(add_sigs(log, zone, db, newver, name, + type, &sig_diff, zone_keys, + nkeys, inception, expire, + check_ksk, keyset_kskonly)); + } + skip: + /* Skip any other updates to the same RRset. */ + while (t != NULL && + dns_name_equal(&t->name, name) && + t->rdata.type == type) + { + t = ISC_LIST_NEXT(t, link); + } + } + } + update_log(log, zone, ISC_LOG_DEBUG(3), "updated data signatures"); + + /* Remove orphaned NSECs and RRSIG NSECs. */ + for (t = ISC_LIST_HEAD(diffnames.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag)); + if (! flag) { + CHECK(delete_if(true_p, db, newver, &t->name, + dns_rdatatype_any, 0, + NULL, &sig_diff)); + } + } + update_log(log, zone, ISC_LOG_DEBUG(3), + "removed any orphaned NSEC records"); + + /* + * See if we need to build NSEC or NSEC3 chains. + */ + CHECK(dns_private_chains(db, newver, privatetype, &build_nsec, + &build_nsec3)); + if (!build_nsec) + goto update_nsec3; + + update_log(log, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain"); + + /* + * When a name is created or deleted, its predecessor needs to + * have its NSEC updated. + */ + for (t = ISC_LIST_HEAD(diffnames.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + isc_boolean_t existed, exists; + dns_fixedname_t fixedname; + dns_name_t *prevname; + + dns_fixedname_init(&fixedname); + prevname = dns_fixedname_name(&fixedname); + + if (oldver != NULL) + CHECK(name_exists(db, oldver, &t->name, &existed)); + else + existed = ISC_FALSE; + CHECK(name_exists(db, newver, &t->name, &exists)); + if (exists == existed) + continue; + + /* + * Find the predecessor. + * When names become obscured or unobscured in this update + * transaction, we may find the wrong predecessor because + * the NSECs have not yet been updated to reflect the delegation + * change. This should not matter because in this case, + * the correct predecessor is either the delegation node or + * a newly unobscured node, and those nodes are on the + * "affected" list in any case. + */ + CHECK(next_active(log, zone, db, newver, + &t->name, prevname, ISC_FALSE)); + CHECK(namelist_append_name(&affected, prevname)); + } + + /* + * Find names potentially affected by delegation changes + * (obscured by adding an NS or DNAME, or unobscured by + * removing one). + */ + for (t = ISC_LIST_HEAD(diffnames.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + isc_boolean_t ns_existed, dname_existed; + isc_boolean_t ns_exists, dname_exists; + + if (oldver != NULL) + CHECK(rrset_exists(db, oldver, &t->name, + dns_rdatatype_ns, 0, &ns_existed)); + else + ns_existed = ISC_FALSE; + if (oldver != NULL) + CHECK(rrset_exists(db, oldver, &t->name, + dns_rdatatype_dname, 0, + &dname_existed)); + else + dname_existed = ISC_FALSE; + CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0, + &ns_exists)); + CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0, + &dname_exists)); + if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) + continue; + /* + * There was a delegation change. Mark all subdomains + * of t->name as potentially needing a NSEC update. + */ + CHECK(namelist_append_subdomain(db, &t->name, &affected)); + } + + ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link); + INSIST(ISC_LIST_EMPTY(diffnames.tuples)); + + CHECK(uniqify_name_list(&affected)); + + /* + * Determine which names should have NSECs, and delete/create + * NSECs to make it so. We don't know the final NSEC targets yet, + * so we just create placeholder NSECs with arbitrary contents + * to indicate that their respective owner names should be part of + * the NSEC chain. + */ + for (t = ISC_LIST_HEAD(affected.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + isc_boolean_t exists; + dns_name_t *name = &t->name; + + CHECK(name_exists(db, newver, name, &exists)); + if (! exists) + continue; + CHECK(is_active(db, newver, name, &flag, &cut, NULL)); + if (!flag) { + /* + * This name is obscured. Delete any + * existing NSEC record. + */ + CHECK(delete_if(true_p, db, newver, name, + dns_rdatatype_nsec, 0, + NULL, &nsec_diff)); + CHECK(delete_if(rrsig_p, db, newver, name, + dns_rdatatype_any, 0, NULL, diff)); + } else { + /* + * This name is not obscured. It needs to have a + * NSEC unless it is the at the origin, in which + * case it should already exist if there is a complete + * NSEC chain and if there isn't a complete NSEC chain + * we don't want to add one as that would signal that + * there is a complete NSEC chain. + */ + if (!dns_name_equal(name, dns_db_origin(db))) { + CHECK(rrset_exists(db, newver, name, + dns_rdatatype_nsec, 0, + &flag)); + if (!flag) + CHECK(add_placeholder_nsec(db, newver, + name, diff)); + } + CHECK(add_exposed_sigs(log, zone, db, newver, name, + cut, &sig_diff, zone_keys, nkeys, + inception, expire, check_ksk, + keyset_kskonly)); + } + } + + /* + * Now we know which names are part of the NSEC chain. + * Make them all point at their correct targets. + */ + for (t = ISC_LIST_HEAD(affected.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + CHECK(rrset_exists(db, newver, &t->name, + dns_rdatatype_nsec, 0, &flag)); + if (flag) { + /* + * There is a NSEC, but we don't know if it is correct. + * Delete it and create a correct one to be sure. + * If the update was unnecessary, the diff minimization + * will take care of eliminating it from the journal, + * IXFRs, etc. + * + * The RRSIG bit should always be set in the NSECs + * we generate, because they will all get RRSIG NSECs. + * (XXX what if the zone keys are missing?). + * Because the RRSIG NSECs have not necessarily been + * created yet, the correctness of the bit mask relies + * on the assumption that NSECs are only created if + * there is other data, and if there is other data, + * there are other RRSIGs. + */ + CHECK(add_nsec(log, zone, db, newver, &t->name, + nsecttl, &nsec_diff)); + } + } + + /* + * Minimize the set of NSEC updates so that we don't + * have to regenerate the RRSIG NSECs for NSECs that were + * replaced with identical ones. + */ + while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { + ISC_LIST_UNLINK(nsec_diff.tuples, t, link); + dns_diff_appendminimal(&nsec_mindiff, &t); + } + + update_log(log, zone, ISC_LOG_DEBUG(3), "signing rebuilt NSEC chain"); + + /* Update RRSIG NSECs. */ + for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + if (t->op == DNS_DIFFOP_DEL) { + CHECK(delete_if(true_p, db, newver, &t->name, + dns_rdatatype_rrsig, dns_rdatatype_nsec, + NULL, &sig_diff)); + } else if (t->op == DNS_DIFFOP_ADD) { + CHECK(add_sigs(log, zone, db, newver, &t->name, + dns_rdatatype_nsec, &sig_diff, + zone_keys, nkeys, inception, expire, + check_ksk, keyset_kskonly)); + } else { + INSIST(0); + } + } + + update_nsec3: + + /* Record our changes for the journal. */ + while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { + ISC_LIST_UNLINK(sig_diff.tuples, t, link); + dns_diff_appendminimal(diff, &t); + } + while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { + ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); + dns_diff_appendminimal(diff, &t); + } + + INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); + INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); + INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); + + if (!build_nsec3) { + update_log(log, zone, ISC_LOG_DEBUG(3), + "no NSEC3 chains to rebuild"); + goto failure; + } + + update_log(log, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains"); + + dns_diff_clear(&diffnames); + dns_diff_clear(&affected); + + CHECK(dns_diff_sort(diff, temp_order)); + + /* + * Find names potentially affected by delegation changes + * (obscured by adding an NS or DNAME, or unobscured by + * removing one). + */ + t = ISC_LIST_HEAD(diff->tuples); + while (t != NULL) { + dns_name_t *name = &t->name; + + isc_boolean_t ns_existed, dname_existed; + isc_boolean_t ns_exists, dname_exists; + isc_boolean_t exists, existed; + + if (t->rdata.type == dns_rdatatype_nsec || + t->rdata.type == dns_rdatatype_rrsig) { + t = ISC_LIST_NEXT(t, link); + continue; + } + + CHECK(namelist_append_name(&affected, name)); + + if (oldver != NULL) + CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns, + 0, &ns_existed)); + else + ns_existed = ISC_FALSE; + if (oldver != NULL) + CHECK(rrset_exists(db, oldver, name, + dns_rdatatype_dname, 0, + &dname_existed)); + else + dname_existed = ISC_FALSE; + CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0, + &ns_exists)); + CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0, + &dname_exists)); + + exists = ns_exists || dname_exists; + existed = ns_existed || dname_existed; + if (exists == existed) + goto nextname; + /* + * There was a delegation change. Mark all subdomains + * of t->name as potentially needing a NSEC3 update. + */ + CHECK(namelist_append_subdomain(db, name, &affected)); + + nextname: + while (t != NULL && dns_name_equal(&t->name, name)) + t = ISC_LIST_NEXT(t, link); + } + + for (t = ISC_LIST_HEAD(affected.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) { + dns_name_t *name = &t->name; + + unsecure = ISC_FALSE; /* Silence compiler warning. */ + CHECK(is_active(db, newver, name, &flag, &cut, &unsecure)); + + if (!flag) { + CHECK(delete_if(rrsig_p, db, newver, name, + dns_rdatatype_any, 0, NULL, diff)); + CHECK(dns_nsec3_delnsec3sx(db, newver, name, + privatetype, &nsec_diff)); + } else { + CHECK(add_exposed_sigs(log, zone, db, newver, name, + cut, &sig_diff, zone_keys, nkeys, + inception, expire, check_ksk, + keyset_kskonly)); + CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl, + unsecure, privatetype, + &nsec_diff)); + } + } + + /* + * Minimize the set of NSEC3 updates so that we don't + * have to regenerate the RRSIG NSEC3s for NSEC3s that were + * replaced with identical ones. + */ + while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { + ISC_LIST_UNLINK(nsec_diff.tuples, t, link); + dns_diff_appendminimal(&nsec_mindiff, &t); + } + + update_log(log, zone, ISC_LOG_DEBUG(3), + "signing rebuilt NSEC3 chain"); + + /* Update RRSIG NSEC3s. */ + for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); + t != NULL; + t = ISC_LIST_NEXT(t, link)) + { + if (t->op == DNS_DIFFOP_DEL) { + CHECK(delete_if(true_p, db, newver, &t->name, + dns_rdatatype_rrsig, + dns_rdatatype_nsec3, + NULL, &sig_diff)); + } else if (t->op == DNS_DIFFOP_ADD) { + CHECK(add_sigs(log, zone, db, newver, &t->name, + dns_rdatatype_nsec3, + &sig_diff, zone_keys, nkeys, + inception, expire, check_ksk, + keyset_kskonly)); + } else { + INSIST(0); + } + } + + /* Record our changes for the journal. */ + while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { + ISC_LIST_UNLINK(sig_diff.tuples, t, link); + dns_diff_appendminimal(diff, &t); + } + while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { + ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); + dns_diff_appendminimal(diff, &t); + } + + INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); + INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); + INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); + + failure: + dns_diff_clear(&sig_diff); + dns_diff_clear(&nsec_diff); + dns_diff_clear(&nsec_mindiff); + + dns_diff_clear(&affected); + dns_diff_clear(&diffnames); + + for (i = 0; i < nkeys; i++) + dst_key_free(&zone_keys[i]); + + return (result); +} + +isc_uint32_t +dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) { + isc_stdtime_t now; + + if (method == dns_updatemethod_unixtime) { + isc_stdtime_get(&now); + if (now != 0 && isc_serial_gt(now, serial)) + return (now); + } + + /* RFC1982 */ + serial = (serial + 1) & 0xFFFFFFFF; + if (serial == 0) + serial = 1; + + return (serial); +} diff --git a/contrib/bind9/lib/dns/validator.c b/contrib/bind9/lib/dns/validator.c index 3d7518a2bebf..8cf7f665ec88 100644 --- a/contrib/bind9/lib/dns/validator.c +++ b/contrib/bind9/lib/dns/validator.c @@ -1459,8 +1459,10 @@ isselfsigned(dns_validator_t *val) { if (result != ISC_R_SUCCESS) continue; - result = dns_dnssec_verify2(name, rdataset, dstkey, - ISC_TRUE, mctx, &sigrdata, + result = dns_dnssec_verify3(name, rdataset, dstkey, + ISC_TRUE, + val->view->maxbits, + mctx, &sigrdata, dns_fixedname_name(&fixed)); dst_key_free(&dstkey); if (result != ISC_R_SUCCESS) @@ -1497,8 +1499,9 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata, dns_fixedname_init(&fixed); wild = dns_fixedname_name(&fixed); again: - result = dns_dnssec_verify2(val->event->name, val->event->rdataset, - key, ignore, val->view->mctx, rdata, wild); + result = dns_dnssec_verify3(val->event->name, val->event->rdataset, + key, ignore, val->view->maxbits, + val->view->mctx, rdata, wild); if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) && val->view->acceptexpired) { diff --git a/contrib/bind9/lib/dns/view.c b/contrib/bind9/lib/dns/view.c index 5b6ad6587d20..9c1a201a8bd9 100644 --- a/contrib/bind9/lib/dns/view.c +++ b/contrib/bind9/lib/dns/view.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #ifdef BIND9 #include @@ -183,7 +184,6 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->answeracl_exclude = NULL; view->denyanswernames = NULL; view->answernames_exclude = NULL; - view->requestixfr = ISC_TRUE; view->provideixfr = ISC_TRUE; view->maxcachettl = 7 * 24 * 3600; view->maxncachettl = 3 * 3600; @@ -192,6 +192,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->flush = ISC_FALSE; view->dlv = NULL; view->maxudp = 0; + view->maxbits = 0; view->v4_aaaa = dns_v4_aaaa_ok; view->v4_aaaa_acl = NULL; ISC_LIST_INIT(view->rpz_zones); @@ -199,6 +200,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->rpz_break_dnssec = ISC_FALSE; dns_fixedname_init(&view->dlv_fixed); view->managed_keys = NULL; + view->redirect = NULL; #ifdef BIND9 view->new_zone_file = NULL; view->new_zone_config = NULL; @@ -435,6 +437,8 @@ destroy(dns_view_t *view) { } if (view->managed_keys != NULL) dns_zone_detach(&view->managed_keys); + if (view->redirect != NULL) + dns_zone_detach(&view->redirect); dns_view_setnewzones(view, ISC_FALSE, NULL, NULL); #endif dns_fwdtable_destroy(&view->fwdtable); @@ -486,7 +490,7 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { isc_refcount_decrement(&view->references, &refs); if (refs == 0) { #ifdef BIND9 - dns_zone_t *mkzone = NULL; + dns_zone_t *mkzone = NULL, *rdzone = NULL; #endif LOCK(&view->lock); @@ -509,6 +513,12 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { if (view->flush) dns_zone_flush(mkzone); } + if (view->redirect != NULL) { + rdzone = view->redirect; + view->redirect = NULL; + if (view->flush) + dns_zone_flush(rdzone); + } #endif done = all_done(view); UNLOCK(&view->lock); @@ -517,6 +527,9 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) { /* Need to detach zones outside view lock */ if (mkzone != NULL) dns_zone_detach(&mkzone); + + if (rdzone != NULL) + dns_zone_detach(&rdzone); #endif } @@ -661,7 +674,8 @@ req_shutdown(isc_task_t *task, isc_event_t *event) { isc_result_t dns_view_createresolver(dns_view_t *view, - isc_taskmgr_t *taskmgr, unsigned int ntasks, + isc_taskmgr_t *taskmgr, + unsigned int ntasks, unsigned int ndisp, isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, unsigned int options, @@ -682,7 +696,7 @@ dns_view_createresolver(dns_view_t *view, return (result); isc_task_setname(view->task, "view", view); - result = dns_resolver_create(view, taskmgr, ntasks, socketmgr, + result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr, timermgr, options, dispatchmgr, dispatchv4, dispatchv6, &view->resolver); @@ -714,8 +728,7 @@ dns_view_createresolver(dns_view_t *view, result = dns_requestmgr_create(view->mctx, timermgr, socketmgr, dns_resolver_taskmgr(view->resolver), dns_resolver_dispatchmgr(view->resolver), - dns_resolver_dispatchv4(view->resolver), - dns_resolver_dispatchv6(view->resolver), + dispatchv4, dispatchv6, &view->requestmgr); if (result != ISC_R_SUCCESS) { dns_adb_shutdown(view->adb); @@ -1434,6 +1447,7 @@ isc_result_t dns_view_load(dns_view_t *view, isc_boolean_t stop) { REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(view->zonetable != NULL); return (dns_zt_load(view->zonetable, stop)); } @@ -1442,9 +1456,20 @@ isc_result_t dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) { REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(view->zonetable != NULL); return (dns_zt_loadnew(view->zonetable, stop)); } + +isc_result_t +dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg) { + REQUIRE(DNS_VIEW_VALID(view)); + REQUIRE(view->zonetable != NULL); + + return (dns_zt_asyncload(view->zonetable, callback, arg)); +} + + #endif /* BIND9 */ isc_result_t @@ -1545,16 +1570,23 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) { isc_result_t dns_view_flushname(dns_view_t *view, dns_name_t *name) { + return (dns_view_flushnode(view, name, ISC_FALSE)); +} + +isc_result_t +dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) { REQUIRE(DNS_VIEW_VALID(view)); - if (view->adb != NULL) - dns_adb_flushname(view->adb, name); - if (view->cache == NULL) - return (ISC_R_SUCCESS); - if (view->resolver != NULL) - dns_resolver_flushbadcache(view->resolver, name); - return (dns_cache_flushname(view->cache, name)); + if (!tree) { + if (view->adb != NULL) + dns_adb_flushname(view->adb, name); + if (view->cache == NULL) + return (ISC_R_SUCCESS); + if (view->resolver != NULL) + dns_resolver_flushbadcache(view->resolver, name); + } + return (dns_cache_flushnode(view->cache, name, tree)); } isc_result_t diff --git a/contrib/bind9/lib/dns/xfrin.c b/contrib/bind9/lib/dns/xfrin.c index 3026af97cdb1..813f616e6fa0 100644 --- a/contrib/bind9/lib/dns/xfrin.c +++ b/contrib/bind9/lib/dns/xfrin.c @@ -360,7 +360,7 @@ ixfr_init(dns_xfrin_ctx_t *xfr) { journalfile = dns_zone_getjournal(xfr->zone); if (journalfile != NULL) CHECK(dns_journal_open(xfr->mctx, journalfile, - ISC_TRUE, &xfr->ixfr.journal)); + DNS_JOURNAL_CREATE, &xfr->ixfr.journal)); result = ISC_R_SUCCESS; failure: @@ -631,7 +631,8 @@ dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype, isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, isc_mem_t *mctx, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, - isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp) + isc_task_t *task, dns_xfrindone_t done, + dns_xfrin_ctx_t **xfrp) { dns_name_t *zonename = dns_zone_getorigin(zone); dns_xfrin_ctx_t *xfr = NULL; diff --git a/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c index c212bf68490b..10ba807c52f1 100644 --- a/contrib/bind9/lib/dns/zone.c +++ b/contrib/bind9/lib/dns/zone.c @@ -23,16 +23,18 @@ #include #include +#include #include +#include #include #include #include #include #include #include -#include #include #include +#include #include #include #include @@ -61,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -76,8 +79,10 @@ #include #include #include +#include #include #include +#include #include @@ -145,6 +150,7 @@ typedef ISC_LIST(dns_signing_t) dns_signinglist_t; typedef struct dns_nsec3chain dns_nsec3chain_t; typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t; typedef struct dns_keyfetch dns_keyfetch_t; +typedef struct dns_asyncload dns_asyncload_t; #define DNS_ZONE_CHECKLOCK #ifdef DNS_ZONE_CHECKLOCK @@ -217,6 +223,7 @@ struct dns_zone { isc_time_t signingtime; isc_time_t nsec3chaintime; isc_time_t refreshkeytime; + isc_uint32_t refreshkeyinterval; isc_uint32_t refreshkeycount; isc_uint32_t refresh; isc_uint32_t retry; @@ -239,9 +246,11 @@ struct dns_zone { isc_sockaddr_t masteraddr; dns_notifytype_t notifytype; isc_sockaddr_t *notify; + dns_name_t **notifykeynames; unsigned int notifycnt; isc_sockaddr_t notifyfrom; isc_task_t *task; + isc_task_t *loadtask; isc_sockaddr_t notifysrc4; isc_sockaddr_t notifysrc6; isc_sockaddr_t xfrsource4; @@ -297,8 +306,10 @@ struct dns_zone { * Optional per-zone statistics counters. Counted outside of this * module. */ + dns_zonestat_level_t statlevel; isc_boolean_t requeststats_on; isc_stats_t *requeststats; + dns_stats_t *rcvquerystats; isc_uint32_t notifydelay; dns_isselffunc_t isself; void *isselfarg; @@ -339,10 +350,26 @@ struct dns_zone { */ isc_boolean_t is_rpz; + /*% + * Serial number update method. + */ + dns_updatemethod_t updatemethod; + + /*% + * whether ixfr is requested + */ + isc_boolean_t requestixfr; + /*% * Outstanding forwarded UPDATE requests. */ dns_forwardlist_t forwards; + + dns_zone_t *raw; + dns_zone_t *secure; + + isc_boolean_t sourceserialset; + isc_uint32_t sourceserial; }; typedef struct { @@ -403,8 +430,9 @@ typedef struct { #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */ #define DNS_ZONEFLG_THAW 0x08000000U -/* #define DNS_ZONEFLG_XXXXX 0x10000000U XXXMPA unused. */ +#define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */ #define DNS_ZONEFLG_NODELAY 0x20000000U +#define DNS_ZONEFLG_SENDSECURE 0x40000000U #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0) @@ -437,7 +465,9 @@ struct dns_zonemgr { isc_timermgr_t * timermgr; isc_socketmgr_t * socketmgr; isc_taskpool_t * zonetasks; + isc_taskpool_t * loadtasks; isc_task_t * task; + isc_pool_t * mctxpool; isc_ratelimiter_t * rl; isc_rwlock_t rwlock; isc_mutex_t iolock; @@ -476,6 +506,7 @@ struct dns_notify { dns_request_t *request; dns_name_t ns; isc_sockaddr_t dst; + dns_tsigkey_t *key; ISC_LINK(dns_notify_t) link; }; @@ -594,6 +625,15 @@ struct dns_keyfetch { dns_fetch_t *fetch; }; +/*% + * Hold state for an asynchronous load + */ +struct dns_asyncload { + dns_zone_t *zone; + dns_zt_zoneloaded_t loaded; + void *loaded_arg; +}; + #define HOUR 3600 #define DAY (24*HOUR) #define MONTH (30*DAY) @@ -632,6 +672,9 @@ static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length); static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length); static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length); static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length); +static isc_result_t zone_send_secureserial(dns_zone_t *zone, + isc_boolean_t secure_locked, + isc_uint32_t serial); #if 0 /* ondestroy example */ @@ -688,6 +731,8 @@ static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver, static void zone_rekey(dns_zone_t *zone); static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys); +static isc_result_t zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, + dns_db_t *db); #define ENTER zone_debuglog(zone, me, 1, "enter") @@ -798,6 +843,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { isc_time_settoepoch(&zone->signingtime); isc_time_settoepoch(&zone->nsec3chaintime); isc_time_settoepoch(&zone->refreshkeytime); + zone->refreshkeyinterval = 0; zone->refreshkeycount = 0; zone->refresh = DNS_ZONE_DEFAULTREFRESH; zone->retry = DNS_ZONE_DEFAULTRETRY; @@ -813,9 +859,11 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->masterscnt = 0; zone->curmaster = 0; zone->notify = NULL; + zone->notifykeynames = NULL; zone->notifytype = dns_notifytype_yes; zone->notifycnt = 0; zone->task = NULL; + zone->loadtask = NULL; zone->update_acl = NULL; zone->forward_acl = NULL; zone->notify_acl = NULL; @@ -857,7 +905,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->statelist = NULL; zone->stats = NULL; zone->requeststats_on = ISC_FALSE; + zone->statlevel = dns_zonestat_none; zone->requeststats = NULL; + zone->rcvquerystats = NULL; zone->notifydelay = 5; zone->isself = NULL; zone->isselfarg = NULL; @@ -869,6 +919,10 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->added = ISC_FALSE; zone->is_rpz = ISC_FALSE; ISC_LIST_INIT(zone->forwards); + zone->raw = NULL; + zone->secure = NULL; + zone->sourceserial = 0; + zone->sourceserialset = ISC_FALSE; zone->magic = ZONE_MAGIC; @@ -925,6 +979,8 @@ zone_free(dns_zone_t *zone) { if (zone->task != NULL) isc_task_detach(&zone->task); + if (zone->loadtask != NULL) + isc_task_detach(&zone->loadtask); if (zone->zmgr != NULL) dns_zonemgr_releasezone(zone->zmgr, zone); @@ -959,6 +1015,8 @@ zone_free(dns_zone_t *zone) { isc_stats_detach(&zone->stats); if (zone->requeststats != NULL) isc_stats_detach(&zone->requeststats); + if(zone->rcvquerystats != NULL ) + dns_stats_detach(&zone->rcvquerystats); if (zone->db != NULL) zone_detachdb(zone); if (zone->acache != NULL) @@ -1004,6 +1062,30 @@ zone_free(dns_zone_t *zone) { isc_mem_detach(&mctx); } +/* + * Returns ISC_TRUE iff this the signed side of an inline-signing zone. + * Caller should hold zone lock. + */ +static inline isc_boolean_t +inline_secure(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + if (zone->raw != NULL) + return (ISC_TRUE); + return (ISC_FALSE); +} + +/* + * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone + * Caller should hold zone lock. + */ +static inline isc_boolean_t +inline_raw(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + if (zone->secure != NULL) + return (ISC_TRUE); + return (ISC_FALSE); +} + /* * Single shot. */ @@ -1032,6 +1114,8 @@ dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) { zone_rdclass_tostr(zone, namebuf, sizeof namebuf); zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf); + if (inline_secure(zone)) + dns_zone_setclass(zone->raw, rdclass); UNLOCK_ZONE(zone); } @@ -1092,6 +1176,7 @@ dns_zone_getserial(dns_zone_t *zone) { */ void dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) { + char namebuf[1024]; REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(type != dns_zone_none); @@ -1102,6 +1187,12 @@ dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) { LOCK_ZONE(zone); REQUIRE(zone->type == dns_zone_none || zone->type == type); zone->type = type; + + if (zone->strnamerd != NULL) + isc_mem_free(zone->mctx, zone->strnamerd); + + zone_namerd_tostr(zone, namebuf, sizeof namebuf); + zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf); UNLOCK_ZONE(zone); } @@ -1220,10 +1311,12 @@ dns_zone_setview(dns_zone_t *zone, dns_view_t *view) { zone_viewname_tostr(zone, namebuf, sizeof namebuf); zone->strviewname = isc_mem_strdup(zone->mctx, namebuf); + if (inline_secure(zone)) + dns_zone_setview(zone->raw, view); + UNLOCK_ZONE(zone); } - dns_view_t * dns_zone_getview(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); @@ -1257,6 +1350,8 @@ dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) { zone_name_tostr(zone, namebuf, sizeof namebuf); zone->strname = isc_mem_strdup(zone->mctx, namebuf); + if (result == ISC_R_SUCCESS && inline_secure(zone)) + result = dns_zone_setorigin(zone->raw, origin); UNLOCK_ZONE(zone); return (result); } @@ -1394,16 +1489,24 @@ dns_zone_getjournal(dns_zone_t *zone) { * allow dynamic updates either by having an update policy ("ssutable") * or an "allow-update" ACL with a value other than exactly "{ none; }". */ -static isc_boolean_t -zone_isdynamic(dns_zone_t *zone) { +isc_boolean_t +dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) { REQUIRE(DNS_ZONE_VALID(zone)); - return (ISC_TF(zone->type == dns_zone_slave || - zone->type == dns_zone_stub || - zone->type == dns_zone_key || - (!zone->update_disabled && zone->ssutable != NULL) || - (!zone->update_disabled && zone->update_acl != NULL && - !dns_acl_isnone(zone->update_acl)))); + if (zone->type == dns_zone_slave || zone->type == dns_zone_stub || + zone->type == dns_zone_key || + (zone->type == dns_zone_redirect && zone->masters != NULL)) + return (ISC_TRUE); + + /* If !ignore_freeze, we need check whether updates are disabled. */ + if (zone->type == dns_zone_master && + (!zone->update_disabled || ignore_freeze) && + ((zone->ssutable != NULL) || + (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)))) + return (ISC_TRUE); + + return (ISC_FALSE); + } /* @@ -1437,11 +1540,21 @@ zone_load(dns_zone_t *zone, unsigned int flags) { isc_time_t now; isc_time_t loadtime, filetime; dns_db_t *db = NULL; - isc_boolean_t rbt; + isc_boolean_t rbt, hasraw; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); + hasraw = inline_secure(zone); + if (hasraw) { + result = zone_load(zone->raw, flags); + if (result != ISC_R_SUCCESS) { + UNLOCK_ZONE(zone); + return(result); + } + LOCK_ZONE(zone->raw); + } + TIME_NOW(&now); INSIST(zone->type != dns_zone_none); @@ -1453,7 +1566,6 @@ zone_load(dns_zone_t *zone, unsigned int flags) { goto cleanup; } - INSIST(zone->db_argc >= 1); rbt = strcmp(zone->db_argv[0], "rbt") == 0 || @@ -1467,7 +1579,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) { goto cleanup; } - if (zone->db != NULL && zone_isdynamic(zone)) { + if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) { /* * This is a slave, stub, or dynamically updated * zone being reloaded. Do nothing - the database @@ -1531,7 +1643,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) { goto cleanup; } - if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) && + if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub || + (zone->type == dns_zone_redirect && zone->masters != NULL)) && rbt) { if (zone->masterfile == NULL || !isc_file_exists(zone->masterfile)) { @@ -1569,7 +1682,9 @@ zone_load(dns_zone_t *zone, unsigned int flags) { result = zone_startload(db, zone, loadtime); } else { result = DNS_R_NOMASTERFILE; - if (zone->type == dns_zone_master) { + if (zone->type == dns_zone_master || + (zone->type == dns_zone_redirect && + zone->masters == NULL)) { dns_zone_log(zone, ISC_LOG_ERROR, "loading zone: " "no master file configured"); @@ -1590,6 +1705,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) { result = zone_postload(zone, db, loadtime, result); cleanup: + if (hasraw) + UNLOCK_ZONE(zone->raw); UNLOCK_ZONE(zone); if (db != NULL) dns_db_detach(&db); @@ -1606,17 +1723,100 @@ dns_zone_loadnew(dns_zone_t *zone) { return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT)); } +static void +zone_asyncload(isc_task_t *task, isc_event_t *event) { + dns_asyncload_t *asl = event->ev_arg; + dns_zone_t *zone = asl->zone; + isc_result_t result = ISC_R_SUCCESS; + + UNUSED(task); + + REQUIRE(DNS_ZONE_VALID(zone)); + + if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) + result = ISC_R_CANCELED; + isc_event_free(&event); + if (result == ISC_R_CANCELED || + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) + goto cleanup; + + zone_load(zone, 0); + + LOCK_ZONE(zone); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING); + UNLOCK_ZONE(zone); + + /* Inform the zone table we've finished loading */ + if (asl->loaded != NULL) + (asl->loaded)(asl->loaded_arg, zone, task); + + cleanup: + isc_mem_put(zone->mctx, asl, sizeof (*asl)); + dns_zone_idetach(&zone); +} + +isc_result_t +dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) { + isc_event_t *e; + dns_asyncload_t *asl = NULL; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(DNS_ZONE_VALID(zone)); + + if (zone->zmgr == NULL) + return (ISC_R_FAILURE); + + asl = isc_mem_get(zone->mctx, sizeof (*asl)); + if (asl == NULL) + CHECK(ISC_R_NOMEMORY); + + asl->zone = NULL; + asl->loaded = done; + asl->loaded_arg = arg; + + e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, + DNS_EVENT_ZONELOAD, + zone_asyncload, asl, + sizeof(isc_event_t)); + if (e == NULL) + CHECK(ISC_R_NOMEMORY); + + LOCK_ZONE(zone); + zone_iattach(zone, &asl->zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING); + isc_task_send(zone->loadtask, &e); + UNLOCK_ZONE(zone); + + return (ISC_R_SUCCESS); + + failure: + if (asl != NULL) + isc_mem_put(zone->mctx, asl, sizeof (*asl)); + return (result); +} + +isc_boolean_t +dns__zone_loadpending(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + + return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))); +} + isc_result_t dns_zone_loadandthaw(dns_zone_t *zone) { isc_result_t result; - result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + if (inline_raw(zone)) + result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW); + else + result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + switch (result) { case DNS_R_CONTINUE: /* Deferred thaw. */ break; - case ISC_R_SUCCESS: case DNS_R_UPTODATE: + case ISC_R_SUCCESS: case DNS_R_SEENINCLUDE: zone->update_disabled = ISC_FALSE; break; @@ -1635,7 +1835,8 @@ get_master_options(dns_zone_t *zone) { unsigned int options; options = DNS_MASTER_ZONE; - if (zone->type == dns_zone_slave) + if (zone->type == dns_zone_slave || + (zone->type == dns_zone_redirect && zone->masters == NULL)) options |= DNS_MASTER_SLAVE; if (zone->type == dns_zone_key) options |= DNS_MASTER_KEY; @@ -1653,9 +1854,9 @@ get_master_options(dns_zone_t *zone) { options |= DNS_MASTER_CHECKMXFAIL; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) options |= DNS_MASTER_CHECKWILDCARD; - if (zone->type == dns_zone_master && + if (inline_secure(zone) || (zone->type == dns_zone_master && ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) || - zone->ssutable != NULL)) + zone->ssutable != NULL))) options |= DNS_MASTER_RESIGN; return (options); } @@ -1679,8 +1880,7 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) { result = dns_master_loadfileinc3(load->zone->masterfile, dns_db_origin(load->db), dns_db_origin(load->db), - load->zone->rdclass, - options, + load->zone->rdclass, options, load->zone->sigresigninginterval, &load->callbacks, task, zone_loaddone, load, @@ -1695,12 +1895,30 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) { zone_loaddone(load, result); } +static void +get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) { + isc_result_t result; + unsigned int soacount; + + LOCK(&raw->lock); + if (raw->db != NULL) { + result = zone_get_from_db(raw, raw->db, NULL, &soacount, + &rawdata->sourceserial, + NULL, NULL, NULL, NULL, + NULL); + if (result == ISC_R_SUCCESS && soacount > 0U) + rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET; + } + UNLOCK(&raw->lock); +} + static void zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { const char me[] = "zone_gotwritehandle"; dns_zone_t *zone = event->ev_arg; isc_result_t result = ISC_R_SUCCESS; dns_dbversion_t *version = NULL; + dns_masterrawheader_t rawdata; REQUIRE(DNS_ZONE_VALID(zone)); INSIST(task == zone->task); @@ -1716,11 +1934,14 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); if (zone->db != NULL) { dns_db_currentversion(zone->db, &version); - result = dns_master_dumpinc2(zone->mctx, zone->db, version, + dns_master_initrawheader(&rawdata); + if (inline_secure(zone)) + get_raw_serial(zone->raw, &rawdata); + result = dns_master_dumpinc3(zone->mctx, zone->db, version, &dns_master_style_default, zone->masterfile, zone->task, dump_done, zone, &zone->dctx, - zone->masterformat); + zone->masterformat, &rawdata); dns_db_closeversion(zone->db, &version, ISC_FALSE); } else result = ISC_R_CANCELED; @@ -1734,6 +1955,31 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { dump_done(zone, result); } +/* + * Save the raw serial number for inline-signing zones. + * (XXX: Other information from the header will be used + * for other purposes in the future, but for now this is + * all we're interested in.) + */ +static void +zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) { + if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) + return; + + zone->sourceserial = header->sourceserial; + zone->sourceserialset = ISC_TRUE; +} + +void +dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) { + if (zone == NULL) + return; + + LOCK_ZONE(zone); + zone_setrawdata(zone, header); + UNLOCK_ZONE(zone); +} + static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { dns_load_t *load; @@ -1753,7 +1999,7 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) options |= DNS_MASTER_MANYERRORS; - if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) { + if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) { load = isc_mem_get(zone->mctx, sizeof(*load)); if (load == NULL) return (ISC_R_NOMEMORY); @@ -1768,11 +2014,13 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { zone_iattach(zone, &load->zone); dns_db_attach(db, &load->db); dns_rdatacallbacks_init(&load->callbacks); + load->callbacks.rawdata = zone_setrawdata; + zone_iattach(zone, &load->callbacks.zone); result = dns_db_beginload(db, &load->callbacks.add, &load->callbacks.add_private); if (result != ISC_R_SUCCESS) goto cleanup; - result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task, + result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask, zone_gotreadhandle, load, &zone->readio); if (result != ISC_R_SUCCESS) { @@ -1789,18 +2037,24 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); + callbacks.rawdata = zone_setrawdata; + zone_iattach(zone, &callbacks.zone); result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + zone_idetach(&callbacks.zone); return (result); - result = dns_master_loadfile3(zone->masterfile, &zone->origin, - &zone->origin, zone->rdclass, - options, zone->sigresigninginterval, + } + result = dns_master_loadfile3(zone->masterfile, + &zone->origin, &zone->origin, + zone->rdclass, options, + zone->sigresigninginterval, &callbacks, zone->mctx, zone->masterformat); tresult = dns_db_endload(db, &callbacks.add_private); if (result == ISC_R_SUCCESS) result = tresult; + zone_idetach(&callbacks.zone); } return (result); @@ -1809,6 +2063,7 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { load->magic = 0; dns_db_detach(&load->db); zone_idetach(&load->zone); + zone_idetach(&load->callbacks.zone); isc_mem_detach(&load->mctx); isc_mem_put(zone->mctx, load, sizeof(*load)); return (result); @@ -2531,13 +2786,22 @@ resume_signingwithkey(dns_zone_t *zone) { static isc_result_t zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { dns_nsec3chain_t *nsec3chain, *current; + dns_dbversion_t *version = NULL; + isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE; isc_result_t result; isc_time_t now; unsigned int options = 0; char saltbuf[255*2+1]; - char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")]; + char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")]; int i; + dns_db_currentversion(zone->db, &version); + result = dns_nsec_nseconly(zone->db, version, &nseconly); + nsec3ok = (result == ISC_R_SUCCESS && !nseconly); + dns_db_closeversion(zone->db, &version, ISC_FALSE); + if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) + return (ISC_R_SUCCESS); + nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain); if (nsec3chain == NULL) return (ISC_R_NOMEMORY); @@ -2564,6 +2828,12 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { flags[0] = '\0'; if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) strlcat(flags, "REMOVE", sizeof(flags)); + if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) { + if (flags[0] == '\0') + strlcpy(flags, "INITIAL", sizeof(flags)); + else + strlcat(flags, "|INITIAL", sizeof(flags)); + } if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) { if (flags[0] == '\0') strlcpy(flags, "CREATE", sizeof(flags)); @@ -2592,6 +2862,7 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { "zone_addnsec3chain(%u,%s,%u,%s)", nsec3param->hash, flags, nsec3param->iterations, saltbuf); + for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL; current = ISC_LIST_NEXT(current, link)) { @@ -2644,6 +2915,7 @@ resume_addnsec3chain(dns_zone_t *zone) { dns_rdataset_t rdataset; isc_result_t result; dns_rdata_nsec3param_t nsec3param; + isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE; if (zone->privatetype == 0) return; @@ -2653,6 +2925,10 @@ resume_addnsec3chain(dns_zone_t *zone) { goto cleanup; dns_db_currentversion(zone->db, &version); + + result = dns_nsec_nseconly(zone->db, version, &nseconly); + nsec3ok = (result == ISC_R_SUCCESS && !nseconly); + dns_rdataset_init(&rdataset); result = dns_db_findrdataset(zone->db, node, version, zone->privatetype, dns_rdatatype_none, @@ -2676,8 +2952,9 @@ resume_addnsec3chain(dns_zone_t *zone) { continue; result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 || - (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) { + if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) || + ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok)) + { result = zone_addnsec3chain(zone, &nsec3param); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -2727,7 +3004,7 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t dynamic = (zone->type == dns_zone_master) ? - zone_isdynamic(zone) : ISC_FALSE; + dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE; dns_rdataset_init(&rdataset); result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node); @@ -3149,8 +3426,8 @@ update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, } static isc_result_t -increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, - dns_diff_t *diff, isc_mem_t *mctx) { +update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, + isc_mem_t *mctx, dns_updatemethod_t method) { dns_difftuple_t *deltuple = NULL; dns_difftuple_t *addtuple = NULL; isc_uint32_t serial; @@ -3161,12 +3438,7 @@ increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, addtuple->op = DNS_DIFFOP_ADD; serial = dns_soa_getserial(&addtuple->rdata); - - /* RFC1982 */ - serial = (serial + 1) & 0xFFFFFFFF; - if (serial == 0) - serial = 1; - + serial = dns_update_soaserial(serial, method); dns_soa_setserial(serial, &addtuple->rdata); CHECK(do_one_tuple(&deltuple, db, ver, diff)); CHECK(do_one_tuple(&addtuple, db, ver, diff)); @@ -3184,17 +3456,20 @@ increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, * Write all transactions in 'diff' to the zone journal file. */ static isc_result_t -zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) { +zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial, + const char *caller) +{ const char me[] = "zone_journal"; const char *journalfile; isc_result_t result = ISC_R_SUCCESS; dns_journal_t *journal = NULL; + unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE; ENTER; journalfile = dns_zone_getjournal(zone); if (journalfile != NULL) { - result = dns_journal_open(zone->mctx, journalfile, - ISC_TRUE, &journal); + result = dns_journal_open(zone->mctx, journalfile, mode, + &journal); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "%s:dns_journal_open -> %s", @@ -3202,15 +3477,18 @@ zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) { return (result); } + if (sourceserial != NULL) + dns_journal_set_sourceserial(journal, *sourceserial); + result = dns_journal_write_transaction(journal, diff); - dns_journal_destroy(&journal); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "%s:dns_journal_write_transaction -> %s", caller, dns_result_totext(result)); - return (result); } + dns_journal_destroy(&journal); } + return (result); } @@ -3391,8 +3669,9 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { if (changed) { /* Write changes to journal file. */ - CHECK(increment_soa_serial(db, ver, &diff, zone->mctx)); - CHECK(zone_journal(zone, &diff, "sync_keyzone")); + CHECK(update_soa_serial(db, ver, &diff, zone->mctx, + zone->updatemethod)); + CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone")); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); zone_needdump(zone, 30); @@ -3418,6 +3697,73 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { return (result); } +isc_result_t +dns_zone_synckeyzone(dns_zone_t *zone) { + isc_result_t result; + dns_db_t *db = NULL; + + if (zone->type != dns_zone_key) + return (DNS_R_BADZONE); + + CHECK(dns_zone_getdb(zone, &db)); + + LOCK_ZONE(zone); + result = sync_keyzone(zone, db); + UNLOCK_ZONE(zone); + + failure: + if (db != NULL) + dns_db_detach(&db); + return (result); +} + +static void +maybe_send_secure(dns_zone_t *zone) { + isc_result_t result; + + /* + * We've finished loading, or else failed to load, an inline-signing + * 'secure' zone. We now need information about the status of the + * 'raw' zone. If we failed to load, then we need it to send a + * copy of its database; if we succeeded, we need it to send its + * serial number so that we can sync with it. If it has not yet + * loaded, we set a flag so that it will send the necessary + * information when it has finished loading. + */ + if (zone->raw->db != NULL) { + if (zone->db != NULL) { + isc_uint32_t serial; + unsigned int soacount; + + result = zone_get_from_db(zone->raw, zone->raw->db, + NULL, &soacount, &serial, NULL, + NULL, NULL, NULL, NULL); + if (result == ISC_R_SUCCESS && soacount > 0U) + zone_send_secureserial(zone->raw, ISC_TRUE, serial); + } else + zone_send_securedb(zone->raw, ISC_TRUE, zone->raw->db); + + } else + DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE); +} + +static isc_boolean_t +zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) { + isc_result_t result; + isc_boolean_t answer = ISC_FALSE; + dns_diff_t diff; + + dns_diff_init(mctx, &diff); + result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL); + if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) + answer = ISC_TRUE; + dns_diff_clear(&diff); + return (answer); +} + +/* + * The zone is presumed to be locked. + */ static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_result_t result) @@ -3441,7 +3787,9 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, */ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { if (zone->type == dns_zone_slave || - zone->type == dns_zone_stub) { + zone->type == dns_zone_stub || + (zone->type == dns_zone_redirect && + zone->masters == NULL)) { if (result == ISC_R_FILENOTFOUND) dns_zone_log(zone, ISC_LOG_DEBUG(1), "no master file"); @@ -3451,6 +3799,12 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, "failed: %s", zone->masterfile, dns_result_totext(result)); + } else if (zone->type == dns_zone_master && + inline_secure(zone) && result == ISC_R_FILENOTFOUND) + { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "no master file, requesting db"); + maybe_send_secure(zone); } else { int level = ISC_LOG_ERROR; if (zone->type == dns_zone_key && @@ -3510,6 +3864,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, "journal rollforward failed: %s", dns_result_totext(result)); goto cleanup; + + } if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -3525,7 +3881,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, needdump = ISC_TRUE; } - dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity"); /* * Obtain ns, soa and cname counts for top of zone. */ @@ -3538,6 +3893,46 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, "could not find NS and/or SOA records"); } + /* + * Check to make sure the journal is up to date, and remove the + * journal file if it isn't, as we wouldn't be able to apply + * updates otherwise. + */ + if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) && + ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { + isc_uint32_t jserial; + dns_journal_t *journal = NULL; + + result = dns_journal_open(zone->mctx, zone->journal, + DNS_JOURNAL_READ, &journal); + if (result == ISC_R_SUCCESS) { + jserial = dns_journal_last_serial(journal); + dns_journal_destroy(&journal); + } else { + jserial = serial; + result = ISC_R_SUCCESS; + } + + if (jserial != serial) { + dns_zone_log(zone, ISC_LOG_INFO, + "journal file is out of date: " + "removing journal file"); + if (remove(zone->journal) < 0 && errno != ENOENT) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_ZONE, + ISC_LOG_WARNING, + "unable to remove journal " + "'%s': '%s'", + zone->journal, strbuf); + } + } + } + + dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity"); + /* * Master / Slave / Stub zones require both NS and SOA records at * the top of the zone. @@ -3548,6 +3943,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, case dns_zone_master: case dns_zone_slave: case dns_zone_stub: + case dns_zone_redirect: if (soacount != 1) { dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records", soacount); @@ -3564,7 +3960,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, result = DNS_R_BADZONE; goto cleanup; } - if (zone->type != dns_zone_stub) { + if (zone->type != dns_zone_stub && + zone->type != dns_zone_redirect) { result = check_nsec3param(zone, db); if (result != ISC_R_SUCCESS) goto cleanup; @@ -3575,7 +3972,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, result = DNS_R_BADZONE; goto cleanup; } - if (zone->type == dns_zone_master && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) && !zone_check_dup(zone, db)) { @@ -3602,6 +3998,14 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, INSIST(zone->type == dns_zone_master); + if (serial == oldserial && + zone_unchanged(zone->db, db, zone->mctx)) { + dns_zone_log(zone, ISC_LOG_INFO, + "ixfr-from-differences: " + "unchanged"); + return(ISC_R_SUCCESS); + } + serialmin = (oldserial + 1) & 0xffffffffU; serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; @@ -3644,7 +4048,9 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); if (zone->type == dns_zone_slave || - zone->type == dns_zone_stub) { + zone->type == dns_zone_stub || + (zone->type == dns_zone_redirect && + zone->masters != NULL)) { isc_time_t t; isc_uint32_t delay; @@ -3666,6 +4072,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, &zone->expiretime) >= 0) zone->refreshtime = now; } + break; case dns_zone_key: @@ -3717,8 +4124,24 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) && + inline_raw(zone)) + { + if (zone->secure->db == NULL) + zone_send_securedb(zone, ISC_FALSE, db); + else + zone_send_secureserial(zone, ISC_FALSE, serial); + } } + /* + * Finished loading inline-signing zone; need to get status + * from the raw side now. + */ + if (zone->type == dns_zone_master && inline_secure(zone)) + maybe_send_secure(zone); + + result = ISC_R_SUCCESS; if (needdump) { @@ -3736,7 +4159,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, } if (zone->type == dns_zone_master && - zone_isdynamic(zone) && + !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) && + dns_zone_isdynamic(zone, ISC_FALSE) && dns_db_issecure(db)) { dns_name_t *name; dns_fixedname_t fixed; @@ -3775,12 +4199,14 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, dns_db_issecure(db) ? " (DNSSEC signed)" : ""); zone->loadtime = loadtime; + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING); return (result); cleanup: if (zone->type == dns_zone_slave || zone->type == dns_zone_stub || - zone->type == dns_zone_key) { + zone->type == dns_zone_key || + (zone->type == dns_zone_redirect && zone->masters != NULL)) { if (zone->journal != NULL) zone_saveunique(zone, zone->journal, "jn-XXXXXXXX"); if (zone->masterfile != NULL) @@ -3791,8 +4217,15 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, if (zone->task != NULL) zone_settimer(zone, &now); result = ISC_R_SUCCESS; - } else if (zone->type == dns_zone_master) - dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors."); + } else if (zone->type == dns_zone_master || + zone->type == dns_zone_redirect) { + if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) + dns_zone_log(zone, ISC_LOG_ERROR, + "not loaded due to errors."); + else if (zone->type == dns_zone_master) + result = ISC_R_SUCCESS; + } + return (result); } @@ -4087,6 +4520,8 @@ dns_zone_attach(dns_zone_t *source, dns_zone_t **target) { void dns_zone_detach(dns_zone_t **zonep) { dns_zone_t *zone; + dns_zone_t *raw = NULL; + dns_zone_t *secure = NULL; unsigned int refs; isc_boolean_t free_now = ISC_FALSE; @@ -4124,12 +4559,21 @@ dns_zone_detach(dns_zone_t **zonep) { */ INSIST(zone->view == NULL); free_now = ISC_TRUE; + raw = zone->raw; + zone->raw = NULL; + secure = zone->secure; + zone->secure = NULL; } UNLOCK_ZONE(zone); } *zonep = NULL; - if (free_now) + if (free_now) { + if (raw != NULL) + dns_zone_detach(&raw); + if (secure != NULL) + dns_zone_idetach(&secure); zone_free(zone); + } } void @@ -4141,26 +4585,6 @@ dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) { UNLOCK_ZONE(source); } -isc_result_t -dns_zone_synckeyzone(dns_zone_t *zone) { - isc_result_t result; - dns_db_t *db = NULL; - - if (zone->type != dns_zone_key) - return (DNS_R_BADZONE); - - CHECK(dns_zone_getdb(zone, &db)); - - LOCK_ZONE(zone); - result = sync_keyzone(zone, db); - UNLOCK_ZONE(zone); - - failure: - if (db != NULL) - dns_db_detach(&db); - return (result); -} - static void zone_iattach(dns_zone_t *source, dns_zone_t **target) { @@ -4385,48 +4809,8 @@ dns_zone_getnotifysrc6(dns_zone_t *zone) { return (&zone->notifysrc6); } -isc_result_t -dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, - isc_uint32_t count) -{ - isc_sockaddr_t *new; - - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(count == 0 || notify != NULL); - - LOCK_ZONE(zone); - if (zone->notify != NULL) { - isc_mem_put(zone->mctx, zone->notify, - zone->notifycnt * sizeof(*new)); - zone->notify = NULL; - zone->notifycnt = 0; - } - if (count != 0) { - new = isc_mem_get(zone->mctx, count * sizeof(*new)); - if (new == NULL) { - UNLOCK_ZONE(zone); - return (ISC_R_NOMEMORY); - } - memcpy(new, notify, count * sizeof(*new)); - zone->notify = new; - zone->notifycnt = count; - } - UNLOCK_ZONE(zone); - return (ISC_R_SUCCESS); -} - -isc_result_t -dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters, - isc_uint32_t count) -{ - isc_result_t result; - - result = dns_zone_setmasterswithkeys(zone, masters, NULL, count); - return (result); -} - static isc_boolean_t -same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new, +same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new, isc_uint32_t count) { unsigned int i; @@ -4456,15 +4840,170 @@ same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) { return (ISC_TRUE); } +static void +clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp, + unsigned int *countp, isc_mem_t *mctx) +{ + unsigned int count; + isc_sockaddr_t *addrs; + dns_name_t **keynames; + + REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL); + + count = *countp; + *countp = 0; + addrs = *addrsp; + *addrsp = NULL; + keynames = *keynamesp; + *keynamesp = NULL; + + if (addrs != NULL) + isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t)); + + if (keynames != NULL) { + unsigned int i; + for (i = 0; i < count; i++) { + if (keynames[i] != NULL) { + dns_name_free(keynames[i], mctx); + isc_mem_put(mctx, keynames[i], + sizeof(dns_name_t)); + keynames[i] = NULL; + } + } + isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *)); + } +} + +static isc_result_t +set_addrkeylist(unsigned int count, + const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp, + dns_name_t **names, dns_name_t ***newnamesp, + isc_mem_t *mctx) +{ + isc_result_t result; + isc_sockaddr_t *newaddrs = NULL; + dns_name_t **newnames = NULL; + unsigned int i; + + REQUIRE(newaddrsp != NULL && *newaddrsp == NULL); + REQUIRE(newnamesp != NULL && *newnamesp == NULL); + + newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs)); + if (newaddrs == NULL) + return (ISC_R_NOMEMORY); + memcpy(newaddrs, addrs, count * sizeof(*newaddrs)); + + newnames = NULL; + if (names != NULL) { + newnames = isc_mem_get(mctx, count * sizeof(*newnames)); + if (newnames == NULL) { + isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs)); + return (ISC_R_NOMEMORY); + } + for (i = 0; i < count; i++) + newnames[i] = NULL; + for (i = 0; i < count; i++) { + if (names[i] != NULL) { + newnames[i] = isc_mem_get(mctx, + sizeof(dns_name_t)); + if (newnames[i] == NULL) + goto allocfail; + dns_name_init(newnames[i], NULL); + result = dns_name_dup(names[i], mctx, + newnames[i]); + if (result != ISC_R_SUCCESS) { + allocfail: + for (i = 0; i < count; i++) + if (newnames[i] != NULL) + dns_name_free( + newnames[i], + mctx); + isc_mem_put(mctx, newaddrs, + count * sizeof(*newaddrs)); + isc_mem_put(mctx, newnames, + count * sizeof(*newnames)); + return (ISC_R_NOMEMORY); + } + } + } + } + + *newaddrsp = newaddrs; + *newnamesp = newnames; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, + isc_uint32_t count) +{ + return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count)); +} + +isc_result_t +dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify, + dns_name_t **keynames, isc_uint32_t count) +{ + isc_result_t result; + isc_sockaddr_t *newaddrs = NULL; + dns_name_t **newnames = NULL; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(count == 0 || notify != NULL); + if (keynames != NULL) + REQUIRE(count != 0); + + LOCK_ZONE(zone); + + if (count == zone->notifycnt && + same_addrs(zone->notify, notify, count) && + same_keynames(zone->notifykeynames, keynames, count)) + goto unlock; + + clear_addresskeylist(&zone->notify, &zone->notifykeynames, + &zone->notifycnt, zone->mctx); + + if (count == 0) + goto unlock; + + /* + * Set up the notify and notifykey lists + */ + result = set_addrkeylist(count, notify, &newaddrs, + keynames, &newnames, zone->mctx); + if (result != ISC_R_SUCCESS) + goto unlock; + + /* + * Everything is ok so attach to the zone. + */ + zone->notify = newaddrs; + zone->notifykeynames = newnames; + zone->notifycnt = count; + unlock: + UNLOCK_ZONE(zone); + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters, + isc_uint32_t count) +{ + isc_result_t result; + + result = dns_zone_setmasterswithkeys(zone, masters, NULL, count); + return (result); +} + isc_result_t dns_zone_setmasterswithkeys(dns_zone_t *zone, const isc_sockaddr_t *masters, dns_name_t **keynames, isc_uint32_t count) { - isc_sockaddr_t *new; isc_result_t result = ISC_R_SUCCESS; - dns_name_t **newname; + isc_sockaddr_t *newaddrs = NULL; + dns_name_t **newnames = NULL; isc_boolean_t *newok; unsigned int i; @@ -4482,38 +5021,24 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, * unlock and exit. */ if (count != zone->masterscnt || - !same_masters(zone->masters, masters, count) || + !same_addrs(zone->masters, masters, count) || !same_keynames(zone->masterkeynames, keynames, count)) { if (zone->request != NULL) dns_request_cancel(zone->request); } else goto unlock; - if (zone->masters != NULL) { - isc_mem_put(zone->mctx, zone->masters, - zone->masterscnt * sizeof(*new)); - zone->masters = NULL; - } - if (zone->masterkeynames != NULL) { - for (i = 0; i < zone->masterscnt; i++) { - if (zone->masterkeynames[i] != NULL) { - dns_name_free(zone->masterkeynames[i], - zone->mctx); - isc_mem_put(zone->mctx, - zone->masterkeynames[i], - sizeof(dns_name_t)); - zone->masterkeynames[i] = NULL; - } - } - isc_mem_put(zone->mctx, zone->masterkeynames, - zone->masterscnt * sizeof(dns_name_t *)); - zone->masterkeynames = NULL; - } + + /* + * This needs to happen before clear_addresskeylist() sets + * zone->masterscnt to 0: + */ if (zone->mastersok != NULL) { isc_mem_put(zone->mctx, zone->mastersok, zone->masterscnt * sizeof(isc_boolean_t)); zone->mastersok = NULL; } - zone->masterscnt = 0; + clear_addresskeylist(&zone->masters, &zone->masterkeynames, + &zone->masterscnt, zone->mctx); /* * If count == 0, don't allocate any space for masters, mastersok or * keynames so internally, those pointers are NULL if count == 0 @@ -4522,76 +5047,34 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone, goto unlock; /* - * masters must contain count elements! - */ - new = isc_mem_get(zone->mctx, count * sizeof(*new)); - if (new == NULL) { - result = ISC_R_NOMEMORY; - goto unlock; - } - memcpy(new, masters, count * sizeof(*new)); - - /* - * Similarly for mastersok. + * mastersok must contain count elements */ newok = isc_mem_get(zone->mctx, count * sizeof(*newok)); if (newok == NULL) { result = ISC_R_NOMEMORY; - isc_mem_put(zone->mctx, new, count * sizeof(*new)); + isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs)); goto unlock; }; for (i = 0; i < count; i++) newok[i] = ISC_FALSE; /* - * if keynames is non-NULL, it must contain count elements! + * Now set up the masters and masterkey lists */ - newname = NULL; - if (keynames != NULL) { - newname = isc_mem_get(zone->mctx, count * sizeof(*newname)); - if (newname == NULL) { - result = ISC_R_NOMEMORY; - isc_mem_put(zone->mctx, new, count * sizeof(*new)); - isc_mem_put(zone->mctx, newok, count * sizeof(*newok)); - goto unlock; - } - for (i = 0; i < count; i++) - newname[i] = NULL; - for (i = 0; i < count; i++) { - if (keynames[i] != NULL) { - newname[i] = isc_mem_get(zone->mctx, - sizeof(dns_name_t)); - if (newname[i] == NULL) - goto allocfail; - dns_name_init(newname[i], NULL); - result = dns_name_dup(keynames[i], zone->mctx, - newname[i]); - if (result != ISC_R_SUCCESS) { - allocfail: - for (i = 0; i < count; i++) - if (newname[i] != NULL) - dns_name_free( - newname[i], - zone->mctx); - isc_mem_put(zone->mctx, new, - count * sizeof(*new)); - isc_mem_put(zone->mctx, newok, - count * sizeof(*newok)); - isc_mem_put(zone->mctx, newname, - count * sizeof(*newname)); - goto unlock; - } - } - } + result = set_addrkeylist(count, masters, &newaddrs, + keynames, &newnames, zone->mctx); + if (result != ISC_R_SUCCESS) { + isc_mem_put(zone->mctx, newok, count * sizeof(*newok)); + goto unlock; } /* * Everything is ok so attach to the zone. */ zone->curmaster = 0; - zone->masters = new; zone->mastersok = newok; - zone->masterkeynames = newname; + zone->masters = newaddrs; + zone->masterkeynames = newnames; zone->masterscnt = count; DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS); @@ -5072,9 +5555,12 @@ zone_resigninc(dns_zone_t *zone) { zonediff_init(&zonediff, &_sig_diff); /* - * Updates are disabled. Pause for 5 minutes. + * Zone is frozen or automatic resigning is disabled. + * Pause for 5 minutes. */ - if (zone->update_disabled) { + if (zone->update_disabled || + DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN)) + { result = ISC_R_FAILURE; goto failure; } @@ -5186,18 +5672,18 @@ zone_resigninc(dns_zone_t *zone) { */ if (ISC_LIST_EMPTY(zonediff.diff->tuples)) { /* - * Commit the changes if any key has been marked as offline. - */ + * Commit the changes if any key has been marked as offline. */ if (zonediff.offline) dns_db_closeversion(db, &version, ISC_TRUE); goto failure; } /* Increment SOA serial if we have made changes */ - result = increment_soa_serial(db, version, zonediff.diff, zone->mctx); + result = update_soa_serial(db, version, zonediff.diff, zone->mctx, + zone->updatemethod); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, - "zone_resigninc:increment_soa_serial -> %s", + "zone_resigninc:update_soa_serial -> %s", dns_result_totext(result)); goto failure; } @@ -5217,7 +5703,7 @@ zone_resigninc(dns_zone_t *zone) { } /* Write changes to journal file. */ - CHECK(zone_journal(zone, zonediff.diff, "zone_resigninc")); + CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc")); /* Everything has succeeded. Commit the changes. */ dns_db_closeversion(db, &version, ISC_TRUE); @@ -5625,6 +6111,7 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain, isc_buffer_t buffer; unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE]; dns_ttl_t ttl = 0; + isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE; dns_rdataset_init(&rdataset); @@ -5675,6 +6162,10 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain, if (active) goto add; + + result = dns_nsec_nseconly(db, ver, &nseconly); + nsec3ok = (result == ISC_R_SUCCESS && !nseconly); + /* * Delete all private records which match that in nsec3chain. */ @@ -5697,7 +6188,9 @@ fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain, continue; CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); - if (nsec3param.hash != chain->nsec3param.hash || + if ((!nsec3ok && + (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) || + nsec3param.hash != chain->nsec3param.hash || nsec3param.iterations != chain->nsec3param.iterations || nsec3param.salt_length != chain->nsec3param.salt_length || memcmp(nsec3param.salt, chain->nsec3param.salt, @@ -6271,7 +6764,8 @@ zone_nsec3chain(dns_zone_t *zone) { * of removing this NSEC3 chain. */ if (first && !updatensec && - (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) { + (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) + { result = need_nsec_chain(db, version, &nsec3chain->nsec3param, &buildnsecchain); @@ -6585,10 +7079,11 @@ zone_nsec3chain(dns_zone_t *zone) { goto failure; } - result = increment_soa_serial(db, version, zonediff.diff, zone->mctx); + result = update_soa_serial(db, version, zonediff.diff, zone->mctx, + zone->updatemethod); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:" - "increment_soa_serial -> %s", + "update_soa_serial -> %s", dns_result_totext(result)); goto failure; } @@ -6603,7 +7098,7 @@ zone_nsec3chain(dns_zone_t *zone) { } /* Write changes to journal file. */ - CHECK(zone_journal(zone, zonediff.diff, "zone_nsec3chain")); + CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain")); LOCK_ZONE(zone); zone_needdump(zone, DNS_DUMP_DELAY); @@ -7154,10 +7649,11 @@ zone_sign(dns_zone_t *zone) { goto failure; } - result = increment_soa_serial(db, version, zonediff.diff, zone->mctx); + result = update_soa_serial(db, version, zonediff.diff, zone->mctx, + zone->updatemethod); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, - "zone_sign:increment_soa_serial -> %s", + "zone_sign:update_soa_serial -> %s", dns_result_totext(result)); goto failure; } @@ -7179,7 +7675,7 @@ zone_sign(dns_zone_t *zone) { /* * Write changes to journal file. */ - CHECK(zone_journal(zone, zonediff.diff, "zone_sign")); + CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign")); pauseall: /* @@ -7941,8 +8437,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (!ISC_LIST_EMPTY(diff.tuples)) { /* Write changes to journal file. */ - CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx)); - CHECK(zone_journal(zone, &diff, "keyfetch_done")); + CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx, + zone->updatemethod)); + CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done")); commit = ISC_TRUE; DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); @@ -8115,8 +8612,9 @@ zone_refreshkeys(dns_zone_t *zone) { } } if (!ISC_LIST_EMPTY(diff.tuples)) { - CHECK(increment_soa_serial(db, ver, &diff, zone->mctx)); - CHECK(zone_journal(zone, &diff, "zone_refreshkeys")); + CHECK(update_soa_serial(db, ver, &diff, zone->mctx, + zone->updatemethod)); + CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys")); commit = ISC_TRUE; DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); zone_needdump(zone, 30); @@ -8163,12 +8661,18 @@ zone_maintenance(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); ENTER; + /* + * Are we pending load/reload? + */ + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) + return; + /* * Configuring the view of this zone may have * failed, for example because the config file * had a syntax error. In that case, the view - * db or resolver will be NULL, and we had better not try - * to do maintenance on it. + * adb or resolver will be NULL, and we had better not try + * to do further maintenance on it. */ if (zone->view == NULL || zone->view->adb == NULL) return; @@ -8179,6 +8683,9 @@ zone_maintenance(dns_zone_t *zone) { * Expire check. */ switch (zone->type) { + case dns_zone_redirect: + if (zone->masters == NULL) + break; case dns_zone_slave: case dns_zone_stub: LOCK_ZONE(zone); @@ -8197,6 +8704,9 @@ zone_maintenance(dns_zone_t *zone) { * Up to date check. */ switch (zone->type) { + case dns_zone_redirect: + if (zone->masters == NULL) + break; case dns_zone_slave: case dns_zone_stub: if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) && @@ -8222,6 +8732,7 @@ zone_maintenance(dns_zone_t *zone) { case dns_zone_master: case dns_zone_slave: case dns_zone_key: + case dns_zone_redirect: case dns_zone_stub: LOCK_ZONE(zone); if (zone->masterfile != NULL && @@ -8249,6 +8760,7 @@ zone_maintenance(dns_zone_t *zone) { */ switch (zone->type) { case dns_zone_master: + case dns_zone_redirect: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) && isc_time_compare(&now, &zone->notifytime) >= 0) zone_notify(zone, &now); @@ -8278,6 +8790,7 @@ zone_maintenance(dns_zone_t *zone) { switch (zone->type) { case dns_zone_master: + case dns_zone_redirect: case dns_zone_slave: /* * Do we need to sign/resign some RRsets? @@ -8299,6 +8812,7 @@ zone_maintenance(dns_zone_t *zone) { set_key_expiry_warning(zone, zone->key_expiry, isc_time_seconds(&now)); break; + default: break; } @@ -8307,10 +8821,31 @@ zone_maintenance(dns_zone_t *zone) { void dns_zone_markdirty(dns_zone_t *zone) { + isc_uint32_t serial; + isc_result_t result = ISC_R_SUCCESS; LOCK_ZONE(zone); - if (zone->type == dns_zone_master) - set_resigntime(zone); /* XXXMPA make separate call back */ + if (zone->type == dns_zone_master) { + if (inline_raw(zone)) { + unsigned int soacount; + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) { + result = zone_get_from_db(zone, zone->db, NULL, + &soacount, &serial, + NULL, NULL, NULL, + NULL, NULL); + } else + result = DNS_R_NOTLOADED; + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (result == ISC_R_SUCCESS && soacount > 0U) + zone_send_secureserial(zone, ISC_FALSE, serial); + } + + /* XXXMPA make separate call back */ + if (result == ISC_R_SUCCESS) + set_resigntime(zone); + } zone_needdump(zone, DNS_DUMP_DELAY); UNLOCK_ZONE(zone); } @@ -8497,6 +9032,22 @@ dump_done(void *arg, isc_result_t result) { version = dns_dumpctx_version(zone->dctx); tresult = dns_db_getsoaserial(db, version, &serial); + /* + * If there is a secure version of this zone + * use its serial if it is less than ours. + */ + if (tresult == ISC_R_SUCCESS && inline_raw(zone) && + zone->secure->db != NULL) + { + isc_uint32_t sserial; + isc_result_t mresult; + + mresult = dns_db_getsoaserial(zone->secure->db, + NULL, &sserial); + if (mresult == ISC_R_SUCCESS && + isc_serial_lt(sserial, serial)) + serial = sserial; + } /* * Note: we are task locked here so we can test * zone->xfr safely. @@ -8605,10 +9156,15 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) { result = DNS_R_CONTINUE; UNLOCK_ZONE(zone); } else { + dns_masterrawheader_t rawdata; dns_db_currentversion(db, &version); - result = dns_master_dump2(zone->mctx, db, version, + dns_master_initrawheader(&rawdata); + if (inline_secure(zone)) + get_raw_serial(zone->raw, &rawdata); + result = dns_master_dump3(zone->mctx, db, version, &dns_master_style_default, - masterfile, masterformat); + masterfile, masterformat, + &rawdata); dns_db_closeversion(db, &version, ISC_FALSE); } fail: @@ -8647,11 +9203,12 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) { static isc_result_t dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style, - dns_masterformat_t format) + dns_masterformat_t format, const isc_uint32_t rawversion) { isc_result_t result; dns_dbversion_t *version = NULL; dns_db_t *db = NULL; + dns_masterrawheader_t rawdata; REQUIRE(DNS_ZONE_VALID(zone)); @@ -8663,29 +9220,46 @@ dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style, return (DNS_R_NOTLOADED); dns_db_currentversion(db, &version); - result = dns_master_dumptostream2(zone->mctx, db, version, style, - format, fd); + dns_master_initrawheader(&rawdata); + if (rawversion == 0) + rawdata.flags |= DNS_MASTERRAW_COMPAT; + else if (inline_secure(zone)) + get_raw_serial(zone->raw, &rawdata); + else if (zone->sourceserialset) { + rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET; + rawdata.sourceserial = zone->sourceserial; + } + result = dns_master_dumptostream3(zone->mctx, db, version, style, + format, &rawdata, fd); dns_db_closeversion(db, &version, ISC_FALSE); dns_db_detach(&db); return (result); } +isc_result_t +dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, + const dns_master_style_t *style, + const isc_uint32_t rawversion) +{ + return (dumptostream(zone, fd, style, format, rawversion)); +} + isc_result_t dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, const dns_master_style_t *style) { - return dumptostream(zone, fd, style, format); + return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION)); } isc_result_t dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) { - return dumptostream(zone, fd, &dns_master_style_default, - dns_masterformat_text); + return (dumptostream(zone, fd, &dns_master_style_default, + dns_masterformat_text, 0)); } isc_result_t dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) { - return dumptostream(zone, fd, &dns_master_style_full, - dns_masterformat_text); + return (dumptostream(zone, fd, &dns_master_style_full, + dns_masterformat_text, 0)); } void @@ -8880,6 +9454,8 @@ notify_destroy(dns_notify_t *notify, isc_boolean_t locked) { dns_request_destroy(¬ify->request); if (dns_name_dynamic(¬ify->ns)) dns_name_free(¬ify->ns, notify->mctx); + if (notify->key != NULL) + dns_tsigkey_detach(¬ify->key); mctx = notify->mctx; isc_mem_put(notify->mctx, notify, sizeof(*notify)); isc_mem_detach(&mctx); @@ -8901,6 +9477,7 @@ notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) { notify->zone = NULL; notify->find = NULL; notify->request = NULL; + notify->key = NULL; isc_sockaddr_any(¬ify->dst); dns_name_init(¬ify->ns, NULL); ISC_LINK_INIT(notify, link); @@ -9045,15 +9622,23 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) goto cleanup; - isc_netaddr_fromsockaddr(&dstip, ¬ify->dst); - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); - result = dns_view_getpeertsig(notify->zone->view, &dstip, &key); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { - notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not " - "sent. Peer TSIG key lookup failure.", addrbuf); - goto cleanup_message; + if (notify->key != NULL) { + /* Transfer ownership of key */ + key = notify->key; + notify->key = NULL; + } else { + isc_netaddr_fromsockaddr(&dstip, ¬ify->dst); + isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + result = dns_view_getpeertsig(notify->zone->view, &dstip, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + notify_log(notify->zone, ISC_LOG_ERROR, + "NOTIFY to %s not sent. " + "Peer TSIG key lookup failure.", addrbuf); + goto cleanup_message; + } } + /* XXX: should we log the tsig key too? */ notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s", addrbuf); if (notify->zone->view->peers != NULL) { @@ -9255,14 +9840,30 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { */ LOCK_ZONE(zone); for (i = 0; i < zone->notifycnt; i++) { + dns_tsigkey_t *key = NULL; + dst = zone->notify[i]; if (notify_isqueued(zone, NULL, &dst)) continue; + result = notify_create(zone->mctx, flags, ¬ify); if (result != ISC_R_SUCCESS) continue; + zone_iattach(zone, ¬ify->zone); notify->dst = dst; + + if ((zone->notifykeynames != NULL) && + (zone->notifykeynames[i] != NULL)) { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *keyname = zone->notifykeynames[i]; + result = dns_view_gettsig(view, keyname, &key); + if (result == ISC_R_SUCCESS) { + notify->key = key; + key = NULL; + } + } + ISC_LIST_APPEND(zone->notifies, notify, link); result = notify_send_queue(notify); if (result != ISC_R_SUCCESS) @@ -9753,7 +10354,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { "master %s exceeded (source %s)", master, source); /* Try with slave with TCP. */ - if (zone->type == dns_zone_slave && + if ((zone->type == dns_zone_slave || + zone->type == dns_zone_redirect) && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) { if (!dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, @@ -9819,7 +10421,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { * Perhaps AXFR/IXFR is allowed even if SOA queries aren't. */ if (msg->rcode == dns_rcode_refused && - zone->type == dns_zone_slave) + (zone->type == dns_zone_slave || + zone->type == dns_zone_redirect)) goto tcp_transfer; goto next_master; } @@ -9828,7 +10431,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { * If truncated punt to zone transfer which will query again. */ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { - if (zone->type == dns_zone_slave) { + if (zone->type == dns_zone_slave || + zone->type == dns_zone_redirect) { dns_zone_log(zone, ISC_LOG_INFO, "refresh: truncated UDP answer, " "initiating TCP zone xfer " @@ -9955,7 +10559,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { dns_zone_log(zone, ISC_LOG_INFO, "refresh: skipping %s as master %s " "(source %s) is unreachable (cached)", - zone->type == dns_zone_slave ? + (zone->type == dns_zone_slave || + zone->type == dns_zone_redirect) ? "zone transfer" : "NS query", master, source); goto next_master; @@ -9963,7 +10568,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { tcp_transfer: isc_event_free(&event); dns_request_destroy(&zone->request); - if (zone->type == dns_zone_slave) { + if (zone->type == dns_zone_slave || + zone->type == dns_zone_redirect) { do_queue_xfrin = ISC_TRUE; } else { INSIST(zone->type == dns_zone_stub); @@ -10643,6 +11249,7 @@ static void zone_shutdown(isc_task_t *task, isc_event_t *event) { dns_zone_t *zone = (dns_zone_t *) event->ev_arg; isc_boolean_t free_needed, linked = ISC_FALSE; + dns_zone_t *raw = NULL, *secure = NULL; UNUSED(task); REQUIRE(DNS_ZONE_VALID(zone)); @@ -10725,7 +11332,19 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) { */ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN); free_needed = exit_check(zone); + if (inline_secure(zone)) { + raw = zone->raw; + zone->raw = NULL; + } + if (inline_raw(zone)) { + secure = zone->secure; + zone->secure = NULL; + } UNLOCK_ZONE(zone); + if (raw != NULL) + dns_zone_detach(&raw); + if (secure != NULL) + dns_zone_idetach(&secure); if (free_needed) zone_free(zone); } @@ -10759,6 +11378,11 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) { isc_time_settoepoch(&next); switch (zone->type) { + case dns_zone_redirect: + if (zone->masters != NULL) + goto treat_as_slave; + /* FALLTHROUGH */ + case dns_zone_master: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) next = zone->notifytime; @@ -10769,6 +11393,8 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) { isc_time_compare(&zone->dumptime, &next) < 0) next = zone->dumptime; } + if (zone->type == dns_zone_redirect) + break; if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) && !isc_time_isepoch(&zone->refreshkeytime)) { if (isc_time_isepoch(&next) || @@ -10798,9 +11424,10 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) { break; case dns_zone_slave: + treat_as_slave: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) next = zone->notifytime; - /*FALLTHROUGH*/ + /* FALLTHROUGH */ case dns_zone_stub: if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) && @@ -11078,9 +11705,17 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, isc_sockaddr_format(from, fromtext, sizeof(fromtext)); /* - * We only handle NOTIFY (SOA) at the present. + * Notify messages are processed by the raw zone. */ LOCK_ZONE(zone); + if (inline_secure(zone)) { + result = dns_zone_notifyreceive(zone->raw, from, msg); + UNLOCK_ZONE(zone); + return (result); + } + /* + * We only handle NOTIFY (SOA) at the present. + */ if (isc_sockaddr_pf(from) == PF_INET) inc_stats(zone, dns_zonestatscounter_notifyinv4); else @@ -11468,15 +12103,17 @@ zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) { * Leave space for terminating '\0'. */ isc_buffer_init(&buffer, buf, length - 1); - if (dns_name_dynamic(&zone->origin)) - result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer); - if (result != ISC_R_SUCCESS && - isc_buffer_availablelength(&buffer) >= (sizeof("") - 1)) - isc_buffer_putstr(&buffer, ""); + if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) { + if (dns_name_dynamic(&zone->origin)) + result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer); + if (result != ISC_R_SUCCESS && + isc_buffer_availablelength(&buffer) >= (sizeof("") - 1)) + isc_buffer_putstr(&buffer, ""); - if (isc_buffer_availablelength(&buffer) > 0) - isc_buffer_putstr(&buffer, "/"); - (void)dns_rdataclass_totext(zone->rdclass, &buffer); + if (isc_buffer_availablelength(&buffer) > 0) + isc_buffer_putstr(&buffer, "/"); + (void)dns_rdataclass_totext(zone->rdclass, &buffer); + } if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 && strcmp(zone->view->name, "_default") != 0 && @@ -11484,6 +12121,10 @@ zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) { isc_buffer_putstr(&buffer, "/"); isc_buffer_putstr(&buffer, zone->view->name); } + if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) + isc_buffer_putstr(&buffer, " (signed)"); + if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) + isc_buffer_putstr(&buffer, " (unsigned)"); buf[isc_buffer_usedlength(&buffer)] = '\0'; } @@ -11585,8 +12226,9 @@ dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, vsnprintf(message, sizeof(message), fmt, ap); va_end(ap); isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, - level, "%s %s: %s", (zone->type == dns_zone_key) ? - "managed-keys-zone" : "zone", zone->strnamerd, message); + level, "%s%s: %s", (zone->type == dns_zone_key) ? + "managed-keys-zone" : (zone->type == dns_zone_redirect) ? + "redirect-zone" : "zone ", zone->strnamerd, message); } void @@ -11601,8 +12243,9 @@ dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) { vsnprintf(message, sizeof(message), fmt, ap); va_end(ap); isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, - level, "%s %s: %s", (zone->type == dns_zone_key) ? - "managed-keys-zone" : "zone", zone->strnamerd, message); + level, "%s%s: %s", (zone->type == dns_zone_key) ? + "managed-keys-zone" : (zone->type == dns_zone_redirect) ? + "redirect-zone" : "zone ", zone->strnamerd, message); } static void @@ -11612,6 +12255,7 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, va_list ap; char message[4096]; int level = ISC_LOG_DEBUG(debuglevel); + const char *zstr; if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) return; @@ -11619,9 +12263,21 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, va_start(ap, fmt); vsnprintf(message, sizeof(message), fmt, ap); va_end(ap); + + switch (zone->type) { + case dns_zone_key: + zstr = "managed-keys-zone"; + break; + case dns_zone_redirect: + zstr = "redirect-zone"; + break; + default: + zstr = "zone"; + } + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, - level, "%s: %s %s: %s", me, zone->type != dns_zone_key ? - "zone" : "managed-keys-zone", zone->strnamerd, message); + level, "%s: %s %s: %s", me, zstr, zone->strnamerd, + message); } static int @@ -11799,6 +12455,572 @@ notify_done(isc_task_t *task, isc_event_t *event) { dns_message_destroy(&message); } +struct secure_event { + isc_event_t e; + dns_db_t *db; + isc_uint32_t serial; +}; + +static void +update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { + UNUSED(arg); + dns_zone_log(zone, level, "%s", message); +} + +static isc_result_t +sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, + isc_uint32_t start, isc_uint32_t end, + dns_difftuple_t **soatuplep, dns_diff_t *diff) +{ + isc_result_t result; + dns_difftuple_t *tuple = NULL; + dns_diffop_t op = DNS_DIFFOP_ADD; + int n_soa = 0; + + REQUIRE(soatuplep != NULL); + + if (start == end) + return (DNS_R_UNCHANGED); + + CHECK(dns_journal_iter_init(journal, start, end)); + for (result = dns_journal_first_rr(journal); + result == ISC_R_SUCCESS; + result = dns_journal_next_rr(journal)) + { + dns_name_t *name = NULL; + isc_uint32_t ttl; + dns_rdata_t *rdata = NULL; + dns_journal_current_rr(journal, &name, &ttl, &rdata); + + if (rdata->type == dns_rdatatype_soa) { + n_soa++; + if (n_soa == 2) { + /* + * Save the latest raw SOA record. + */ + if (*soatuplep != NULL) + dns_difftuple_free(soatuplep); + CHECK(dns_difftuple_create(diff->mctx, + DNS_DIFFOP_ADD, + name, ttl, rdata, + soatuplep)); + } + if (n_soa == 3) + n_soa = 1; + continue; + } + + /* Sanity. */ + if (n_soa == 0) { + dns_zone_log(zone->raw, ISC_LOG_ERROR, + "corrupt journal file: '%s'\n", + zone->raw->journal); + return (ISC_R_FAILURE); + } + + if (zone->privatetype != 0 && + rdata->type == zone->privatetype) + continue; + + if (rdata->type == dns_rdatatype_nsec || + rdata->type == dns_rdatatype_rrsig || + rdata->type == dns_rdatatype_nsec3 || + rdata->type == dns_rdatatype_dnskey || + rdata->type == dns_rdatatype_nsec3param) + continue; + + op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD; + + CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata, + &tuple)); + dns_diff_appendminimal(diff, &tuple); + } + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + + failure: + return(result); +} + +static isc_result_t +sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, + dns_dbversion_t *secver, dns_difftuple_t **soatuple, + dns_diff_t *diff) +{ + isc_result_t result; + dns_db_t *rawdb = NULL; + dns_dbversion_t *rawver = NULL; + dns_difftuple_t *tuple = NULL, *next; + dns_difftuple_t *oldtuple = NULL, *newtuple = NULL; + dns_rdata_soa_t oldsoa, newsoa; + + REQUIRE(DNS_ZONE_VALID(seczone)); + REQUIRE(inline_secure(seczone)); + REQUIRE(soatuple != NULL && *soatuple == NULL); + + if (!seczone->sourceserialset) + return (DNS_R_UNCHANGED); + + dns_db_attach(seczone->raw->db, &rawdb); + dns_db_currentversion(rawdb, &rawver); + result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL); + dns_db_closeversion(rawdb, &rawver, ISC_FALSE); + dns_db_detach(&rawdb); + + if (result != ISC_R_SUCCESS) + return (result); + + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = next) + { + next = ISC_LIST_NEXT(tuple, link); + if (tuple->rdata.type == dns_rdatatype_nsec || + tuple->rdata.type == dns_rdatatype_rrsig || + tuple->rdata.type == dns_rdatatype_dnskey || + tuple->rdata.type == dns_rdatatype_nsec3 || + tuple->rdata.type == dns_rdatatype_nsec3param) + { + ISC_LIST_UNLINK(diff->tuples, tuple, link); + dns_difftuple_free(&tuple); + continue; + } + if (tuple->rdata.type == dns_rdatatype_soa) { + if (tuple->op == DNS_DIFFOP_DEL) { + INSIST(oldtuple == NULL); + oldtuple = tuple; + } + if (tuple->op == DNS_DIFFOP_ADD) { + INSIST(newtuple == NULL); + newtuple = tuple; + } + } + } + + if (oldtuple != NULL && newtuple != NULL) { + + result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + /* + * If the SOA records are the same except for the serial + * remove them from the diff. + */ + if (oldsoa.refresh == newsoa.refresh && + oldsoa.retry == newsoa.retry && + oldsoa.minimum == newsoa.minimum && + oldsoa.expire == newsoa.expire && + dns_name_equal(&oldsoa.origin, &newsoa.origin) && + dns_name_equal(&oldsoa.contact, &newsoa.contact)) { + ISC_LIST_UNLINK(diff->tuples, oldtuple, link); + dns_difftuple_free(&oldtuple); + ISC_LIST_UNLINK(diff->tuples, newtuple, link); + dns_difftuple_free(&newtuple); + } + } + + if (ISC_LIST_EMPTY(diff->tuples)) + return (DNS_R_UNCHANGED); + + /* + * If there are still SOA records in the diff they can now be removed + * saving the new SOA record. + */ + if (oldtuple != NULL) { + ISC_LIST_UNLINK(diff->tuples, oldtuple, link); + dns_difftuple_free(&oldtuple); + } + + if (newtuple != NULL) { + ISC_LIST_UNLINK(diff->tuples, newtuple, link); + *soatuple = newtuple; + } + + return (ISC_R_SUCCESS); +} + +static void +receive_secure_serial(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + dns_journal_t *rjournal = NULL; + isc_uint32_t start, end; + dns_zone_t *zone; + dns_db_t *db = NULL; + dns_dbversion_t *newver = NULL, *oldver = NULL; + dns_diff_t diff; + dns_difftuple_t *tuple = NULL, *soatuple = NULL; + dns_update_log_t log = { update_log_cb, NULL }; + isc_time_t timenow; + + zone = event->ev_arg; + end = ((struct secure_event *)event)->serial; + isc_event_free(&event); + + LOCK_ZONE(zone); + + dns_diff_init(zone->mctx, &diff); + + UNUSED(task); + + /* + * zone->db may be NULL if the load from disk failed. + */ + if (zone->db == NULL || !inline_secure(zone)) { + result = ISC_R_FAILURE; + goto failure; + } + + /* + * We first attempt to sync the raw zone to the secure zone + * by using the raw zone's journal, applying all the deltas + * from the latest source-serial of the secure zone up to + * the current serial number of the raw zone. + * + * If that fails, then we'll fall back to a direct comparison + * between raw and secure zones. + */ + result = dns_journal_open(zone->raw->mctx, zone->raw->journal, + DNS_JOURNAL_WRITE, &rjournal); + if (result != ISC_R_SUCCESS) + goto failure; + else { + dns_journal_t *sjournal = NULL; + + result = dns_journal_open(zone->mctx, zone->journal, + DNS_JOURNAL_READ, &sjournal); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + goto failure; + + if (!dns_journal_get_sourceserial(rjournal, &start)) { + start = dns_journal_first_serial(rjournal); + dns_journal_set_sourceserial(rjournal, start); + } + if (sjournal != NULL) { + isc_uint32_t serial; + /* + * We read the secure journal first, if that exists + * use its value provided it is greater that from the + * raw journal. + */ + if (dns_journal_get_sourceserial(sjournal, &serial)) { + if (isc_serial_gt(serial, start)) + start = serial; + } + dns_journal_destroy(&sjournal); + } + } + + dns_db_attach(zone->db, &db); + dns_db_currentversion(db, &oldver); + CHECK(dns_db_newversion(db, &newver)); + + /* + * Try to apply diffs from the raw zone's journal to the secure + * zone. If that fails, we recover by syncing up the databases + * directly. + */ + result = sync_secure_journal(zone, rjournal, start, end, + &soatuple, &diff); + if (result == DNS_R_UNCHANGED) + goto failure; + else if (result != ISC_R_SUCCESS) + CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff)); + + CHECK(dns_diff_apply(&diff, db, newver)); + + if (soatuple != NULL) { + isc_uint32_t oldserial, newserial, desired; + + CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, + DNS_DIFFOP_DEL, &tuple)); + oldserial = dns_soa_getserial(&tuple->rdata); + newserial = desired = dns_soa_getserial(&soatuple->rdata); + if (!isc_serial_gt(newserial, oldserial)) { + newserial = oldserial + 1; + if (newserial == 0) + newserial++; + dns_soa_setserial(newserial, &soatuple->rdata); + } + CHECK(do_one_tuple(&tuple, db, newver, &diff)); + CHECK(do_one_tuple(&soatuple, db, newver, &diff)); + dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)", + newserial, desired); + } else + CHECK(update_soa_serial(db, newver, &diff, zone->mctx, + zone->updatemethod)); + + CHECK(dns_update_signatures(&log, zone, db, oldver, newver, + &diff, zone->sigvalidityinterval)); + + CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial")); + + dns_journal_set_sourceserial(rjournal, end); + dns_journal_commit(rjournal); + + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + + zone->sourceserial = end; + zone->sourceserialset = ISC_TRUE; + zone_needdump(zone, DNS_DUMP_DELAY); + + TIME_NOW(&timenow); + zone_settimer(zone, &timenow); + + dns_db_closeversion(db, &oldver, ISC_FALSE); + dns_db_closeversion(db, &newver, ISC_TRUE); + + failure: + UNLOCK_ZONE(zone); + if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s", + dns_result_totext(result)); + if (tuple != NULL) + dns_difftuple_free(&tuple); + if (soatuple != NULL) + dns_difftuple_free(&soatuple); + if (db != NULL) { + if (oldver != NULL) + dns_db_closeversion(db, &oldver, ISC_FALSE); + if (newver != NULL) + dns_db_closeversion(db, &newver, ISC_FALSE); + dns_db_detach(&db); + } + if (rjournal != NULL) + dns_journal_destroy(&rjournal); + dns_diff_clear(&diff); + dns_zone_idetach(&zone); +} + +static isc_result_t +zone_send_secureserial(dns_zone_t *zone, isc_boolean_t locked, + isc_uint32_t serial) +{ + isc_event_t *e; + dns_zone_t *dummy = NULL; + + e = isc_event_allocate(zone->secure->mctx, zone, + DNS_EVENT_ZONESECURESERIAL, + receive_secure_serial, zone->secure, + sizeof(struct secure_event)); + if (e == NULL) + return (ISC_R_NOMEMORY); + ((struct secure_event *)e)->serial = serial; + if (locked) + zone_iattach(zone->secure, &dummy); + else + dns_zone_iattach(zone->secure, &dummy); + isc_task_send(zone->secure->task, &e); + + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE); + return (ISC_R_SUCCESS); +} + +static isc_result_t +checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdataset_t *rdataset, isc_uint32_t oldserial) +{ + dns_rdata_soa_t soa; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t temprdatalist; + dns_rdataset_t temprdataset; + isc_buffer_t b; + isc_result_t result; + unsigned char buf[DNS_SOA_BUFFERSIZE]; + + result = dns_rdataset_first(rdataset); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + if (isc_serial_gt(soa.serial, oldserial)) + return (dns_db_addrdataset(db, node, version, 0, rdataset, 0, + NULL)); + /* + * Always bump the serial. + */ + oldserial++; + if (oldserial == 0) + oldserial++; + soa.serial = oldserial; + + /* + * Construct a replacement rdataset. + */ + dns_rdata_reset(&rdata); + isc_buffer_init(&b, buf, sizeof(buf)); + result = dns_rdata_fromstruct(&rdata, rdataset->rdclass, + dns_rdatatype_soa, &soa, &b); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + temprdatalist.rdclass = rdata.rdclass; + temprdatalist.type = rdata.type; + temprdatalist.covers = 0; + temprdatalist.ttl = rdataset->ttl; + ISC_LIST_INIT(temprdatalist.rdata); + ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link); + + dns_rdataset_init(&temprdataset); + result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + return (dns_db_addrdataset(db, node, version, 0, &temprdataset, + 0, NULL)); +} + +static void +receive_secure_db(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + dns_zone_t *zone; + dns_db_t *rawdb, *db = NULL; + dns_dbnode_t *rawnode = NULL, *node = NULL; + dns_fixedname_t fname; + dns_name_t *name; + dns_dbiterator_t *dbiterator = NULL; + dns_rdatasetiter_t *rdsit = NULL; + dns_rdataset_t rdataset; + dns_dbversion_t *version = NULL; + isc_time_t loadtime; + unsigned int oldserial = 0; + isc_boolean_t have_oldserial = ISC_FALSE; + + UNUSED(task); + + zone = event->ev_arg; + rawdb = ((struct secure_event *)event)->db; + isc_event_free(&event); + + REQUIRE(inline_secure(zone)); + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_rdataset_init(&rdataset); + + TIME_NOW(&loadtime); + if (zone->db != NULL) { + result = dns_db_getsoaserial(zone->db, NULL, &oldserial); + if (result == ISC_R_SUCCESS) + have_oldserial = ISC_TRUE; + } + + result = dns_db_create(zone->mctx, zone->db_argv[0], + &zone->origin, dns_dbtype_zone, zone->rdclass, + zone->db_argc - 1, zone->db_argv + 1, &db); + if (result != ISC_R_SUCCESS) + goto failure; + + result = dns_db_newversion(db, &version); + if (result != ISC_R_SUCCESS) + goto failure; + + result = dns_db_createiterator(rawdb, 0, &dbiterator); + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_dbiterator_first(dbiterator); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiterator)) { + result = dns_dbiterator_current(dbiterator, &rawnode, name); + if (result != ISC_R_SUCCESS) + continue; + + result = dns_db_findnode(db, name, ISC_TRUE, &node); + if (result != ISC_R_SUCCESS) + goto failure; + + result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit); + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdatasetiter_first(rdsit); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsit)) { + dns_rdatasetiter_current(rdsit, &rdataset); + if (rdataset.type == dns_rdatatype_nsec || + rdataset.type == dns_rdatatype_rrsig || + rdataset.type == dns_rdatatype_nsec3 || + rdataset.type == dns_rdatatype_dnskey || + rdataset.type == dns_rdatatype_nsec3param) { + dns_rdataset_disassociate(&rdataset); + continue; + } + if (rdataset.type == dns_rdatatype_soa && + have_oldserial) { + result = checkandaddsoa(db, node, version, + &rdataset, oldserial); + } else + result = dns_db_addrdataset(db, node, version, + 0, &rdataset, 0, + NULL); + if (result != ISC_R_SUCCESS) + goto failure; + + dns_rdataset_disassociate(&rdataset); + } + dns_rdatasetiter_destroy(&rdsit); + dns_db_detachnode(rawdb, &rawnode); + dns_db_detachnode(db, &node); + } + + dns_db_closeversion(db, &version, ISC_TRUE); + /* + * Lock hierarchy: zmgr, zone, raw. + */ + LOCK_ZONE(zone); + if (inline_secure(zone)) + LOCK_ZONE(zone->raw); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS); + zone_needdump(zone, 0); /* XXXMPA */ + if (inline_secure(zone)) + UNLOCK_ZONE(zone->raw); + UNLOCK_ZONE(zone); + + failure: + if (result != ISC_R_SUCCESS) + dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s", + dns_result_totext(result)); + + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (db != NULL) { + if (node != NULL) + dns_db_detachnode(db, &node); + dns_db_detach(&db); + } + if (rawnode != NULL) + dns_db_detachnode(rawdb, &rawnode); + dns_db_detach(&rawdb); + if (dbiterator != NULL) + dns_dbiterator_destroy(&dbiterator); + dns_zone_idetach(&zone); +} + +static isc_result_t +zone_send_securedb(dns_zone_t *zone, isc_boolean_t locked, dns_db_t *db) { + isc_event_t *e; + dns_db_t *dummy = NULL; + dns_zone_t *secure = NULL; + + e = isc_event_allocate(zone->secure->mctx, zone, + DNS_EVENT_ZONESECUREDB, + receive_secure_db, zone->secure, + sizeof(struct secure_event)); + if (e == NULL) + return (ISC_R_NOMEMORY); + dns_db_attach(db, &dummy); + ((struct secure_event *)e)->db = dummy; + if (locked) + zone_iattach(zone->secure, &secure); + else + dns_zone_iattach(zone->secure, &secure); + + isc_task_send(zone->secure->task, &e); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE); + return (ISC_R_SUCCESS); +} + isc_result_t dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { isc_result_t result; @@ -11860,7 +13082,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { */ if (zone->db != NULL && zone->journal != NULL && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && - !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { + !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) + { isc_uint32_t serial, oldserial; unsigned int soacount; @@ -11882,8 +13105,10 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(soacount > 0U); - if (zone->type == dns_zone_slave && - !isc_serial_gt(serial, oldserial)) { + if ((zone->type == dns_zone_slave || + (zone->type == dns_zone_redirect && + zone->masters != NULL)) + && !isc_serial_gt(serial, oldserial)) { isc_uint32_t serialmin, serialmax; serialmin = (oldserial + 1) & 0xffffffffU; serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; @@ -11919,6 +13144,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { break; } } + if (zone->type == dns_zone_master && inline_raw(zone)) + zone_send_secureserial(zone, ISC_FALSE, serial); } else { if (dump && zone->masterfile != NULL) { /* @@ -11969,13 +13196,14 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { zone->journal, strbuf); } } + + if (inline_raw(zone)) + zone_send_securedb(zone, ISC_FALSE, db); } dns_db_closeversion(db, &ver, ISC_FALSE); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), - "replacing zone database"); + dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database"); if (zone->db != NULL) zone_detachdb(zone); @@ -12120,6 +13348,8 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { dns_zone_log(zone, ISC_LOG_INFO, "transferred serial %u%s", serial, buf); + if (inline_raw(zone)) + zone_send_secureserial(zone, ISC_FALSE, serial); } /* @@ -12274,18 +13504,26 @@ zone_loaddone(void *arg, isc_result_t result) { (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)) result = tresult; - LOCK_ZONE(load->zone); - (void)zone_postload(load->zone, load->db, load->loadtime, result); - zonemgr_putio(&load->zone->readio); - DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); + /* + * Lock hierarchy: zmgr, zone, raw. + */ + LOCK_ZONE(zone); + if (inline_secure(zone)) + LOCK_ZONE(zone->raw); + (void)zone_postload(zone, load->db, load->loadtime, result); + zonemgr_putio(&zone->readio); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING); + zone_idetach(&load->callbacks.zone); /* * Leave the zone frozen if the reload fails. */ if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) && - DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW)) + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW)) zone->update_disabled = ISC_FALSE; - DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW); - UNLOCK_ZONE(load->zone); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW); + if (inline_secure(zone)) + UNLOCK_ZONE(zone->raw); + UNLOCK_ZONE(zone); load->magic = 0; dns_db_detach(&load->db); @@ -12383,7 +13621,7 @@ queue_xfrin(dns_zone_t *zone) { */ static void got_transfer_quota(isc_task_t *task, isc_event_t *event) { - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; dns_peer_t *peer = NULL; char master[ISC_SOCKADDR_FORMATSIZE]; char source[ISC_SOCKADDR_FORMATSIZE]; @@ -12432,14 +13670,6 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { "no database exists yet, requesting AXFR of " "initial version from %s", master); xfrtype = dns_rdatatype_axfr; - } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences " - "set, requesting %sAXFR from %s", soa_before, - master); - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) - xfrtype = dns_rdatatype_soa; - else - xfrtype = dns_rdatatype_axfr; } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "forced reload, requesting AXFR of " @@ -12455,13 +13685,10 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { UNLOCK_ZONE(zone); } else { isc_boolean_t use_ixfr = ISC_TRUE; - if (peer != NULL && - dns_peer_getrequestixfr(peer, &use_ixfr) == - ISC_R_SUCCESS) { - ; /* Using peer setting */ - } else { - use_ixfr = zone->view->requestixfr; - } + if (peer != NULL) + result = dns_peer_getrequestixfr(peer, &use_ixfr); + if (peer == NULL || result != ISC_R_SUCCESS) + use_ixfr = zone->requestixfr; if (use_ixfr == ISC_FALSE) { dns_zone_log(zone, ISC_LOG_DEBUG(1), "IXFR disabled, requesting %sAXFR from %s", @@ -12806,6 +14033,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, zmgr->timermgr = timermgr; zmgr->socketmgr = socketmgr; zmgr->zonetasks = NULL; + zmgr->loadtasks = NULL; + zmgr->mctxpool = NULL; zmgr->task = NULL; zmgr->rl = NULL; ISC_LIST_INIT(zmgr->zones); @@ -12873,6 +14102,33 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, return (result); } +isc_result_t +dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) { + isc_result_t result; + isc_mem_t *mctx = NULL; + dns_zone_t *zone = NULL; + void *item; + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + REQUIRE(zonep != NULL && *zonep == NULL); + + if (zmgr->mctxpool == NULL) + return (ISC_R_FAILURE); + + item = isc_pool_get(zmgr->mctxpool); + if (item == NULL) + return (ISC_R_FAILURE); + + isc_mem_attach((isc_mem_t *) item, &mctx); + result = dns_zone_create(&zone, mctx); + isc_mem_detach(&mctx); + + if (result == ISC_R_SUCCESS) + *zonep = zone; + + return (result); +} + isc_result_t dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { isc_result_t result; @@ -12890,6 +14146,7 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { REQUIRE(zone->zmgr == NULL); isc_taskpool_gettask(zmgr->zonetasks, &zone->task); + isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask); /* * Set the task name. The tag will arbitrarily point to one @@ -12897,6 +14154,7 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { * to be managed last). */ isc_task_setname(zone->task, "zone", zone); + isc_task_setname(zone->loadtask, "loadzone", zone); result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL, NULL, @@ -12904,7 +14162,7 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { &zone->timer); if (result != ISC_R_SUCCESS) - goto cleanup_task; + goto cleanup_tasks; /* * The timer "holds" a iref. @@ -12918,7 +14176,8 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { goto unlock; - cleanup_task: + cleanup_tasks: + isc_task_detach(&zone->loadtask); isc_task_detach(&zone->task); unlock: @@ -13034,6 +14293,10 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) { isc_task_destroy(&zmgr->task); if (zmgr->zonetasks != NULL) isc_taskpool_destroy(&zmgr->zonetasks); + if (zmgr->loadtasks != NULL) + isc_taskpool_destroy(&zmgr->loadtasks); + if (zmgr->mctxpool != NULL) + isc_pool_destroy(&zmgr->mctxpool); RWLOCK(&zmgr->rwlock, isc_rwlocktype_read); for (zone = ISC_LIST_HEAD(zmgr->zones); @@ -13047,23 +14310,56 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) { RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read); } +static isc_result_t +mctxinit(void **target, void *arg) { + isc_result_t result; + isc_mem_t *mctx = NULL; + + UNUSED(arg); + + REQUIRE(target != NULL && *target == NULL); + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) + return (result); + isc_mem_setname(mctx, "zonemgr-pool", NULL); + + *target = mctx; + return (ISC_R_SUCCESS); +} + +static void +mctxfree(void **target) { + isc_mem_t *mctx = *(isc_mem_t **) target; + isc_mem_detach(&mctx); + *target = NULL; +} + +#define ZONES_PER_TASK 100 +#define ZONES_PER_MCTX 1000 + isc_result_t dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) { isc_result_t result; - int ntasks = num_zones / 100; + int ntasks = num_zones / ZONES_PER_TASK; + int nmctx = num_zones / ZONES_PER_MCTX; isc_taskpool_t *pool = NULL; + isc_pool_t *mctxpool = NULL; REQUIRE(DNS_ZONEMGR_VALID(zmgr)); /* * For anything fewer than 1000 zones we use 10 tasks in - * the task pool. More than that, and we'll scale at one - * task per 100 zones. + * the task pools. More than that, and we'll scale at one + * task per 100 zones. Similarly, for anything smaller than + * 2000 zones we use 2 memory contexts, then scale at 1:1000. */ if (ntasks < 10) ntasks = 10; + if (nmctx < 2) + nmctx = 2; - /* Create or resize the zone task pool. */ + /* Create or resize the zone task pools. */ if (zmgr->zonetasks == NULL) result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks, 2, &pool); @@ -13073,6 +14369,43 @@ dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) { if (result == ISC_R_SUCCESS) zmgr->zonetasks = pool; + pool = NULL; + if (zmgr->loadtasks == NULL) + result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, + ntasks, 2, &pool); + else + result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool); + + if (result == ISC_R_SUCCESS) + zmgr->loadtasks = pool; + +#ifdef BIND9 + /* + * We always set all tasks in the zone-load task pool to + * privileged. This prevents other tasks in the system from + * running while the server task manager is in privileged + * mode. + * + * NOTE: If we start using task privileges for any other + * part of the system than zone tasks, then this will need to be + * revisted. In that case we'd want to turn on privileges for + * zone tasks only when we were loading, and turn them off the + * rest of the time. For now, however, it's okay to just + * set it and forget it. + */ + isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE); +#endif + + /* Create or resize the zone memory context pool. */ + if (zmgr->mctxpool == NULL) + result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, + mctxinit, NULL, &mctxpool); + else + result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool); + + if (result == ISC_R_SUCCESS) + zmgr->mctxpool = mctxpool; + return (result); } @@ -13309,12 +14642,14 @@ zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high, io = isc_mem_get(zmgr->mctx, sizeof(*io)); if (io == NULL) return (ISC_R_NOMEMORY); + io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY, action, arg, sizeof(*io->event)); if (io->event == NULL) { isc_mem_put(zmgr->mctx, io, sizeof(*io)); return (ISC_R_NOMEMORY); } + io->zmgr = zmgr; io->high = high; io->task = NULL; @@ -13334,9 +14669,8 @@ zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high, UNLOCK(&zmgr->iolock); *iop = io; - if (!queue) { + if (!queue) isc_task_send(io->task, &io->event); - } return (ISC_R_SUCCESS); } @@ -13613,7 +14947,8 @@ void dns_zone_forcereload(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); - if (zone->type == dns_zone_master) + if (zone->type == dns_zone_master || + (zone->type == dns_zone_redirect && zone->masters == NULL)) return; LOCK_ZONE(zone); @@ -13661,6 +14996,7 @@ dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) { void dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) { + REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); @@ -13673,10 +15009,25 @@ dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) { } } UNLOCK_ZONE(zone); - - return; } +#ifdef NEWSTATS +void +dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (zone->requeststats_on && stats != NULL) { + if (zone->rcvquerystats == NULL) { + dns_stats_attach(stats, &zone->rcvquerystats); + zone->requeststats_on = ISC_TRUE; + } + } + UNLOCK_ZONE(zone); +} +#endif + isc_stats_t * dns_zone_getrequeststats(dns_zone_t *zone) { /* @@ -13693,6 +15044,20 @@ dns_zone_getrequeststats(dns_zone_t *zone) { return (NULL); } +#ifdef NEWSTATS +/* + * Return the received query stats bucket + * see note from dns_zone_getrequeststats() + */ +dns_stats_t * +dns_zone_getrcvquerystats(dns_zone_t *zone) { + if (zone->requeststats_on) + return (zone->rcvquerystats); + else + return (NULL); +} +#endif + void dns_zone_dialup(dns_zone_t *zone) { @@ -13705,7 +15070,7 @@ dns_zone_dialup(dns_zone_t *zone) { if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) dns_zone_notify(zone); - if (zone->type != dns_zone_master && + if (zone->type != dns_zone_master && zone->masters != NULL && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) dns_zone_refresh(zone); } @@ -14321,8 +15686,12 @@ dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, } /* Check existing DB for NSEC-only DNSKEY */ - if (!nseconly) - CHECK(dns_nsec_nseconly(db, ver, &nseconly)); + if (!nseconly) { + result = dns_nsec_nseconly(db, ver, &nseconly); + if (result == ISC_R_NOTFOUND) + result = ISC_R_SUCCESS; + CHECK(result); + } /* Check existing DB for NSEC3 */ if (!nsec3) @@ -14360,7 +15729,7 @@ clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, if (result != ISC_R_NOTFOUND) goto failure; - result = dns_nsec3param_deletechains(db, ver, zone, diff); + result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff); failure: if (node != NULL) @@ -14476,14 +15845,11 @@ zone_rekey(dns_zone_t *zone) { dns_rdatatype_none, 0, &keyset, &keysigs); if (result == ISC_R_SUCCESS) { ttl = keyset.ttl; - result = dns_dnssec_keylistfromrdataset(&zone->origin, dir, - mctx, &keyset, - &keysigs, &soasigs, - ISC_FALSE, ISC_FALSE, - &dnskeys); - /* Can't get keys for some reason; try again later. */ - if (result != ISC_R_SUCCESS) - goto trylater; + CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir, + mctx, &keyset, + &keysigs, &soasigs, + ISC_FALSE, ISC_FALSE, + &dnskeys)); } else if (result != ISC_R_NOTFOUND) goto failure; @@ -14509,7 +15875,7 @@ zone_rekey(dns_zone_t *zone) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:" "couldn't update zone keys: %s", isc_result_totext(result)); - goto trylater; + goto failure; } /* @@ -14552,15 +15918,17 @@ zone_rekey(dns_zone_t *zone) { CHECK(add_signing_records(db, zone->privatetype, ver, &diff, ISC_TF(newalg || fullsign))); - CHECK(increment_soa_serial(db, ver, &diff, mctx)); + CHECK(update_soa_serial(db, ver, &diff, mctx, + zone->updatemethod)); CHECK(add_chains(zone, db, ver, &diff)); CHECK(sign_apex(zone, db, ver, &diff, &zonediff)); - CHECK(zone_journal(zone, zonediff.diff, "zone_rekey")); + CHECK(zone_journal(zone, zonediff.diff, NULL, + "zone_rekey")); commit = ISC_TRUE; } } - dns_db_closeversion(db, &ver, commit); + dns_db_closeversion(db, &ver, ISC_TRUE); if (commit) { dns_difftuple_t *tuple; @@ -14672,6 +16040,13 @@ zone_rekey(dns_zone_t *zone) { } } + /* + * Activate any NSEC3 chain updates that may have + * been scheduled before this rekey. + */ + if (fullsign || newalg) + resume_addnsec3chain(zone); + /* * Schedule the next resigning event */ @@ -14683,15 +16058,16 @@ zone_rekey(dns_zone_t *zone) { /* * If we're doing key maintenance, set the key refresh timer to - * the next scheduled key event or to one hour in the future, - * whichever is sooner. + * the next scheduled key event or to 'dnssec-loadkeys-interval' + * seconds in the future, whichever is sooner. */ if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) { isc_time_t timethen; isc_stdtime_t then; LOCK_ZONE(zone); - DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen); + DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval, + &timethen); zone->refreshkeytime = timethen; UNLOCK_ZONE(zone); @@ -14718,7 +16094,7 @@ zone_rekey(dns_zone_t *zone) { dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf); } - failure: + done: dns_diff_clear(&diff); dns_diff_clear(&_sig_diff); @@ -14740,10 +16116,14 @@ zone_rekey(dns_zone_t *zone) { dns_db_detach(&db); return; - trylater: - isc_interval_set(&ival, HOUR, 0); + failure: + /* + * Something went wrong; try again in ten minutes or + * after a key refresh interval, whichever is shorter. + */ + isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0); isc_time_nowplusinterval(&zone->refreshkeytime, &ival); - goto failure; + goto done; } void @@ -14802,10 +16182,572 @@ dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) { isc_time_t loadtime; isc_result_t result; + TIME_NOW(&loadtime); + /* + * Lock hierarchy: zmgr, zone, raw. + */ LOCK_ZONE(zone); + if (inline_secure(zone)) + LOCK_ZONE(zone->raw); result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS); + if (inline_secure(zone)) + UNLOCK_ZONE(zone->raw); UNLOCK_ZONE(zone); return result; } + +isc_result_t +dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) { + REQUIRE(DNS_ZONE_VALID(zone)); + if (interval == 0) + return (ISC_R_RANGE); + /* Maximum value: 24 hours (3600 minutes) */ + if (interval > (24 * 60)) + interval = (24 * 60); + /* Multiply by 60 for seconds */ + zone->refreshkeyinterval = interval * 60; + return (ISC_R_SUCCESS); +} + +void +dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->requestixfr = flag; +} + +isc_boolean_t +dns_zone_getrequestixfr(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return (zone->requestixfr); +} + +void +dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) { + REQUIRE(DNS_ZONE_VALID(zone)); + zone->updatemethod = method; +} + +dns_updatemethod_t +dns_zone_getserialupdatemethod(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + return(zone->updatemethod); +} + +/* + * Lock hierarchy: zmgr, zone, raw. + */ +isc_result_t +dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) { + isc_result_t result; + dns_zonemgr_t *zmgr; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(zone->zmgr != NULL); + REQUIRE(zone->task != NULL); + REQUIRE(zone->loadtask != NULL); + REQUIRE(zone->raw == NULL); + + REQUIRE(DNS_ZONE_VALID(raw)); + REQUIRE(raw->zmgr == NULL); + REQUIRE(raw->task == NULL); + REQUIRE(raw->loadtask == NULL); + REQUIRE(raw->secure == NULL); + + /* + * Lock hierarchy: zmgr, zone, raw. + */ + zmgr = zone->zmgr; + RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); + LOCK_ZONE(zone); + LOCK_ZONE(raw); + + result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, + NULL, NULL, zone->task, zone_timer, raw, + &raw->timer); + if (result != ISC_R_SUCCESS) + goto unlock; + + /* + * The timer "holds" a iref. + */ + raw->irefs++; + INSIST(raw->irefs != 0); + + + /* dns_zone_attach(raw, &zone->raw); */ + isc_refcount_increment(&raw->erefs, NULL); + zone->raw = raw; + + /* dns_zone_iattach(zone, &raw->secure); */ + zone_iattach(zone, &raw->secure); + + isc_task_attach(zone->task, &raw->task); + isc_task_attach(zone->loadtask, &raw->loadtask); + + ISC_LIST_APPEND(zmgr->zones, raw, link); + raw->zmgr = zmgr; + zmgr->refs++; + + unlock: + UNLOCK_ZONE(raw); + UNLOCK_ZONE(zone); + RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); + return (result); +} + +void +dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(raw != NULL && *raw == NULL); + + LOCK(&zone->lock); + if (zone->raw != NULL) + dns_zone_attach(zone->raw, raw); + UNLOCK(&zone->lock); +} + +struct keydone { + isc_event_t event; + isc_boolean_t all; + unsigned char data[5]; +}; + +#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL) + +static void +keydone(isc_task_t *task, isc_event_t *event) { + const char *me = "keydone"; + isc_boolean_t commit = ISC_FALSE; + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_dbversion_t *oldver = NULL, *newver = NULL; + dns_zone_t *zone; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_diff_t diff; + struct keydone *keydone = (struct keydone *)event; + dns_update_log_t log = { update_log_cb, NULL }; + isc_boolean_t clear_pending = ISC_FALSE; + + UNUSED(task); + + zone = event->ev_arg; + INSIST(DNS_ZONE_VALID(zone)); + + ENTER; + + dns_rdataset_init(&rdataset); + dns_diff_init(zone->mctx, &diff); + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) { + dns_db_attach(zone->db, &db); + dns_db_currentversion(db, &oldver); + result = dns_db_newversion(db, &newver); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "keydone:dns_db_newversion -> %s", + dns_result_totext(result)); + goto failure; + } + } + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (db == NULL) + goto failure; + + result = dns_db_getoriginnode(db, &node); + if (result != ISC_R_SUCCESS) + goto failure; + + result = dns_db_findrdataset(db, node, newver, zone->privatetype, + dns_rdatatype_none, 0, &rdataset, NULL); + if (result == ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&rdataset)); + goto failure; + } + if (result != ISC_R_SUCCESS) { + INSIST(!dns_rdataset_isassociated(&rdataset)); + goto failure; + } + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + isc_boolean_t found = ISC_FALSE; + + dns_rdataset_current(&rdataset, &rdata); + + if (keydone->all) { + if (rdata.length == 5 && rdata.data[0] != 0 && + rdata.data[3] == 0 && rdata.data[4] == 1) + found = ISC_TRUE; + else if (rdata.data[0] == 0 && + (rdata.data[2] & PENDINGFLAGS) != 0) { + found = ISC_TRUE; + clear_pending = ISC_TRUE; + } + } else if (rdata.length == 5 && + memcmp(rdata.data, keydone->data, 5) == 0) + found = ISC_TRUE; + + if (found) + CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL, + &zone->origin, rdataset.ttl, + &rdata)); + dns_rdata_reset(&rdata); + } + + if (!ISC_LIST_EMPTY(diff.tuples)) { + /* Write changes to journal file. */ + CHECK(update_soa_serial(db, newver, &diff, zone->mctx, + zone->updatemethod)); + + result = dns_update_signatures(&log, zone, db, + oldver, newver, &diff, + zone->sigvalidityinterval); + if (!clear_pending) + CHECK(result); + + CHECK(zone_journal(zone, &diff, NULL, "keydone")); + commit = ISC_TRUE; + + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); + zone_needdump(zone, 30); + UNLOCK_ZONE(zone); + } + + failure: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (db != NULL) { + if (node != NULL) + dns_db_detachnode(db, &node); + if (oldver != NULL) + dns_db_closeversion(db, &oldver, ISC_FALSE); + if (newver != NULL) + dns_db_closeversion(db, &newver, commit); + dns_db_detach(&db); + } + dns_diff_clear(&diff); + isc_event_free(&event); + dns_zone_idetach(&zone); +} + +isc_result_t +dns_zone_keydone(dns_zone_t *zone, const char *keystr) { + isc_result_t result = ISC_R_SUCCESS; + isc_event_t *e; + isc_buffer_t b; + dns_zone_t *dummy = NULL; + struct keydone *kd; + + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + + e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone, + zone, sizeof(struct keydone)); + if (e == NULL) { + result = ISC_R_NOMEMORY; + goto failure; + } + + kd = (struct keydone *) e; + if (strcasecmp(keystr, "all") == 0) + kd->all = ISC_TRUE; + else { + isc_textregion_t r; + char *algstr; + dns_keytag_t keyid; + dns_secalg_t alg; + size_t n; + + kd->all = ISC_FALSE; + + n = sscanf(keystr, "%hd/", &keyid); + if (n == 0U) + CHECK(ISC_R_FAILURE); + + algstr = strchr(keystr, '/'); + if (algstr != NULL) + algstr++; + else + CHECK(ISC_R_FAILURE); + + n = sscanf(algstr, "%hhd", &alg); + if (n == 0U) { + DE_CONST(algstr, r.base); + r.length = strlen(algstr); + CHECK(dns_secalg_fromtext(&alg, &r)); + } + + /* construct a private-type rdata */ + isc_buffer_init(&b, kd->data, sizeof(kd->data)); + isc_buffer_putuint8(&b, alg); + isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8); + isc_buffer_putuint8(&b, (keyid & 0xff)); + isc_buffer_putuint8(&b, 0); + isc_buffer_putuint8(&b, 1); + } + + zone_iattach(zone, &dummy); + isc_task_send(zone->task, &e); + + failure: + if (e != NULL) + isc_event_free(&e); + UNLOCK_ZONE(zone); + return (result); +} + +struct nsec3param { + isc_event_t event; + unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1]; + unsigned int length; + isc_boolean_t nsec; + isc_boolean_t replace; +}; + +static void +setnsec3param(isc_task_t *task, isc_event_t *event) { + const char *me = "setnsec3param"; + isc_boolean_t commit = ISC_FALSE; + isc_result_t result; + dns_dbversion_t *oldver = NULL, *newver = NULL; + dns_zone_t *zone; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t prdataset, nrdataset; + dns_diff_t diff; + struct nsec3param *np = (struct nsec3param *)event; + dns_update_log_t log = { update_log_cb, NULL }; + dns_rdata_t rdata; + isc_boolean_t nseconly; + isc_boolean_t exists = ISC_FALSE; + + UNUSED(task); + + zone = event->ev_arg; + INSIST(DNS_ZONE_VALID(zone)); + + ENTER; + + dns_rdataset_init(&prdataset); + dns_rdataset_init(&nrdataset); + dns_diff_init(zone->mctx, &diff); + + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) { + dns_db_attach(zone->db, &db); + dns_db_currentversion(db, &oldver); + result = dns_db_newversion(db, &newver); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "setnsec3param:dns_db_newversion -> %s", + dns_result_totext(result)); + goto failure; + } + } + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (db == NULL) + goto failure; + + CHECK(dns_db_getoriginnode(db, &node)); + + /* + * Does a private-type record already exist for this chain? + */ + result = dns_db_findrdataset(db, node, newver, zone->privatetype, + dns_rdatatype_none, 0, &prdataset, NULL); + if (result == ISC_R_SUCCESS) { + for (result = dns_rdataset_first(&prdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&prdataset)) { + dns_rdata_init(&rdata); + dns_rdataset_current(&prdataset, &rdata); + + if (np->length == rdata.length && + memcmp(rdata.data, np->data, np->length) == 0) { + exists = ISC_TRUE; + break; + } + } + } else if (result != ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&prdataset)); + goto failure; + } + + /* + * Does the chain already exist? + */ + result = dns_db_findrdataset(db, node, newver, + dns_rdatatype_nsec3param, + dns_rdatatype_none, 0, &nrdataset, NULL); + if (result == ISC_R_SUCCESS) { + for (result = dns_rdataset_first(&nrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&nrdataset)) { + dns_rdata_init(&rdata); + dns_rdataset_current(&nrdataset, &rdata); + + if (np->length == (rdata.length + 1) && + memcmp(rdata.data, np->data + 1, + np->length - 1) == 0) + { + exists = ISC_TRUE; + break; + } + } + } else if (result != ISC_R_NOTFOUND) { + INSIST(!dns_rdataset_isassociated(&nrdataset)); + goto failure; + } + + + /* + * We need to remove any existing NSEC3 chains. + */ + if (!exists && np->replace && (np->length != 0 || np->nsec)) + CHECK(dns_nsec3param_deletechains(db, newver, zone, + !np->nsec, &diff)); + + if (!exists && np->length != 0) { + /* + * We're creating an NSEC3 chain. + * + * If the zone is not currently capable of supporting + * an NSEC3 chain, add the INITIAL flag, so these + * parameters can be used later when NSEC3 becomes + * available. + */ + dns_rdata_init(&rdata); + + np->data[2] |= DNS_NSEC3FLAG_CREATE; + result = dns_nsec_nseconly(db, newver, &nseconly); + if (result == ISC_R_NOTFOUND || nseconly) + np->data[2] |= DNS_NSEC3FLAG_INITIAL; + + rdata.length = np->length; + rdata.data = np->data; + rdata.type = zone->privatetype; + rdata.rdclass = zone->rdclass; + CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD, + &zone->origin, 0, &rdata)); + } + + if (!ISC_LIST_EMPTY(diff.tuples)) { + /* Write changes to journal file. */ + CHECK(update_soa_serial(db, newver, &diff, zone->mctx, + zone->updatemethod)); + result = dns_update_signatures(&log, zone, db, + oldver, newver, &diff, + zone->sigvalidityinterval); + if (result != ISC_R_NOTFOUND) + CHECK(result); + CHECK(zone_journal(zone, &diff, NULL, "setnsec3param")); + commit = ISC_TRUE; + + LOCK_ZONE(zone); + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED); + zone_needdump(zone, 30); + UNLOCK_ZONE(zone); + } + + failure: + if (dns_rdataset_isassociated(&prdataset)) + dns_rdataset_disassociate(&prdataset); + if (dns_rdataset_isassociated(&nrdataset)) + dns_rdataset_disassociate(&nrdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + if (oldver != NULL) + dns_db_closeversion(db, &oldver, ISC_FALSE); + if (newver != NULL) + dns_db_closeversion(db, &newver, commit); + if (db != NULL) + dns_db_detach(&db); + if (commit) + resume_addnsec3chain(zone); + dns_diff_clear(&diff); + isc_event_free(&event); + dns_zone_idetach(&zone); +} + +isc_result_t +dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags, + isc_uint16_t iter, isc_uint8_t saltlen, + unsigned char *salt, isc_boolean_t replace) +{ + isc_result_t result = ISC_R_SUCCESS; + dns_rdata_nsec3param_t param; + dns_rdata_t nrdata = DNS_RDATA_INIT; + dns_rdata_t prdata = DNS_RDATA_INIT; + unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE]; + struct nsec3param *np; + dns_zone_t *dummy = NULL; + isc_buffer_t b; + isc_event_t *e; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(salt != NULL); + + LOCK_ZONE(zone); + + e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM, + setnsec3param, zone, sizeof(struct nsec3param)); + if (e == NULL) { + result = ISC_R_NOMEMORY; + goto failure; + } + + np = (struct nsec3param *) e; + np->replace = replace; + if (hash == 0) { + np->length = 0; + np->nsec = ISC_TRUE; + } else { + param.common.rdclass = zone->rdclass; + param.common.rdtype = dns_rdatatype_nsec3param; + ISC_LINK_INIT(¶m.common, link); + param.mctx = NULL; + param.hash = hash; + param.flags = flags; + param.iterations = iter; + param.salt_length = saltlen; + param.salt = salt; + isc_buffer_init(&b, nbuf, sizeof(nbuf)); + CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass, + dns_rdatatype_nsec3param, + ¶m, &b)); + dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype, + np->data, sizeof(np->data)); + np->length = prdata.length; + } + + zone_iattach(zone, &dummy); + isc_task_send(zone->task, &e); + + failure: + if (e != NULL) + isc_event_free(&e); + UNLOCK_ZONE(zone); + return (result); +} + +void +dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) { + REQUIRE(DNS_ZONE_VALID(zone)); + + zone->statlevel = level; +} + +dns_zonestat_level_t +dns_zone_getstatlevel(dns_zone_t *zone) { + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->statlevel); +} diff --git a/contrib/bind9/lib/dns/zt.c b/contrib/bind9/lib/dns/zt.c index 650d46bf9002..eb1e42472475 100644 --- a/contrib/bind9/lib/dns/zt.c +++ b/contrib/bind9/lib/dns/zt.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -42,8 +43,12 @@ struct dns_zt { isc_mem_t *mctx; dns_rdataclass_t rdclass; isc_rwlock_t rwlock; + dns_zt_allloaded_t loaddone; + void * loaddone_arg; /* Locked by lock. */ + isc_boolean_t flush; isc_uint32_t references; + unsigned int loads_pending; dns_rbt_t *table; }; @@ -56,12 +61,18 @@ auto_detach(void *, void *); static isc_result_t load(dns_zone_t *zone, void *uap); +static isc_result_t +asyncload(dns_zone_t *zone, void *callback); + static isc_result_t loadnew(dns_zone_t *zone, void *uap); static isc_result_t freezezones(dns_zone_t *zone, void *uap); +static isc_result_t +doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task); + isc_result_t dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) { @@ -83,10 +94,15 @@ dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp) if (result != ISC_R_SUCCESS) goto cleanup_rbt; - zt->mctx = mctx; + zt->mctx = NULL; + isc_mem_attach(mctx, &zt->mctx); zt->references = 1; + zt->flush = ISC_FALSE; zt->rdclass = rdclass; zt->magic = ZTMAGIC; + zt->loaddone = NULL; + zt->loaddone_arg = NULL; + zt->loads_pending = 0; *ztp = zt; return (ISC_R_SUCCESS); @@ -187,6 +203,16 @@ flush(dns_zone_t *zone, void *uap) { return (dns_zone_flush(zone)); } +static void +zt_destroy(dns_zt_t *zt) { + if (zt->flush) + (void)dns_zt_apply(zt, ISC_FALSE, flush, NULL); + dns_rbt_destroy(&zt->table); + isc_rwlock_destroy(&zt->rwlock); + zt->magic = 0; + isc_mem_putanddetach(&zt->mctx, zt, sizeof(*zt)); +} + static void zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) { isc_boolean_t destroy = ISC_FALSE; @@ -202,17 +228,13 @@ zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) { zt->references--; if (zt->references == 0) destroy = ISC_TRUE; + if (need_flush) + zt->flush = ISC_TRUE; RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); - if (destroy) { - if (need_flush) - (void)dns_zt_apply(zt, ISC_FALSE, flush, NULL); - dns_rbt_destroy(&zt->table); - isc_rwlock_destroy(&zt->rwlock); - zt->magic = 0; - isc_mem_put(zt->mctx, zt, sizeof(*zt)); - } + if (destroy) + zt_destroy(zt); *ztp = NULL; } @@ -243,12 +265,66 @@ static isc_result_t load(dns_zone_t *zone, void *uap) { isc_result_t result; UNUSED(uap); + result = dns_zone_load(zone); if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE) result = ISC_R_SUCCESS; + return (result); } +isc_result_t +dns_zt_asyncload(dns_zt_t *zt, dns_zt_allloaded_t alldone, void *arg) { + isc_result_t result; + static dns_zt_zoneloaded_t dl = doneloading; + int pending; + + REQUIRE(VALID_ZT(zt)); + + RWLOCK(&zt->rwlock, isc_rwlocktype_write); + + INSIST(zt->loads_pending == 0); + result = dns_zt_apply2(zt, ISC_FALSE, NULL, asyncload, &dl); + + pending = zt->loads_pending; + if (pending != 0) { + zt->loaddone = alldone; + zt->loaddone_arg = arg; + } + + RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); + + if (pending == 0) + alldone(arg); + + return (result); +} + +/* + * Initiates asynchronous loading of zone 'zone'. 'callback' is a + * pointer to a function which will be used to inform the caller when + * the zone loading is complete. + */ +static isc_result_t +asyncload(dns_zone_t *zone, void *callback) { + isc_result_t result; + dns_zt_zoneloaded_t *loaded = callback; + dns_zt_t *zt; + + REQUIRE(zone != NULL); + zt = dns_zone_getview(zone)->zonetable; + INSIST(VALID_ZT(zt)); + + result = dns_zone_asyncload(zone, *loaded, zt); + if (result == ISC_R_SUCCESS) { + INSIST(zt->references > 0); + zt->references++; + INSIST(zt->references != 0); + zt->loads_pending++; + } + return (ISC_R_SUCCESS); +} + isc_result_t dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop) { isc_result_t result; @@ -265,6 +341,7 @@ static isc_result_t loadnew(dns_zone_t *zone, void *uap) { isc_result_t result; UNUSED(uap); + result = dns_zone_loadnew(zone); if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE || result == DNS_R_DYNAMIC) @@ -281,6 +358,8 @@ dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze) { RWLOCK(&zt->rwlock, isc_rwlocktype_read); result = dns_zt_apply2(zt, ISC_FALSE, &tresult, freezezones, &freeze); RWUNLOCK(&zt->rwlock, isc_rwlocktype_read); + if (tresult == ISC_R_NOTFOUND) + tresult = ISC_R_SUCCESS; return ((result == ISC_R_SUCCESS) ? tresult : result); } @@ -291,14 +370,25 @@ freezezones(dns_zone_t *zone, void *uap) { isc_result_t result = ISC_R_SUCCESS; char classstr[DNS_RDATACLASS_FORMATSIZE]; char zonename[DNS_NAME_FORMATSIZE]; + dns_zone_t *raw = NULL; dns_view_t *view; - char *journal; const char *vname; const char *sep; int level; - if (dns_zone_gettype(zone) != dns_zone_master) + dns_zone_getraw(zone, &raw); + if (raw != NULL) + zone = raw; + if (dns_zone_gettype(zone) != dns_zone_master) { + if (raw != NULL) + dns_zone_detach(&raw); return (ISC_R_SUCCESS); + } + if (!dns_zone_isdynamic(zone, ISC_TRUE)) { + if (raw != NULL) + dns_zone_detach(&raw); + return (ISC_R_SUCCESS); + } frozen = dns_zone_getupdatedisabled(zone); if (freeze) { @@ -306,11 +396,6 @@ freezezones(dns_zone_t *zone, void *uap) { result = DNS_R_FROZEN; if (result == ISC_R_SUCCESS) result = dns_zone_flush(zone); - if (result == ISC_R_SUCCESS) { - journal = dns_zone_getjournal(zone); - if (journal != NULL) - (void)isc_file_remove(journal); - } } else { if (frozen) { result = dns_zone_load(zone); @@ -340,6 +425,8 @@ freezezones(dns_zone_t *zone, void *uap) { freeze ? "freezing" : "thawing", zonename, classstr, sep, vname, isc_result_totext(result)); + if (raw != NULL) + dns_zone_detach(&raw); return (result); } @@ -368,6 +455,7 @@ dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub, /* * The tree is empty. */ + tresult = result; result = ISC_R_NOMORE; } while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) { @@ -397,6 +485,46 @@ dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub, return (result); } +/* + * Decrement the loads_pending counter; when counter reaches + * zero, call the loaddone callback that was initially set by + * dns_zt_asyncload(). + */ +static isc_result_t +doneloading(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) { + isc_boolean_t destroy = ISC_FALSE; + dns_zt_allloaded_t alldone = NULL; + void *arg = NULL; + + UNUSED(zone); + UNUSED(task); + + REQUIRE(VALID_ZT(zt)); + + RWLOCK(&zt->rwlock, isc_rwlocktype_write); + INSIST(zt->loads_pending != 0); + INSIST(zt->references != 0); + zt->references--; + if (zt->references == 0) + destroy = ISC_TRUE; + zt->loads_pending--; + if (zt->loads_pending == 0) { + alldone = zt->loaddone; + arg = zt->loaddone_arg; + zt->loaddone = NULL; + zt->loaddone_arg = NULL; + } + RWUNLOCK(&zt->rwlock, isc_rwlocktype_write); + + if (alldone != NULL) + alldone(arg); + + if (destroy) + zt_destroy(zt); + + return (ISC_R_SUCCESS); +} + /*** *** Private ***/ diff --git a/contrib/bind9/lib/irs/api b/contrib/bind9/lib/irs/api index 5c8dd5e14db7..298e96a8abc9 100644 --- a/contrib/bind9/lib/irs/api +++ b/contrib/bind9/lib/irs/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 80 -LIBREVISION = 4 +LIBINTERFACE = 90 +LIBREVISION = 1 LIBAGE = 0 diff --git a/contrib/bind9/lib/isc/Makefile.in b/contrib/bind9/lib/isc/Makefile.in index 2fa563358515..e68290cd2975 100644 --- a/contrib/bind9/lib/isc/Makefile.in +++ b/contrib/bind9/lib/isc/Makefile.in @@ -58,7 +58,7 @@ OBJS = @ISC_EXTRA_OBJS@ \ httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ md5.@O@ mem.@O@ mutexblock.@O@ \ - netaddr.@O@ netscope.@O@ ondestroy.@O@ \ + netaddr.@O@ netscope.@O@ pool.@O@ ondestroy.@O@ \ parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \ ratelimiter.@O@ refcount.@O@ region.@O@ regex.@O@ result.@O@ \ rwlock.@O@ \ @@ -75,7 +75,7 @@ SRCS = @ISC_EXTRA_SRCS@ \ httpd.c inet_aton.c iterated_hash.c \ lex.c lfsr.c lib.c log.c \ md5.c mem.c mutexblock.c \ - netaddr.c netscope.c ondestroy.c \ + netaddr.c netscope.c pool.c ondestroy.c \ parseint.c portset.c quota.c radix.c random.c \ ratelimiter.c refcount.c region.c regex.c result.c rwlock.c \ serial.c sha1.c sha2.c sockaddr.c stats.c string.c strtoul.c \ diff --git a/contrib/bind9/lib/isc/api b/contrib/bind9/lib/isc/api index c7d281344cf1..48bc766d9378 100644 --- a/contrib/bind9/lib/isc/api +++ b/contrib/bind9/lib/isc/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 87 +LIBINTERFACE = 95 LIBREVISION = 1 -LIBAGE = 3 +LIBAGE = 0 diff --git a/contrib/bind9/lib/isc/include/isc/heap.h b/contrib/bind9/lib/isc/include/isc/heap.h index 77bf07c34498..0b3a53b01ef5 100644 --- a/contrib/bind9/lib/isc/include/isc/heap.h +++ b/contrib/bind9/lib/isc/include/isc/heap.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -60,6 +60,8 @@ isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare, * storage method. When the heap elements are deleted space is not freed * but will be reused when new elements are inserted. * + * Heap elements are indexed from 1. + * * Requires: *\li "mctx" is valid. *\li "compare" is a function which takes two void * arguments and diff --git a/contrib/bind9/lib/isc/include/isc/list.h b/contrib/bind9/lib/isc/include/isc/list.h index 2b174eca575c..401bbdad756c 100644 --- a/contrib/bind9/lib/isc/include/isc/list.h +++ b/contrib/bind9/lib/isc/include/isc/list.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2006, 2007, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -171,6 +171,19 @@ (list2).tail = NULL; \ } while (0) +#define ISC_LIST_PREPENDLIST(list1, list2, link) \ + do { \ + if (ISC_LIST_EMPTY(list1)) \ + (list1) = (list2); \ + else if (!ISC_LIST_EMPTY(list2)) { \ + (list2).tail->link.next = (list1).head; \ + (list1).head->link.prev = (list2).tail; \ + (list1).head = (list2).head; \ + } \ + (list2).head = NULL; \ + (list2).tail = NULL; \ + } while (0) + #define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link) #define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \ __ISC_LIST_APPENDUNSAFE(list, elt, link) diff --git a/contrib/bind9/lib/isc/include/isc/mem.h b/contrib/bind9/lib/isc/include/isc/mem.h index 317417f63663..320d0d83138b 100644 --- a/contrib/bind9/lib/isc/include/isc/mem.h +++ b/contrib/bind9/lib/isc/include/isc/mem.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -317,7 +317,7 @@ isc_mem_createx2(size_t max_size, size_t target_size, * ISC_MEMFLAG_INTERNAL is not set, 'target_size' is ignored. * * 'max_size' is also used to size the statistics arrays and the array - * used to record active memory when ISC_MEM_DEBUGRECORD is set. Settin + * used to record active memory when ISC_MEM_DEBUGRECORD is set. Setting * 'max_size' too low can have detrimental effects on performance. * * A memory context created using isc_mem_createx() will obtain diff --git a/contrib/bind9/lib/isc/include/isc/namespace.h b/contrib/bind9/lib/isc/include/isc/namespace.h index 45b769c5eeb5..f8744d8ad635 100644 --- a/contrib/bind9/lib/isc/include/isc/namespace.h +++ b/contrib/bind9/lib/isc/include/isc/namespace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -31,6 +31,7 @@ #define isc_app_run isc__app_run #define isc_app_ctxrun isc__app_ctxrun #define isc_app_shutdown isc__app_shutdown +#define isc_app_ctxfinish isc__app_ctxfinish #define isc_app_ctxshutdown isc__app_ctxshutdown #define isc_app_ctxsuspend isc__app_ctxsuspend #define isc_app_reload isc__app_reload @@ -89,6 +90,7 @@ #define isc_mempool_getfillcount isc__mempool_getfillcount #define isc_socket_create isc__socket_create +#define isc_socket_dup isc__socket_dup #define isc_socket_attach isc__socket_attach #define isc_socket_detach isc__socket_detach #define isc_socketmgr_create isc__socketmgr_create @@ -111,6 +113,7 @@ #define isc_socket_listen isc__socket_listen #define isc_socket_accept isc__socket_accept #define isc_socket_connect isc__socket_connect +#define isc_socket_getfd isc__socket_getfd #define isc_socket_getname isc__socket_getname #define isc_socket_gettag isc__socket_gettag #define isc_socket_getpeername isc__socket_getpeername @@ -146,11 +149,15 @@ #define isc_task_gettag isc__task_gettag #define isc_task_getcurrenttime isc__task_getcurrenttime #define isc_taskmgr_create isc__taskmgr_create +#define isc_taskmgr_setmode isc__taskmgr_setmode +#define isc_taskmgr_mode isc__taskmgr_mode #define isc_taskmgr_destroy isc__taskmgr_destroy #define isc_taskmgr_setexcltask isc__taskmgr_setexcltask #define isc_taskmgr_excltask isc__taskmgr_excltask #define isc_task_beginexclusive isc__task_beginexclusive #define isc_task_endexclusive isc__task_endexclusive +#define isc_task_setprivilege isc__task_setprivilege +#define isc_task_privilege isc__task_privilege #define isc_timer_create isc__timer_create #define isc_timer_reset isc__timer_reset diff --git a/contrib/bind9/lib/isc/include/isc/pool.h b/contrib/bind9/lib/isc/include/isc/pool.h new file mode 100644 index 000000000000..7b33c37bb791 --- /dev/null +++ b/contrib/bind9/lib/isc/include/isc/pool.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ISC_OBJPOOL_H +#define ISC_OBJPOOL_H 1 + +/***** + ***** Module Info + *****/ + +/*! \file isc/pool.h + * \brief An object pool is a mechanism for sharing a small pool of + * fungible objects among a large number of objects that depend on them. + * + * This is useful, for example, when it causes performance problems for + * large number of zones to share a single memory context or task object, + * but it would create a different set of problems for them each to have an + * independent task or memory context. + */ + + +/*** + *** Imports. + ***/ + +#include +#include +#include + +ISC_LANG_BEGINDECLS + +/***** + ***** Types. + *****/ + +typedef void +(*isc_pooldeallocator_t)(void **object); + +typedef isc_result_t +(*isc_poolinitializer_t)(void **target, void *arg); + +typedef struct isc_pool isc_pool_t; + +/***** + ***** Functions. + *****/ + +isc_result_t +isc_pool_create(isc_mem_t *mctx, unsigned int count, + isc_pooldeallocator_t free, + isc_poolinitializer_t init, void *initarg, + isc_pool_t **poolp); +/*%< + * Create a pool of "count" object pointers. If 'free' is not NULL, + * it points to a function that will detach the objects. 'init' + * points to a function that will initialize the arguments, and + * 'arg' to an argument to be passed into that function (for example, + * a relevant manager or context object). + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li init != NULL + * + *\li poolp != NULL && *poolp == NULL + * + * Ensures: + * + *\li On success, '*poolp' points to the new object pool. + * + * Returns: + * + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOMEMORY + *\li #ISC_R_UNEXPECTED + */ + +void * +isc_pool_get(isc_pool_t *pool); +/*%< + * Returns a pointer to an object from the pool. Currently the object + * is chosen from the pool at random. (This may be changed in the future + * to something that guaratees balance.) + */ + +int +isc_pool_count(isc_pool_t *pool); +/*%< + * Returns the number of objcts in the pool 'pool'. + */ + +isc_result_t +isc_pool_expand(isc_pool_t **sourcep, unsigned int count, isc_pool_t **targetp); + +/*%< + * If 'size' is larger than the number of objects in the pool pointed to by + * 'sourcep', then a new pool of size 'count' is allocated, the existing + * objects are copied into it, additional ones created to bring the + * total number up to 'count', and the resulting pool is attached to + * 'targetp'. + * + * If 'count' is less than or equal to the number of objects in 'source', then + * 'sourcep' is attached to 'targetp' without any other action being taken. + * + * In either case, 'sourcep' is detached. + * + * Requires: + * + * \li 'sourcep' is not NULL and '*source' is not NULL + * \li 'targetp' is not NULL and '*source' is NULL + * + * Ensures: + * + * \li On success, '*targetp' points to a valid task pool. + * \li On success, '*sourcep' points to NULL. + * + * Returns: + * + * \li #ISC_R_SUCCESS + * \li #ISC_R_NOMEMORY + */ + +void +isc_pool_destroy(isc_pool_t **poolp); +/*%< + * Destroy a task pool. The tasks in the pool are detached but not + * shut down. + * + * Requires: + * \li '*poolp' is a valid task pool. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_OBJPOOL_H */ diff --git a/contrib/bind9/lib/isc/include/isc/queue.h b/contrib/bind9/lib/isc/include/isc/queue.h new file mode 100644 index 000000000000..1cc6c12a4f10 --- /dev/null +++ b/contrib/bind9/lib/isc/include/isc/queue.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +/* + * This is a generic implementation of a two-lock concurrent queue. + * There are built-in mutex locks for the head and tail of the queue, + * allowing elements to be safely added and removed at the same time. + * + * NULL is "end of list" + * -1 is "not linked" + */ + +#ifndef ISC_QUEUE_H +#define ISC_QUEUE_H 1 +#include +#include +#include + +#ifdef ISC_QUEUE_CHECKINIT +#define ISC_QLINK_INSIST(x) ISC_INSIST(x) +#else +#define ISC_QLINK_INSIST(x) (void)0 +#endif + +#define ISC_QLINK(type) struct { type *prev, *next; } + +#define ISC_QLINK_INIT(elt, link) \ + do { \ + (elt)->link.next = (elt)->link.prev = (void *)(-1); \ + } while(0) + +#define ISC_QLINK_LINKED(elt, link) ((void*)(elt)->link.next != (void*)(-1)) + +#define ISC_QUEUE(type) struct { \ + type *head, *tail; \ + isc_mutex_t headlock, taillock; \ +} + +#define ISC_QUEUE_INIT(queue, link) \ + do { \ + (void) isc_mutex_init(&(queue).taillock); \ + (void) isc_mutex_init(&(queue).headlock); \ + (queue).tail = (queue).head = NULL; \ + } while (0) + +#define ISC_QUEUE_EMPTY(queue) ISC_TF((queue).head == NULL) + +#define ISC_QUEUE_DESTROY(queue) \ + do { \ + ISC_QLINK_INSIST(ISC_QUEUE_EMPTY(queue)); \ + (void) isc_mutex_destroy(&(queue).taillock); \ + (void) isc_mutex_destroy(&(queue).headlock); \ + } while (0) + +/* + * queues are meant to separate the locks at either end. For best effect, that + * means keeping the ends separate - i.e. non-empty queues work best. + * + * a push to an empty queue has to take the pop lock to update + * the pop side of the queue. + * Popping the last entry has to take the push lock to update + * the push side of the queue. + * + * The order is (pop, push), because a pop is presumably in the + * latency path and a push is when we're done. + * + * We do an MT hot test in push to see if we need both locks, so we can + * acquire them in order. Hopefully that makes the case where we get + * the push lock and find we need the pop lock (and have to release it) rare. + * + * > 1 entry - no collision, push works on one end, pop on the other + * 0 entry - headlock race + * pop wins - return(NULL), push adds new as both head/tail + * push wins - updates head/tail, becomes 1 entry case. + * 1 entry - taillock race + * pop wins - return(pop) sets head/tail NULL, becomes 0 entry case + * push wins - updates {head,tail}->link.next, pop updates head + * with new ->link.next and doesn't update tail + * + */ +#define ISC_QUEUE_PUSH(queue, elt, link) \ + do { \ + isc_boolean_t headlocked = ISC_FALSE; \ + ISC_QLINK_INSIST(!ISC_QLINK_LINKED(elt, link)); \ + if ((queue).head == NULL) { \ + LOCK(&(queue).headlock); \ + headlocked = ISC_TRUE; \ + } \ + LOCK(&(queue).taillock); \ + if ((queue).tail == NULL && !headlocked) { \ + UNLOCK(&(queue).taillock); \ + LOCK(&(queue).headlock); \ + LOCK(&(queue).taillock); \ + headlocked = ISC_TRUE; \ + } \ + (elt)->link.prev = (queue).tail; \ + (elt)->link.next = NULL; \ + if ((queue).tail != NULL) \ + (queue).tail->link.next = (elt); \ + (queue).tail = (elt); \ + UNLOCK(&(queue).taillock); \ + if (headlocked) { \ + if ((queue).head == NULL) \ + (queue).head = (elt); \ + UNLOCK(&(queue).headlock); \ + } \ + } while (0) + +#define ISC_QUEUE_POP(queue, link, ret) \ + do { \ + LOCK(&(queue).headlock); \ + ret = (queue).head; \ + while (ret != NULL) { \ + if (ret->link.next == NULL) { \ + LOCK(&(queue).taillock); \ + if (ret->link.next == NULL) { \ + (queue).head = (queue).tail = NULL; \ + UNLOCK(&(queue).taillock); \ + break; \ + }\ + UNLOCK(&(queue).taillock); \ + } \ + (queue).head = ret->link.next; \ + (queue).head->link.prev = NULL; \ + break; \ + } \ + UNLOCK(&(queue).headlock); \ + if (ret != NULL) \ + (ret)->link.next = (ret)->link.prev = (void *)(-1); \ + } while(0) + +#define ISC_QUEUE_UNLINK(queue, elt, link) \ + do { \ + ISC_QLINK_INSIST(ISC_QLINK_LINKED(elt, link)); \ + LOCK(&(queue).headlock); \ + LOCK(&(queue).taillock); \ + if ((elt)->link.prev == NULL) \ + (queue).head = (elt)->link.next; \ + else \ + (elt)->link.prev->link.next = (elt)->link.next; \ + if ((elt)->link.next == NULL) \ + (queue).tail = (elt)->link.prev; \ + else \ + (elt)->link.next->link.prev = (elt)->link.prev; \ + UNLOCK(&(queue).taillock); \ + UNLOCK(&(queue).headlock); \ + (elt)->link.next = (elt)->link.prev = (void *)(-1); \ + } while(0) + +#endif /* ISC_QUEUE_H */ diff --git a/contrib/bind9/lib/isc/include/isc/radix.h b/contrib/bind9/lib/isc/include/isc/radix.h index 6b413a23b909..47512c722885 100644 --- a/contrib/bind9/lib/isc/include/isc/radix.h +++ b/contrib/bind9/lib/isc/include/isc/radix.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2007, 2008, 2013 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -54,13 +54,14 @@ } while(0) typedef struct isc_prefix { - unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */ - unsigned int bitlen; /* 0 for "any" */ - isc_refcount_t refcount; - union { + isc_mem_t *mctx; + unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */ + unsigned int bitlen; /* 0 for "any" */ + isc_refcount_t refcount; + union { struct in_addr sin; struct in6_addr sin6; - } add; + } add; } isc_prefix_t; typedef void (*isc_radix_destroyfunc_t)(void *); @@ -90,12 +91,13 @@ typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **); #define ISC_IS6(family) ((family) == AF_INET6 ? 1 : 0) typedef struct isc_radix_node { - isc_uint32_t bit; /* bit length of the prefix */ - isc_prefix_t *prefix; /* who we are in radix tree */ - struct isc_radix_node *l, *r; /* left and right children */ - struct isc_radix_node *parent; /* may be used */ - void *data[2]; /* pointers to IPv4 and IPV6 data */ - int node_num[2]; /* which node this was in the tree, + isc_mem_t *mctx; + isc_uint32_t bit; /* bit length of the prefix */ + isc_prefix_t *prefix; /* who we are in radix tree */ + struct isc_radix_node *l, *r; /* left and right children */ + struct isc_radix_node *parent; /* may be used */ + void *data[2]; /* pointers to IPv4 and IPV6 data */ + int node_num[2]; /* which node this was in the tree, or -1 for glue nodes */ } isc_radix_node_t; @@ -103,12 +105,12 @@ typedef struct isc_radix_node { #define RADIX_TREE_VALID(a) ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC); typedef struct isc_radix_tree { - unsigned int magic; - isc_mem_t *mctx; - isc_radix_node_t *head; - isc_uint32_t maxbits; /* for IP, 32 bit addresses */ - int num_active_node; /* for debugging purposes */ - int num_added_node; /* total number of nodes */ + unsigned int magic; + isc_mem_t *mctx; + isc_radix_node_t *head; + isc_uint32_t maxbits; /* for IP, 32 bit addresses */ + int num_active_node; /* for debugging purposes */ + int num_added_node; /* total number of nodes */ } isc_radix_tree_t; isc_result_t diff --git a/contrib/bind9/lib/isc/include/isc/socket.h b/contrib/bind9/lib/isc/include/isc/socket.h index 4111ec2c6bed..9d086b452012 100644 --- a/contrib/bind9/lib/isc/include/isc/socket.h +++ b/contrib/bind9/lib/isc/include/isc/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -283,12 +283,20 @@ typedef struct isc_socketmethods { isc_task_t *task, isc_taskaction_t action, const void *arg, isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); + isc_result_t (*sendto2)(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_sockaddr_t *address, + struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, + unsigned int flags); isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task, isc_taskaction_t action, const void *arg); isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, isc_task_t *task, isc_taskaction_t action, const void *arg); + isc_result_t (*recv2)(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags); void (*cancel)(isc_socket_t *sock, isc_task_t *task, unsigned int how); isc_result_t (*getsockname)(isc_socket_t *sock, @@ -296,6 +304,9 @@ typedef struct isc_socketmethods { isc_sockettype_t (*gettype)(isc_socket_t *sock); void (*ipv6only)(isc_socket_t *sock, isc_boolean_t yes); isc_result_t (*fdwatchpoke)(isc_socket_t *sock, int flags); + isc_result_t (*dup)(isc_socket_t *socket, + isc_socket_t **socketp); + int (*getfd)(isc_socket_t *socket); } isc_socketmethods_t; /*% @@ -449,6 +460,12 @@ isc_socket_create(isc_socketmgr_t *manager, *\li #ISC_R_UNEXPECTED */ +isc_result_t +isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp); +/*%< + * Duplicate an existing socket, reusing its file descriptor. + */ + void isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); @@ -1102,6 +1119,11 @@ void *isc_socket_gettag(isc_socket_t *socket); * Get the tag associated with a socket, if any. */ +int isc_socket_getfd(isc_socket_t *socket); +/*%< + * Get the file descriptor associated with a socket + */ + void isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t); /*%< diff --git a/contrib/bind9/lib/isc/include/isc/task.h b/contrib/bind9/lib/isc/include/isc/task.h index ced70590b167..7abf2ef2be60 100644 --- a/contrib/bind9/lib/isc/include/isc/task.h +++ b/contrib/bind9/lib/isc/include/isc/task.h @@ -88,6 +88,7 @@ #define ISC_TASKEVENT_FIRSTEVENT (ISC_EVENTCLASS_TASK + 0) #define ISC_TASKEVENT_SHUTDOWN (ISC_EVENTCLASS_TASK + 1) +#define ISC_TASKEVENT_TEST (ISC_EVENTCLASS_TASK + 1) #define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535) /***** @@ -100,9 +101,17 @@ ISC_LANG_BEGINDECLS *** Types ***/ +typedef enum { + isc_taskmgrmode_normal = 0, + isc_taskmgrmode_privileged +} isc_taskmgrmode_t; + /*% Task and task manager methods */ typedef struct isc_taskmgrmethods { void (*destroy)(isc_taskmgr_t **managerp); + void (*setmode)(isc_taskmgr_t *manager, + isc_taskmgrmode_t mode); + isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager); isc_result_t (*taskcreate)(isc_taskmgr_t *manager, unsigned int quantum, isc_task_t **taskp); @@ -129,6 +138,8 @@ typedef struct isc_taskmethods { void *tag); isc_result_t (*beginexclusive)(isc_task_t *task); void (*endexclusive)(isc_task_t *task); + void (*setprivilege)(isc_task_t *task, isc_boolean_t priv); + isc_boolean_t (*privilege)(isc_task_t *task); } isc_taskmethods_t; /*% @@ -613,6 +624,32 @@ isc_task_exiting(isc_task_t *t); *\li 'task' is a valid task. */ +void +isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv); +/*%< + * Set or unset the task's "privileged" flag depending on the value of + * 'priv'. + * + * Under normal circumstances this flag has no effect on the task behavior, + * but when the task manager has been set to privileged exeuction mode via + * isc_taskmgr_setmode(), only tasks with the flag set will be executed, + * and all other tasks will wait until they're done. Once all privileged + * tasks have finished executing, the task manager will automatically + * return to normal execution mode and nonprivileged task can resume. + * + * Requires: + *\li 'task' is a valid task. + */ + +isc_boolean_t +isc_task_privilege(isc_task_t *task); +/*%< + * Returns the current value of the task's privilege flag. + * + * Requires: + *\li 'task' is a valid task. + */ + /***** ***** Task Manager. *****/ @@ -665,6 +702,31 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, * manager shutting down. */ +void +isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode); + +isc_taskmgrmode_t +isc_taskmgr_mode(isc_taskmgr_t *manager); +/*%< + * Set/get the current operating mode of the task manager. Valid modes are: + * + *\li isc_taskmgrmode_normal + *\li isc_taskmgrmode_privileged + * + * In privileged execution mode, only tasks that have had the "privilege" + * flag set via isc_task_setprivilege() can be executed. When all such + * tasks are complete, the manager automatically returns to normal mode + * and proceeds with running non-privileged ready tasks. This means it is + * necessary to have at least one privileged task waiting on the ready + * queue *before* setting the manager into privileged execution mode, + * which in turn means the task which calls this function should be in + * task-exclusive mode when it does so. + * + * Requires: + * + *\li 'manager' is a valid task manager. + */ + void isc_taskmgr_destroy(isc_taskmgr_t **managerp); /*%< diff --git a/contrib/bind9/lib/isc/include/isc/taskpool.h b/contrib/bind9/lib/isc/include/isc/taskpool.h index 64c739a211ab..46f395ea246f 100644 --- a/contrib/bind9/lib/isc/include/isc/taskpool.h +++ b/contrib/bind9/lib/isc/include/isc/taskpool.h @@ -139,6 +139,19 @@ isc_taskpool_destroy(isc_taskpool_t **poolp); * \li '*poolp' is a valid task pool. */ +void +isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv); +/*%< + * Set the privilege flag on all tasks in 'pool' to 'priv'. If 'priv' is + * true, then when the task manager is set into privileged mode, only + * tasks wihin this pool will be able to execute. (Note: It is important + * to turn the pool tasks' privilege back off before the last task finishes + * executing.) + * + * Requires: + * \li 'pool' is a valid task pool. + */ + ISC_LANG_ENDDECLS #endif /* ISC_TASKPOOL_H */ diff --git a/contrib/bind9/lib/isc/log.c b/contrib/bind9/lib/isc/log.c index f1c925cd3fc4..024d97c6a9ff 100644 --- a/contrib/bind9/lib/isc/log.c +++ b/contrib/bind9/lib/isc/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -275,7 +275,8 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) { lctx = isc_mem_get(mctx, sizeof(*lctx)); if (lctx != NULL) { - lctx->mctx = mctx; + lctx->mctx = NULL; + isc_mem_attach(mctx, &lctx->mctx); lctx->categories = NULL; lctx->category_count = 0; lctx->modules = NULL; @@ -286,7 +287,7 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) { result = isc_mutex_init(&lctx->lock); if (result != ISC_R_SUCCESS) { - isc_mem_put(mctx, lctx, sizeof(*lctx)); + isc_mem_putanddetach(&mctx, lctx, sizeof(*lctx)); return (result); } @@ -493,7 +494,7 @@ isc_log_destroy(isc_log_t **lctxp) { lctx->mctx = NULL; lctx->magic = 0; - isc_mem_put(mctx, lctx, sizeof(*lctx)); + isc_mem_putanddetach(&mctx, lctx, sizeof(*lctx)); *lctxp = NULL; } diff --git a/contrib/bind9/lib/isc/pool.c b/contrib/bind9/lib/isc/pool.c new file mode 100644 index 000000000000..509abcb418d4 --- /dev/null +++ b/contrib/bind9/lib/isc/pool.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id$ */ + +/*! \file */ + +#include + +#include + +#include +#include +#include +#include + +/*** + *** Types. + ***/ + +struct isc_pool { + isc_mem_t * mctx; + unsigned int count; + isc_pooldeallocator_t free; + isc_poolinitializer_t init; + void * initarg; + void ** pool; +}; + +/*** + *** Functions. + ***/ + +static isc_result_t +alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) { + isc_pool_t *pool; + + pool = isc_mem_get(mctx, sizeof(*pool)); + if (pool == NULL) + return (ISC_R_NOMEMORY); + pool->count = count; + pool->free = NULL; + pool->init = NULL; + pool->initarg = NULL; + pool->mctx = NULL; + isc_mem_attach(mctx, &pool->mctx); + pool->pool = isc_mem_get(mctx, count * sizeof(void *)); + if (pool->pool == NULL) { + isc_mem_put(mctx, pool, sizeof(*pool)); + return (ISC_R_NOMEMORY); + } + memset(pool->pool, 0, count * sizeof(void *)); + + *poolp = pool; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_pool_create(isc_mem_t *mctx, unsigned int count, + isc_pooldeallocator_t free, + isc_poolinitializer_t init, void *initarg, + isc_pool_t **poolp) +{ + isc_pool_t *pool = NULL; + isc_result_t result; + unsigned int i; + + INSIST(count > 0); + + /* Allocate the pool structure */ + result = alloc_pool(mctx, count, &pool); + if (result != ISC_R_SUCCESS) + return (result); + + pool->free = free; + pool->init = init; + pool->initarg = initarg; + + /* Populate the pool */ + for (i = 0; i < count; i++) { + result = init(&pool->pool[i], initarg); + if (result != ISC_R_SUCCESS) { + isc_pool_destroy(&pool); + return (result); + } + } + + *poolp = pool; + return (ISC_R_SUCCESS); +} + +void * +isc_pool_get(isc_pool_t *pool) { + isc_uint32_t i; + isc_random_get(&i); + return (pool->pool[i % pool->count]); +} + +int +isc_pool_count(isc_pool_t *pool) { + REQUIRE(pool != NULL); + return (pool->count); +} + +isc_result_t +isc_pool_expand(isc_pool_t **sourcep, unsigned int count, + isc_pool_t **targetp) +{ + isc_result_t result; + isc_pool_t *pool; + + REQUIRE(sourcep != NULL && *sourcep != NULL); + REQUIRE(targetp != NULL && *targetp == NULL); + + pool = *sourcep; + if (count > pool->count) { + isc_pool_t *newpool = NULL; + unsigned int i; + + /* Allocate a new pool structure */ + result = alloc_pool(pool->mctx, count, &newpool); + if (result != ISC_R_SUCCESS) + return (result); + + newpool->free = pool->free; + newpool->init = pool->init; + newpool->initarg = pool->initarg; + + /* Copy over the objects from the old pool */ + for (i = 0; i < pool->count; i++) { + newpool->pool[i] = pool->pool[i]; + pool->pool[i] = NULL; + } + + /* Populate the new entries */ + for (i = pool->count; i < count; i++) { + result = pool->init(&newpool->pool[i], pool->initarg); + if (result != ISC_R_SUCCESS) { + isc_pool_destroy(&pool); + return (result); + } + } + + isc_pool_destroy(&pool); + pool = newpool; + } + + *sourcep = NULL; + *targetp = pool; + return (ISC_R_SUCCESS); +} + +void +isc_pool_destroy(isc_pool_t **poolp) { + unsigned int i; + isc_pool_t *pool = *poolp; + for (i = 0; i < pool->count; i++) { + if (pool->free != NULL && pool->pool[i] != NULL) + pool->free(&pool->pool[i]); + } + isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *)); + isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool)); + *poolp = NULL; +} diff --git a/contrib/bind9/lib/isc/radix.c b/contrib/bind9/lib/isc/radix.c index ac211efb6a87..35088788614e 100644 --- a/contrib/bind9/lib/isc/radix.c +++ b/contrib/bind9/lib/isc/radix.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -34,7 +34,7 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest, int bitlen); static void -_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix); +_deref_prefix(isc_prefix_t *prefix); static isc_result_t _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix); @@ -70,6 +70,8 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest, } prefix->family = family; + prefix->mctx = NULL; + isc_mem_attach(mctx, &prefix->mctx); isc_refcount_init(&prefix->refcount, 1); @@ -78,7 +80,7 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest, } static void -_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) { +_deref_prefix(isc_prefix_t *prefix) { int refs; if (prefix == NULL) @@ -88,7 +90,8 @@ _deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) { if (refs <= 0) { isc_refcount_destroy(&prefix->refcount); - isc_mem_put(mctx, prefix, sizeof(isc_prefix_t)); + isc_mem_putanddetach(&prefix->mctx, prefix, + sizeof(isc_prefix_t)); } } @@ -109,7 +112,7 @@ _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) { isc_result_t ret; ret = _new_prefix(mctx, target, prefix->family, &prefix->add, prefix->bitlen); - return ret; + return (ret); } isc_refcount_increment(&prefix->refcount, NULL); @@ -146,7 +149,8 @@ isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) { if (radix == NULL) return (ISC_R_NOMEMORY); - radix->mctx = mctx; + radix->mctx = NULL; + isc_mem_attach(mctx, &radix->mctx); radix->maxbits = maxbits; radix->head = NULL; radix->num_active_node = 0; @@ -168,7 +172,6 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) { REQUIRE(radix != NULL); if (radix->head != NULL) { - isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; isc_radix_node_t **Xsp = Xstack; isc_radix_node_t *Xrn = radix->head; @@ -178,7 +181,7 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) { isc_radix_node_t *r = Xrn->r; if (Xrn->prefix != NULL) { - _deref_prefix(radix->mctx, Xrn->prefix); + _deref_prefix(Xrn->prefix); if (func != NULL && (Xrn->data[0] != NULL || Xrn->data[1] != NULL)) func(Xrn->data); @@ -209,11 +212,10 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) { void -isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) -{ +isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) { REQUIRE(radix != NULL); _clear_radix(radix, func); - isc_mem_put(radix->mctx, radix, sizeof(*radix)); + isc_mem_putanddetach(&radix->mctx, radix, sizeof(*radix)); } @@ -221,8 +223,7 @@ isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) * func will be called as func(node->prefix, node->data) */ void -isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func) -{ +isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func) { isc_radix_node_t *node; REQUIRE(func != NULL); @@ -461,8 +462,8 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target, *target = node; return (ISC_R_SUCCESS); } else { - result = - _ref_prefix(radix->mctx, &node->prefix, prefix); + result = _ref_prefix(radix->mctx, + &node->prefix, prefix); if (result != ISC_R_SUCCESS) return (result); } @@ -623,7 +624,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { * make sure there is a prefix associated with it! */ if (node->prefix != NULL) - _deref_prefix(radix->mctx, node->prefix); + _deref_prefix(node->prefix); node->prefix = NULL; node->data[0] = node->data[1] = NULL; @@ -632,7 +633,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { if (node->r == NULL && node->l == NULL) { parent = node->parent; - _deref_prefix(radix->mctx, node->prefix); + _deref_prefix(node->prefix); isc_mem_put(radix->mctx, node, sizeof(*node)); radix->num_active_node--; @@ -680,7 +681,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { parent = node->parent; child->parent = parent; - _deref_prefix(radix->mctx, node->prefix); + _deref_prefix(node->prefix); isc_mem_put(radix->mctx, node, sizeof(*node)); radix->num_active_node--; diff --git a/contrib/bind9/lib/isc/socket_api.c b/contrib/bind9/lib/isc/socket_api.c index e97a93149cc9..1fba3e0ac19a 100644 --- a/contrib/bind9/lib/isc/socket_api.c +++ b/contrib/bind9/lib/isc/socket_api.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -140,6 +140,18 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task, pktinfo)); } +isc_result_t +isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_sockaddr_t *address, + struct in6_pktinfo *pktinfo, isc_socketevent_t *event, + unsigned int flags) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->sendto2(sock, region, task, address, + pktinfo, event, flags)); +} + isc_result_t isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task, isc_taskaction_t action, const void *arg) @@ -158,6 +170,17 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, return (sock->methods->recv(sock, region, minimum, task, action, arg)); } +isc_result_t +isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags) +{ + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return (sock->methods->recv2(sock, region, minimum, task, + event, flags)); +} + void isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { REQUIRE(ISCAPI_SOCKET_VALID(sock)); @@ -214,3 +237,18 @@ isc_socket_fdwatchpoke(isc_socket_t *sock, int flags) return(sock->methods->fdwatchpoke(sock, flags)); } + +isc_result_t +isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + REQUIRE(socketp != NULL && *socketp == NULL); + + return(sock->methods->dup(sock, socketp)); +} + +int +isc_socket_getfd(isc_socket_t *sock) { + REQUIRE(ISCAPI_SOCKET_VALID(sock)); + + return(sock->methods->getfd(sock)); +} diff --git a/contrib/bind9/lib/isc/task.c b/contrib/bind9/lib/isc/task.c index 94f1c6d6dabd..b743271339f9 100644 --- a/contrib/bind9/lib/isc/task.c +++ b/contrib/bind9/lib/isc/task.c @@ -64,9 +64,7 @@ #endif /* ISC_PLATFORM_USETHREADS */ #endif /* BIND9 */ -#ifndef USE_WORKER_THREADS #include "task_p.h" -#endif /* USE_WORKER_THREADS */ #ifdef ISC_TASK_TRACE #define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \ @@ -120,9 +118,11 @@ struct isc__task { /* Locked by task manager lock. */ LINK(isc__task_t) link; LINK(isc__task_t) ready_link; + LINK(isc__task_t) ready_priority_link; }; #define TASK_F_SHUTTINGDOWN 0x01 +#define TASK_F_PRIVILEGED 0x02 #define TASK_SHUTTINGDOWN(t) (((t)->flags & TASK_F_SHUTTINGDOWN) \ != 0) @@ -145,11 +145,15 @@ struct isc__taskmgr { unsigned int default_quantum; LIST(isc__task_t) tasks; isc__tasklist_t ready_tasks; + isc__tasklist_t ready_priority_tasks; + isc_taskmgrmode_t mode; #ifdef ISC_PLATFORM_USETHREADS isc_condition_t work_available; isc_condition_t exclusive_granted; + isc_condition_t paused; #endif /* ISC_PLATFORM_USETHREADS */ unsigned int tasks_running; + isc_boolean_t pause_requested; isc_boolean_t exclusive_requested; isc_boolean_t exiting; isc__task_t *excl; @@ -230,6 +234,23 @@ ISC_TASKFUNC_SCOPE isc_result_t isc__task_beginexclusive(isc_task_t *task); ISC_TASKFUNC_SCOPE void isc__task_endexclusive(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void +isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv); +ISC_TASKFUNC_SCOPE isc_boolean_t +isc__task_privilege(isc_task_t *task0); +ISC_TASKFUNC_SCOPE void +isc__taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode); +ISC_TASKFUNC_SCOPE isc_taskmgrmode_t +isc__taskmgr_mode(isc_taskmgr_t *manager0); + +static inline isc_boolean_t +empty_readyq(isc__taskmgr_t *manager); + +static inline isc__task_t * +pop_readyq(isc__taskmgr_t *manager); + +static inline void +push_readyq(isc__taskmgr_t *manager, isc__task_t *task); static struct isc__taskmethods { isc_taskmethods_t methods; @@ -254,7 +275,9 @@ static struct isc__taskmethods { isc__task_purge, isc__task_purgerange, isc__task_beginexclusive, - isc__task_endexclusive + isc__task_endexclusive, + isc__task_setprivilege, + isc__task_privilege } #ifndef BIND9 , @@ -266,6 +289,8 @@ static struct isc__taskmethods { static isc_taskmgrmethods_t taskmgrmethods = { isc__taskmgr_destroy, + isc__taskmgr_setmode, + isc__taskmgr_mode, isc__task_create, isc__taskmgr_setexcltask, isc__taskmgr_excltask @@ -340,6 +365,7 @@ isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum, task->tag = NULL; INIT_LINK(task, link); INIT_LINK(task, ready_link); + INIT_LINK(task, ready_priority_link); exiting = ISC_FALSE; LOCK(&manager->lock); @@ -407,6 +433,7 @@ task_shutdown(isc__task_t *task) { } INSIST(task->state == task_state_ready || task->state == task_state_running); + /* * Note that we post shutdown events LIFO. */ @@ -422,9 +449,17 @@ task_shutdown(isc__task_t *task) { return (was_idle); } +/* + * Moves a task onto the appropriate run queue. + * + * Caller must NOT hold manager lock. + */ static inline void task_ready(isc__task_t *task) { isc__taskmgr_t *manager = task->manager; +#ifdef USE_WORKER_THREADS + isc_boolean_t has_privilege = isc__task_privilege((isc_task_t *) task); +#endif /* USE_WORKER_THREADS */ REQUIRE(VALID_MANAGER(manager)); REQUIRE(task->state == task_state_ready); @@ -432,12 +467,11 @@ task_ready(isc__task_t *task) { XTRACE("task_ready"); LOCK(&manager->lock); - - ENQUEUE(manager->ready_tasks, task, ready_link); + push_readyq(manager, task); #ifdef USE_WORKER_THREADS - SIGNAL(&manager->work_available); + if (manager->mode == isc_taskmgrmode_normal || has_privilege) + SIGNAL(&manager->work_available); #endif /* USE_WORKER_THREADS */ - UNLOCK(&manager->lock); } @@ -875,21 +909,81 @@ isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) { REQUIRE(t != NULL); LOCK(&task->lock); - *t = task->now; - UNLOCK(&task->lock); } /*** *** Task Manager. ***/ + +/* + * Return ISC_TRUE if the current ready list for the manager, which is + * either ready_tasks or the ready_priority_tasks, depending on whether + * the manager is currently in normal or privileged execution mode. + * + * Caller must hold the task manager lock. + */ +static inline isc_boolean_t +empty_readyq(isc__taskmgr_t *manager) { + isc__tasklist_t queue; + + if (manager->mode == isc_taskmgrmode_normal) + queue = manager->ready_tasks; + else + queue = manager->ready_priority_tasks; + + return (ISC_TF(EMPTY(queue))); +} + +/* + * Dequeue and return a pointer to the first task on the current ready + * list for the manager. + * If the task is privileged, dequeue it from the other ready list + * as well. + * + * Caller must hold the task manager lock. + */ +static inline isc__task_t * +pop_readyq(isc__taskmgr_t *manager) { + isc__task_t *task; + + if (manager->mode == isc_taskmgrmode_normal) + task = HEAD(manager->ready_tasks); + else + task = HEAD(manager->ready_priority_tasks); + + if (task != NULL) { + DEQUEUE(manager->ready_tasks, task, ready_link); + if (ISC_LINK_LINKED(task, ready_priority_link)) + DEQUEUE(manager->ready_priority_tasks, task, + ready_priority_link); + } + + return (task); +} + +/* + * Push 'task' onto the ready_tasks queue. If 'task' has the privilege + * flag set, then also push it onto the ready_priority_tasks queue. + * + * Caller must hold the task manager lock. + */ +static inline void +push_readyq(isc__taskmgr_t *manager, isc__task_t *task) { + ENQUEUE(manager->ready_tasks, task, ready_link); + if ((task->flags & TASK_F_PRIVILEGED) != 0) + ENQUEUE(manager->ready_priority_tasks, task, + ready_priority_link); +} + static void dispatch(isc__taskmgr_t *manager) { isc__task_t *task; #ifndef USE_WORKER_THREADS unsigned int total_dispatch_count = 0; - isc__tasklist_t ready_tasks; + isc__tasklist_t new_ready_tasks; + isc__tasklist_t new_priority_tasks; #endif /* USE_WORKER_THREADS */ REQUIRE(VALID_MANAGER(manager)); @@ -945,9 +1039,11 @@ dispatch(isc__taskmgr_t *manager) { */ #ifndef USE_WORKER_THREADS - ISC_LIST_INIT(ready_tasks); + ISC_LIST_INIT(new_ready_tasks); + ISC_LIST_INIT(new_priority_tasks); #endif LOCK(&manager->lock); + while (!FINISHED(manager)) { #ifdef USE_WORKER_THREADS /* @@ -956,10 +1052,12 @@ dispatch(isc__taskmgr_t *manager) { * the task while only holding the manager lock, and then * change the task to running state while only holding the * task lock. + * + * If a pause has been requested, don't do any work + * until it's been released. */ - while ((EMPTY(manager->ready_tasks) || - manager->exclusive_requested) && - !FINISHED(manager)) + while ((empty_readyq(manager) || manager->pause_requested || + manager->exclusive_requested) && !FINISHED(manager)) { XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, @@ -971,13 +1069,13 @@ dispatch(isc__taskmgr_t *manager) { } #else /* USE_WORKER_THREADS */ if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM || - EMPTY(manager->ready_tasks)) + empty_readyq(manager)) break; #endif /* USE_WORKER_THREADS */ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK, ISC_MSG_WORKING, "working")); - task = HEAD(manager->ready_tasks); + task = pop_readyq(manager); if (task != NULL) { unsigned int dispatch_count = 0; isc_boolean_t done = ISC_FALSE; @@ -992,7 +1090,6 @@ dispatch(isc__taskmgr_t *manager) { * have a task to do. We must reacquire the manager * lock before exiting the 'if (task != NULL)' block. */ - DEQUEUE(manager->ready_tasks, task, ready_link); manager->tasks_running++; UNLOCK(&manager->lock); @@ -1113,6 +1210,9 @@ dispatch(isc__taskmgr_t *manager) { if (manager->exclusive_requested && manager->tasks_running == 1) { SIGNAL(&manager->exclusive_granted); + } else if (manager->pause_requested && + manager->tasks_running == 0) { + SIGNAL(&manager->paused); } #endif /* USE_WORKER_THREADS */ if (requeue) { @@ -1136,17 +1236,39 @@ dispatch(isc__taskmgr_t *manager) { * might even hurt rather than help. */ #ifdef USE_WORKER_THREADS - ENQUEUE(manager->ready_tasks, task, - ready_link); + push_readyq(manager, task); #else - ENQUEUE(ready_tasks, task, ready_link); + ENQUEUE(new_ready_tasks, task, ready_link); + if ((task->flags & TASK_F_PRIVILEGED) != 0) + ENQUEUE(new_priority_tasks, task, + ready_priority_link); #endif } } - } -#ifndef USE_WORKER_THREADS - ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link); + +#ifdef USE_WORKER_THREADS + /* + * If we are in privileged execution mode and there are no + * tasks remaining on the current ready queue, then + * we're stuck. Automatically drop privileges at that + * point and continue with the regular ready queue. + */ + if (manager->tasks_running == 0 && empty_readyq(manager)) { + manager->mode = isc_taskmgrmode_normal; + if (!empty_readyq(manager)) + BROADCAST(&manager->work_available); + } #endif + } + +#ifndef USE_WORKER_THREADS + ISC_LIST_APPENDLIST(manager->ready_tasks, new_ready_tasks, ready_link); + ISC_LIST_APPENDLIST(manager->ready_priority_tasks, new_priority_tasks, + ready_priority_link); + if (empty_readyq(manager)) + manager->mode = isc_taskmgrmode_normal; +#endif + UNLOCK(&manager->lock); } @@ -1181,6 +1303,7 @@ manager_free(isc__taskmgr_t *manager) { #ifdef USE_WORKER_THREADS (void)isc_condition_destroy(&manager->exclusive_granted); (void)isc_condition_destroy(&manager->work_available); + (void)isc_condition_destroy(&manager->paused); isc_mem_free(manager->mctx, manager->threads); #endif /* USE_WORKER_THREADS */ DESTROYLOCK(&manager->lock); @@ -1231,6 +1354,7 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, manager->common.methods = &taskmgrmethods; manager->common.impmagic = TASK_MANAGER_MAGIC; manager->common.magic = ISCAPI_TASKMGR_MAGIC; + manager->mode = isc_taskmgrmode_normal; manager->mctx = NULL; result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) @@ -1260,14 +1384,24 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, result = ISC_R_UNEXPECTED; goto cleanup_workavailable; } + if (isc_condition_init(&manager->paused) != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_condition_init() %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + result = ISC_R_UNEXPECTED; + goto cleanup_exclusivegranted; + } #endif /* USE_WORKER_THREADS */ if (default_quantum == 0) default_quantum = DEFAULT_DEFAULT_QUANTUM; manager->default_quantum = default_quantum; INIT_LIST(manager->tasks); INIT_LIST(manager->ready_tasks); + INIT_LIST(manager->ready_priority_tasks); manager->tasks_running = 0; manager->exclusive_requested = ISC_FALSE; + manager->pause_requested = ISC_FALSE; manager->exiting = ISC_FALSE; manager->excl = NULL; @@ -1304,6 +1438,8 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, return (ISC_R_SUCCESS); #ifdef USE_WORKER_THREADS + cleanup_exclusivegranted: + (void)isc_condition_destroy(&manager->exclusive_granted); cleanup_workavailable: (void)isc_condition_destroy(&manager->work_available); cleanup_threads: @@ -1374,6 +1510,11 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) { INSIST(!manager->exiting); manager->exiting = ISC_TRUE; + /* + * If privileged mode was on, turn it off. + */ + manager->mode = isc_taskmgrmode_normal; + /* * Post shutdown event(s) to every task (if they haven't already been * posted). @@ -1383,7 +1524,7 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) { task = NEXT(task, link)) { LOCK(&task->lock); if (task_shutdown(task)) - ENQUEUE(manager->ready_tasks, task, ready_link); + push_readyq(manager, task); UNLOCK(&task->lock); } #ifdef USE_WORKER_THREADS @@ -1422,10 +1563,30 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) { *managerp = NULL; } +ISC_TASKFUNC_SCOPE void +isc__taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + + LOCK(&manager->lock); + manager->mode = mode; + UNLOCK(&manager->lock); +} + +ISC_TASKFUNC_SCOPE isc_taskmgrmode_t +isc__taskmgr_mode(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + isc_taskmgrmode_t mode; + LOCK(&manager->lock); + mode = manager->mode; + UNLOCK(&manager->lock); + return (mode); +} + #ifndef USE_WORKER_THREADS isc_boolean_t isc__taskmgr_ready(isc_taskmgr_t *manager0) { isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + isc_boolean_t is_ready; #ifdef USE_SHARED_MANAGER if (manager == NULL) @@ -1433,7 +1594,12 @@ isc__taskmgr_ready(isc_taskmgr_t *manager0) { #endif if (manager == NULL) return (ISC_FALSE); - return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks))); + + LOCK(&manager->lock); + is_ready = !empty_readyq(manager); + UNLOCK(&manager->lock); + + return (is_ready); } isc_result_t @@ -1452,6 +1618,29 @@ isc__taskmgr_dispatch(isc_taskmgr_t *manager0) { return (ISC_R_SUCCESS); } +#else +ISC_TASKFUNC_SCOPE void +isc__taskmgr_pause(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + LOCK(&manager->lock); + while (manager->tasks_running > 0) { + WAIT(&manager->paused, &manager->lock); + } + manager->pause_requested = ISC_TRUE; + UNLOCK(&manager->lock); +} + +ISC_TASKFUNC_SCOPE void +isc__taskmgr_resume(isc_taskmgr_t *manager0) { + isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; + + LOCK(&manager->lock); + if (manager->pause_requested) { + manager->pause_requested = ISC_FALSE; + BROADCAST(&manager->work_available); + } + UNLOCK(&manager->lock); +} #endif /* USE_WORKER_THREADS */ ISC_TASKFUNC_SCOPE void @@ -1522,6 +1711,44 @@ isc__task_endexclusive(isc_task_t *task0) { #endif } +ISC_TASKFUNC_SCOPE void +isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv) { + isc__task_t *task = (isc__task_t *)task0; + isc__taskmgr_t *manager = task->manager; + isc_boolean_t oldpriv; + + LOCK(&task->lock); + oldpriv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0); + if (priv) + task->flags |= TASK_F_PRIVILEGED; + else + task->flags &= ~TASK_F_PRIVILEGED; + UNLOCK(&task->lock); + + if (priv == oldpriv) + return; + + LOCK(&manager->lock); + if (priv && ISC_LINK_LINKED(task, ready_link)) + ENQUEUE(manager->ready_priority_tasks, task, + ready_priority_link); + else if (!priv && ISC_LINK_LINKED(task, ready_priority_link)) + DEQUEUE(manager->ready_priority_tasks, task, + ready_priority_link); + UNLOCK(&manager->lock); +} + +ISC_TASKFUNC_SCOPE isc_boolean_t +isc__task_privilege(isc_task_t *task0) { + isc__task_t *task = (isc__task_t *)task0; + isc_boolean_t priv; + + LOCK(&task->lock); + priv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0); + UNLOCK(&task->lock); + return (priv); +} + #ifdef USE_SOCKETIMPREGISTER isc_result_t isc__task_register() { diff --git a/contrib/bind9/lib/isc/task_api.c b/contrib/bind9/lib/isc/task_api.c index 06a8d24849ba..f49ab321b2d3 100644 --- a/contrib/bind9/lib/isc/task_api.c +++ b/contrib/bind9/lib/isc/task_api.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -99,6 +99,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { ENSURE(*managerp == NULL); } +void +isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) { + REQUIRE(ISCAPI_TASKMGR_VALID(manager)); + + manager->methods->setmode(manager, mode); +} + +isc_taskmgrmode_t +isc_taskmgr_mode(isc_taskmgr_t *manager) { + REQUIRE(ISCAPI_TASKMGR_VALID(manager)); + + return (manager->methods->mode(manager)); +} + isc_result_t isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, isc_task_t **taskp) @@ -212,6 +226,20 @@ isc_task_endexclusive(isc_task_t *task) { task->methods->endexclusive(task); } +void +isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + task->methods->setprivilege(task, priv); +} + +isc_boolean_t +isc_task_privilege(isc_task_t *task) { + REQUIRE(ISCAPI_TASK_VALID(task)); + + return (task->methods->privilege(task)); +} + /*% * This is necessary for libisc's internal timer implementation. Other diff --git a/contrib/bind9/lib/isc/task_p.h b/contrib/bind9/lib/isc/task_p.h index 85deeae0d0ea..8c1e4c52fa4c 100644 --- a/contrib/bind9/lib/isc/task_p.h +++ b/contrib/bind9/lib/isc/task_p.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -22,10 +22,18 @@ /*! \file */ +#if defined(BIND9) && defined(ISC_PLATFORM_USETHREADS) +void +isc__taskmgr_pause(isc_taskmgr_t *taskmgr); + +void +isc__taskmgr_resume(isc_taskmgr_t *taskmgr); +#else isc_boolean_t isc__taskmgr_ready(isc_taskmgr_t *taskmgr); isc_result_t isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr); +#endif /* !BIND9 || !ISC_PLATFORM_USETHREADS */ #endif /* ISC_TASK_P_H */ diff --git a/contrib/bind9/lib/isc/taskpool.c b/contrib/bind9/lib/isc/taskpool.c index 7324cfa379d0..a5ce0e8514df 100644 --- a/contrib/bind9/lib/isc/taskpool.c +++ b/contrib/bind9/lib/isc/taskpool.c @@ -165,9 +165,8 @@ isc_taskpool_destroy(isc_taskpool_t **poolp) { unsigned int i; isc_taskpool_t *pool = *poolp; for (i = 0; i < pool->ntasks; i++) { - if (pool->tasks[i] != NULL) { + if (pool->tasks[i] != NULL) isc_task_detach(&pool->tasks[i]); - } } isc_mem_put(pool->mctx, pool->tasks, pool->ntasks * sizeof(isc_task_t *)); @@ -175,4 +174,14 @@ isc_taskpool_destroy(isc_taskpool_t **poolp) { *poolp = NULL; } +void +isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv) { + unsigned int i; + REQUIRE(pool != NULL); + + for (i = 0; i < pool->ntasks; i++) { + if (pool->tasks[i] != NULL) + isc_task_setprivilege(pool->tasks[i], priv); + } +} diff --git a/contrib/bind9/lib/isc/unix/socket.c b/contrib/bind9/lib/isc/unix/socket.c index d007598e19d0..7bd12aaa31ed 100644 --- a/contrib/bind9/lib/isc/unix/socket.c +++ b/contrib/bind9/lib/isc/unix/socket.c @@ -334,7 +334,8 @@ struct isc__socket { listener : 1, /* listener socket */ connected : 1, connecting : 1, /* connect pending */ - bound : 1; /* bound to local addr */ + bound : 1, /* bound to local addr */ + dupped : 1; #ifdef ISC_NET_RECVOVERFLOW unsigned char overflow; /* used for MSG_TRUNC fake */ @@ -428,6 +429,10 @@ static isc__socketmgr_t *socketmgr = NULL; # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) #endif +static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf, + isc_sockettype_t type, + isc_socket_t **socketp, + isc_socket_t *dup_socket); static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **); static void send_senddone_event(isc__socket_t *, isc_socketevent_t **); static void free_socket(isc__socket_t **); @@ -546,6 +551,10 @@ isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, isc_task_t *task, isc_socket_t **socketp); ISC_SOCKETFUNC_SCOPE isc_result_t isc__socket_fdwatchpoke(isc_socket_t *sock, int flags); +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp); +ISC_SOCKETFUNC_SCOPE int +isc__socket_getfd(isc_socket_t *sock); static struct { isc_socketmethods_t methods; @@ -563,13 +572,17 @@ static struct { isc__socket_detach, isc__socket_bind, isc__socket_sendto, + isc__socket_sendto2, isc__socket_connect, isc__socket_recv, + isc__socket_recv2, isc__socket_cancel, isc__socket_getsockname, isc__socket_gettype, isc__socket_ipv6only, - isc__socket_fdwatchpoke + isc__socket_fdwatchpoke, + isc__socket_dup, + isc__socket_getfd } #ifndef BIND9 , @@ -2046,6 +2059,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type, sock->manager = manager; sock->type = type; sock->fd = -1; + sock->dupped = 0; sock->statsindex = NULL; ISC_LINK_INIT(sock, link); @@ -2251,7 +2265,9 @@ use_min_mtu(isc__socket_t *sock) { } static isc_result_t -opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { +opensocket(isc__socketmgr_t *manager, isc__socket_t *sock, + isc__socket_t *dup_socket) +{ isc_result_t result; char strbuf[ISC_STRERRORSIZE]; const char *err = "socket"; @@ -2265,22 +2281,29 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { #endif again: - switch (sock->type) { - case isc_sockettype_udp: - sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); - break; - case isc_sockettype_tcp: - sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); - break; - case isc_sockettype_unix: - sock->fd = socket(sock->pf, SOCK_STREAM, 0); - break; - case isc_sockettype_fdwatch: - /* - * We should not be called for isc_sockettype_fdwatch sockets. - */ - INSIST(0); - break; + if (dup_socket == NULL) { + switch (sock->type) { + case isc_sockettype_udp: + sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); + break; + case isc_sockettype_tcp: + sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); + break; + case isc_sockettype_unix: + sock->fd = socket(sock->pf, SOCK_STREAM, 0); + break; + case isc_sockettype_fdwatch: + /* + * We should not be called for isc_sockettype_fdwatch + * sockets. + */ + INSIST(0); + break; + } + } else { + sock->fd = dup(dup_socket->fd); + sock->dupped = 1; + sock->bound = dup_socket->bound; } if (sock->fd == -1 && errno == EINTR && tries++ < 42) goto again; @@ -2357,6 +2380,9 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { } } + if (dup_socket != NULL) + goto setup_done; + result = make_nonblock(sock->fd); if (result != ISC_R_SUCCESS) { (void)close(sock->fd); @@ -2521,20 +2547,21 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { } #endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */ +setup_done: inc_stats(manager->stats, sock->statsindex[STATID_OPEN]); return (ISC_R_SUCCESS); } -/*% - * Create a new 'type' socket managed by 'manager'. Events - * will be posted to 'task' and when dispatched 'action' will be - * called with 'arg' as the arg value. The new socket is returned - * in 'socketp'. +/* + * Create a 'type' socket or duplicate an existing socket, managed + * by 'manager'. Events will be posted to 'task' and when dispatched + * 'action' will be called with 'arg' as the arg value. The new + * socket is returned in 'socketp'. */ -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, - isc_socket_t **socketp) +static isc_result_t +socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, + isc_socket_t **socketp, isc_socket_t *dup_socket) { isc__socket_t *sock = NULL; isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; @@ -2566,7 +2593,8 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, } sock->pf = pf; - result = opensocket(manager, sock); + + result = opensocket(manager, sock, (isc__socket_t *)dup_socket); if (result != ISC_R_SUCCESS) { inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]); free_socket(&sock); @@ -2601,11 +2629,40 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, UNLOCK(&manager->lock); socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_CREATED, "created"); + ISC_MSG_CREATED, dup_socket != NULL ? "dupped" : "created"); return (ISC_R_SUCCESS); } +/*% + * Create a new 'type' socket managed by 'manager'. Events + * will be posted to 'task' and when dispatched 'action' will be + * called with 'arg' as the arg value. The new socket is returned + * in 'socketp'. + */ +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, + isc_socket_t **socketp) +{ + return (socket_create(manager0, pf, type, socketp, NULL)); +} + +/*% + * Duplicate an existing socket. The new socket is returned + * in 'socketp'. + */ +ISC_SOCKETFUNC_SCOPE isc_result_t +isc__socket_dup(isc_socket_t *sock0, isc_socket_t **socketp) { + isc__socket_t *sock = (isc__socket_t *)sock0; + + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(socketp != NULL && *socketp == NULL); + + return (socket_create((isc_socketmgr_t *) sock->manager, + sock->pf, sock->type, socketp, + sock0)); +} + #ifdef BIND9 ISC_SOCKETFUNC_SCOPE isc_result_t isc__socket_open(isc_socket_t *sock0) { @@ -2624,7 +2681,7 @@ isc__socket_open(isc_socket_t *sock0) { */ REQUIRE(sock->fd == -1); - result = opensocket(sock->manager, sock); + result = opensocket(sock->manager, sock, NULL); if (result != ISC_R_SUCCESS) sock->fd = -1; @@ -2804,6 +2861,7 @@ isc__socket_close(isc_socket_t *sock0) { int fd; isc__socketmgr_t *manager; + fflush(stdout); REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -2824,6 +2882,7 @@ isc__socket_close(isc_socket_t *sock0) { manager = sock->manager; fd = sock->fd; sock->fd = -1; + sock->dupped = 0; memset(sock->name, 0, sizeof(sock->name)); sock->tag = NULL; sock->listener = 0; @@ -4991,11 +5050,13 @@ isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr, LOCK(&sock->lock); INSIST(!sock->bound); + INSIST(!sock->dupped); if (sock->pf != sockaddr->type.sa.sa_family) { UNLOCK(&sock->lock); return (ISC_R_FAMILYMISMATCH); } + /* * Only set SO_REUSEADDR when we want a specific port. */ @@ -5680,6 +5741,7 @@ isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) { #endif REQUIRE(VALID_SOCKET(sock)); + INSIST(!sock->dupped); #ifdef IPV6_V6ONLY if (sock->pf == AF_INET6) { @@ -5846,6 +5908,13 @@ isc__socket_register() { } #endif +ISC_SOCKETFUNC_SCOPE int +isc__socket_getfd(isc_socket_t *socket0) { + isc__socket_t *socket = (isc__socket_t *)socket0; + + return ((short) socket->fd); +} + #if defined(HAVE_LIBXML2) && defined(BIND9) static const char * diff --git a/contrib/bind9/lib/isccc/api b/contrib/bind9/lib/isccc/api index 461b9ac31a9b..47724c51e39f 100644 --- a/contrib/bind9/lib/isccc/api +++ b/contrib/bind9/lib/isccc/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 80 +LIBINTERFACE = 90 LIBREVISION = 3 LIBAGE = 0 diff --git a/contrib/bind9/lib/isccfg/api b/contrib/bind9/lib/isccfg/api index 39585b0239db..864bdc90941c 100644 --- a/contrib/bind9/lib/isccfg/api +++ b/contrib/bind9/lib/isccfg/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 82 -LIBREVISION = 7 +LIBINTERFACE = 90 +LIBREVISION = 6 LIBAGE = 0 diff --git a/contrib/bind9/lib/isccfg/namedconf.c b/contrib/bind9/lib/isccfg/namedconf.c index 287ce141f4c7..431af746338b 100644 --- a/contrib/bind9/lib/isccfg/namedconf.c +++ b/contrib/bind9/lib/isccfg/namedconf.c @@ -54,6 +54,9 @@ static isc_result_t parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype, const cfg_type_t *othertype, cfg_obj_t **ret); +static void +doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *type); + static isc_result_t parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); @@ -228,9 +231,8 @@ static cfg_type_t cfg_type_namesockaddrkeylist = { }; /*% - * A list of socket addresses with an optional default port, - * as used in the also-notify option. E.g., - * "port 1234 { 10.0.0.1; 1::2 port 69; }" + * A list of socket addresses with an optional default port, as used + * in the lwresd 'listen-on' option. E.g., "{ 10.0.0.1; 1::2 port 69; }" */ static cfg_tuplefielddef_t portiplist_fields[] = { { "port", &cfg_type_optional_port, 0 }, @@ -238,8 +240,8 @@ static cfg_tuplefielddef_t portiplist_fields[] = { { NULL, NULL, 0 } }; static cfg_type_t cfg_type_portiplist = { - "portiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, - portiplist_fields + "portiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, + &cfg_rep_tuple, portiplist_fields }; /*% @@ -554,6 +556,35 @@ static cfg_type_t cfg_type_autodnssec = { &cfg_rep_string, &autodnssec_enums }; +static const char *dnssecupdatemode_enums[] = { "maintain", "no-resign", NULL }; +static cfg_type_t cfg_type_dnssecupdatemode = { + "dnssecupdatemode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &dnssecupdatemode_enums +}; + +static const char *updatemethods_enums[] = { "increment", "unixtime", NULL }; +static cfg_type_t cfg_type_updatemethod = { + "updatemethod", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &updatemethods_enums +}; + +/* + * zone-statistics: full, terse, or none. + * + * for backward compatibility, we also support boolean values. + * yes represents "full", no represents "terse". in the future we + * may change no to mean "none". + */ +static const char *zonestat_enums[] = { "full", "terse", "none", NULL }; +static isc_result_t +parse_zonestat(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret)); +} +static cfg_type_t cfg_type_zonestat = { + "zonestat", parse_zonestat, cfg_print_ustring, doc_enum_or_other, + &cfg_rep_string, zonestat_enums +}; + static cfg_type_t cfg_type_rrsetorder = { "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_rrsetorderingelement @@ -599,7 +630,7 @@ static cfg_type_t cfg_type_forwardtype = { static const char *zonetype_enums[] = { "master", "slave", "stub", "static-stub", "hint", "forward", - "delegation-only", NULL }; + "delegation-only", "redirect", NULL }; static cfg_type_t cfg_type_zonetype = { "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, &zonetype_enums @@ -912,6 +943,7 @@ options_clauses[] = { { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, { "managed-keys-directory", &cfg_type_qstring, 0 }, { "match-mapped-addresses", &cfg_type_boolean, 0 }, + { "max-rsa-exponent-size", &cfg_type_uint32, 0 }, { "memstatistics-file", &cfg_type_qstring, 0 }, { "memstatistics", &cfg_type_boolean, 0 }, { "multiple-cnames", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, @@ -1458,7 +1490,7 @@ zone_clauses[] = { { "allow-transfer", &cfg_type_bracketed_aml, 0 }, { "allow-update", &cfg_type_bracketed_aml, 0 }, { "allow-update-forwarding", &cfg_type_bracketed_aml, 0 }, - { "also-notify", &cfg_type_portiplist, 0 }, + { "also-notify", &cfg_type_namesockaddrkeylist, 0 }, { "alt-transfer-source", &cfg_type_sockaddr4wild, 0 }, { "alt-transfer-source-v6", &cfg_type_sockaddr6wild, 0 }, { "auto-dnssec", &cfg_type_autodnssec, 0 }, @@ -1472,7 +1504,9 @@ zone_clauses[] = { { "check-wildcard", &cfg_type_boolean, 0 }, { "dialup", &cfg_type_dialuptype, 0 }, { "dnssec-dnskey-kskonly", &cfg_type_boolean, 0 }, + { "dnssec-loadkeys-interval", &cfg_type_uint32, 0 }, { "dnssec-secure-to-insecure", &cfg_type_boolean, 0 }, + { "dnssec-update-mode", &cfg_type_dnssecupdatemode, 0 }, { "forward", &cfg_type_forwardtype, 0 }, { "forwarders", &cfg_type_portiplist, 0 }, { "key-directory", &cfg_type_qstring, 0 }, @@ -1495,17 +1529,20 @@ zone_clauses[] = { { "notify-source-v6", &cfg_type_sockaddr6wild, 0 }, { "notify-to-soa", &cfg_type_boolean, 0 }, { "nsec3-test-zone", &cfg_type_boolean, CFG_CLAUSEFLAG_TESTONLY }, + { "serial-update-method", &cfg_type_updatemethod, 0 }, + { "request-ixfr", &cfg_type_boolean, 0 }, { "sig-signing-nodes", &cfg_type_uint32, 0 }, { "sig-signing-signatures", &cfg_type_uint32, 0 }, { "sig-signing-type", &cfg_type_uint32, 0 }, { "sig-validity-interval", &cfg_type_validityinterval, 0 }, + { "inline-signing", &cfg_type_boolean, 0 }, { "transfer-source", &cfg_type_sockaddr4wild, 0 }, { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 }, { "try-tcp-refresh", &cfg_type_boolean, 0 }, { "update-check-ksk", &cfg_type_boolean, 0 }, { "use-alt-transfer-source", &cfg_type_boolean, 0 }, { "zero-no-soa-ttl", &cfg_type_boolean, 0 }, - { "zone-statistics", &cfg_type_boolean, 0 }, + { "zone-statistics", &cfg_type_zonestat, 0 }, { NULL, NULL, 0 } }; diff --git a/contrib/bind9/lib/lwres/api b/contrib/bind9/lib/lwres/api index 2a5c388460ce..95bd2046233e 100644 --- a/contrib/bind9/lib/lwres/api +++ b/contrib/bind9/lib/lwres/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 80 -LIBREVISION = 6 +LIBINTERFACE = 90 +LIBREVISION = 4 LIBAGE = 0 diff --git a/contrib/bind9/lib/lwres/man/lwres_config.3 b/contrib/bind9/lib/lwres/man/lwres_config.3 index a0919d95f25b..42f0e695f7b3 100644 --- a/contrib/bind9/lib/lwres/man/lwres_config.3 +++ b/contrib/bind9/lib/lwres/man/lwres_config.3 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004, 2005, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -100,7 +100,7 @@ unless an error occurred when converting the network addresses to a numeric host .PP \fI/etc/resolv.conf\fR .SH "COPYRIGHT" -Copyright \(co 2004, 2005, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000, 2001 Internet Software Consortium. .br diff --git a/contrib/bind9/lib/lwres/man/lwres_config.docbook b/contrib/bind9/lib/lwres/man/lwres_config.docbook index 71475706e96f..5736ef3b6490 100644 --- a/contrib/bind9/lib/lwres/man/lwres_config.docbook +++ b/contrib/bind9/lib/lwres/man/lwres_config.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []> - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_config.html b/contrib/bind9/lib/lwres/man/lwres_config.html index ccc9db14dfa8..ed10069c355a 100644 --- a/contrib/bind9/lib/lwres/man/lwres_config.html +++ b/contrib/bind9/lib/lwres/man/lwres_config.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_context.html b/contrib/bind9/lib/lwres/man/lwres_context.html index 70efa240c80c..e13539d9f924 100644 --- a/contrib/bind9/lib/lwres/man/lwres_context.html +++ b/contrib/bind9/lib/lwres/man/lwres_context.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_gabn.html b/contrib/bind9/lib/lwres/man/lwres_gabn.html index 30c9dda251e9..270620d3d661 100644 --- a/contrib/bind9/lib/lwres/man/lwres_gabn.html +++ b/contrib/bind9/lib/lwres/man/lwres_gabn.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html b/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html index e8d4935c303c..f2faacecfb6a 100644 --- a/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html +++ b/contrib/bind9/lib/lwres/man/lwres_gai_strerror.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html b/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html index 57025c0c232e..270236742964 100644 --- a/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html +++ b/contrib/bind9/lib/lwres/man/lwres_getaddrinfo.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_gethostent.html b/contrib/bind9/lib/lwres/man/lwres_gethostent.html index e5f660cb0c70..2c990850805f 100644 --- a/contrib/bind9/lib/lwres/man/lwres_gethostent.html +++ b/contrib/bind9/lib/lwres/man/lwres_gethostent.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_getipnode.html b/contrib/bind9/lib/lwres/man/lwres_getipnode.html index 410fec937555..0fc483d1a8aa 100644 --- a/contrib/bind9/lib/lwres/man/lwres_getipnode.html +++ b/contrib/bind9/lib/lwres/man/lwres_getipnode.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html b/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html index f4808e742dc9..9cc7d5ae3cd1 100644 --- a/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html +++ b/contrib/bind9/lib/lwres/man/lwres_getnameinfo.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html b/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html index 7f3b56dac228..e7d68bb54d3d 100644 --- a/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html +++ b/contrib/bind9/lib/lwres/man/lwres_getrrsetbyname.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_gnba.html b/contrib/bind9/lib/lwres/man/lwres_gnba.html index 774a166eba1d..6d61b87bb43e 100644 --- a/contrib/bind9/lib/lwres/man/lwres_gnba.html +++ b/contrib/bind9/lib/lwres/man/lwres_gnba.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_hstrerror.html b/contrib/bind9/lib/lwres/man/lwres_hstrerror.html index c698d55d4d5e..8d4e9d60b5be 100644 --- a/contrib/bind9/lib/lwres/man/lwres_hstrerror.html +++ b/contrib/bind9/lib/lwres/man/lwres_hstrerror.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_inetntop.html b/contrib/bind9/lib/lwres/man/lwres_inetntop.html index 64be8a929f9d..6f1a37f6d7a4 100644 --- a/contrib/bind9/lib/lwres/man/lwres_inetntop.html +++ b/contrib/bind9/lib/lwres/man/lwres_inetntop.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_noop.html b/contrib/bind9/lib/lwres/man/lwres_noop.html index 9db4d062683f..69d0d386b366 100644 --- a/contrib/bind9/lib/lwres/man/lwres_noop.html +++ b/contrib/bind9/lib/lwres/man/lwres_noop.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_packet.html b/contrib/bind9/lib/lwres/man/lwres_packet.html index 362746563721..fad9076a6e8c 100644 --- a/contrib/bind9/lib/lwres/man/lwres_packet.html +++ b/contrib/bind9/lib/lwres/man/lwres_packet.html @@ -1,5 +1,5 @@ - + @@ -36,7 +36,6 @@ 2004 2005 2007 - 2012 Internet Systems Consortium, Inc. ("ISC") diff --git a/contrib/bind9/lib/lwres/man/lwres_resutil.html b/contrib/bind9/lib/lwres/man/lwres_resutil.html index cbe724b3d1f8..4db7610448c5 100644 --- a/contrib/bind9/lib/lwres/man/lwres_resutil.html +++ b/contrib/bind9/lib/lwres/man/lwres_resutil.html @@ -1,5 +1,5 @@
-Prev  Up  Next
-dnssec-signzone  Home  named-checkzone