diff --git a/CHANGES b/CHANGES index d6147c0a5e..06f7551637 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +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] diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 87971075de..5fd45f0947 100644 --- a/bin/named/named.conf.docbook +++ b/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 ); @@ -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 ); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 387a724d55..5fb74159b7 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.175 2011/04/29 21:37:14 each Exp $ */ +/* $Id: zoneconf.c,v 1.176 2011/05/06 21:23:50 each Exp $ */ /*% */ @@ -999,17 +999,18 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, obj = NULL; result = ns_config_get(maps, "also-notify", &obj); if (result == ISC_R_SUCCESS) { - isc_sockaddr_t *addrs = NULL; isc_uint32_t addrcount; - result = ns_config_getiplist(config, obj, 0, mctx, - &addrs, &addrcount); - if (result != ISC_R_SUCCESS) - return (result); - result = dns_zone_setalsonotify(zone, addrs, - addrcount); - ns_config_putiplist(mctx, &addrs, addrcount); - if (result != ISC_R_SUCCESS) - return (result); + addrs = NULL; + keynames = NULL; + RETERR(ns_config_getipandkeylist(config, obj, mctx, + &addrs, &keynames, + &addrcount)); + result = dns_zone_setalsonotifywithkeys(zone, addrs, + keynames, + addrcount); + ns_config_putipandkeylist(mctx, &addrs, &keynames, + addrcount); + RETERR(result); } else RETERR(dns_zone_setalsonotify(zone, NULL, 0)); diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh index 697877d749..535ae75bda 100644 --- a/bin/tests/system/nsupdate/clean.sh +++ b/bin/tests/system/nsupdate/clean.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: clean.sh,v 1.22 2011/02/03 12:18:11 tbox Exp $ +# $Id: clean.sh,v 1.23 2011/05/06 21:23:50 each Exp $ # # Clean up after zone transfer tests. @@ -26,7 +26,7 @@ rm -f dig.out.ns1 dig.out.ns2 dig.out.ns1.after ns1/*.jnl ns2/*.jnl \ rm -f nsupdate.out rm -f random.data rm -f ns2/example.bk -rm -f ns2/update.bk +rm -f ns2/update.bk ns2/update.alt.bk rm -f */named.memstats rm -f nsupdate.out rm -f ns3/example.db.jnl ns3/example.db diff --git a/bin/tests/system/nsupdate/ns1/named.conf b/bin/tests/system/nsupdate/ns1/named.conf index 19be93aad7..add4fdcf59 100644 --- a/bin/tests/system/nsupdate/ns1/named.conf +++ b/bin/tests/system/nsupdate/ns1/named.conf @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.19 2009/07/29 23:47:43 tbox Exp $ */ +/* $Id: named.conf,v 1.20 2011/05/06 21:23:50 each Exp $ */ controls { /* empty */ }; @@ -41,6 +41,11 @@ controls { inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; }; +key altkey { + algorithm hmac-md5; + secret "1234abcd8765"; +}; + include "ddns.key"; zone "example.nil" { @@ -62,11 +67,16 @@ zone "other.nil" { allow-transfer { any; }; }; +masters othermasters { + 10.53.0.2 port 5300; + 10.53.0.2 port 5300 key altkey; +}; + zone "update.nil" { type master; file "update.db"; check-integrity no; allow-update { any; }; allow-transfer { any; }; - also-notify { 10.53.0.2; }; + also-notify { othermasters; }; }; diff --git a/bin/tests/system/nsupdate/ns2/named.conf b/bin/tests/system/nsupdate/ns2/named.conf index 77e401337b..1bee98cecd 100644 --- a/bin/tests/system/nsupdate/ns2/named.conf +++ b/bin/tests/system/nsupdate/ns2/named.conf @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.14 2007/06/18 23:47:30 tbox Exp $ */ +/* $Id: named.conf,v 1.15 2011/05/06 21:23:50 each Exp $ */ controls { /* empty */ }; @@ -32,18 +32,36 @@ options { notify yes; }; -zone "example.nil" { - type slave; - masters { 10.53.0.1; }; - file "example.bk"; - allow-transfer { any; }; +key altkey { + algorithm hmac-md5; + secret "1234abcd8765"; }; -zone "update.nil" { - type slave; - masters { 10.53.0.1; }; - file "update.bk"; - allow-transfer { any; }; +view alternate { + match-clients { key altkey; }; + + zone "update.nil" { + type slave; + masters { 10.53.0.1; }; + file "update.alt.bk"; + allow-transfer { any; }; + }; }; +view primary { + match-clients { any; }; + zone "example.nil" { + type slave; + masters { 10.53.0.1; }; + file "example.bk"; + allow-transfer { any; }; + }; + + zone "update.nil" { + type slave; + masters { 10.53.0.1; }; + file "update.bk"; + allow-transfer { any; }; + }; +}; diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh index b794d86da6..163954bf0d 100644 --- a/bin/tests/system/nsupdate/setup.sh +++ b/bin/tests/system/nsupdate/setup.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: setup.sh,v 1.16 2010/12/07 23:47:02 tbox Exp $ +# $Id: setup.sh,v 1.17 2011/05/06 21:23:50 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -25,6 +25,7 @@ SYSTEMTESTTOP=.. # rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk +rm -f ns2/update.bk ns2/update.alt.bk rm -f ns3/example.db.jnl cp -f ns1/example1.db ns1/example.db diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 855a050788..5cacc776c9 100644 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.35 2011/03/18 02:08:45 each Exp $ +# $Id: tests.sh,v 1.36 2011/05/06 21:23:50 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -352,5 +352,17 @@ then echo "I:failed"; status=1 fi +n=`expr $n + 1` +ret=0 +echo "I:check notify with TSIG worked ($n)" +# if the alternate view received a notify--meaning, the notify was +# validly signed by "altkey"--then the zonefile update.alt.bk will +# will have been created. +[ -f ns2/update.alt.bk ] || ret=1 +if [ $ret -ne 0 ]; then + echo "I:failed" + status=1 +fi + echo "I:exit status: $status" exit $status diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 519cb2e054..2aecee5808 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -5106,8 +5106,9 @@ badresp:1,adberr:0,findfail:0,valfail:0] notify-source (ip4_addr | *) port ip_port ; notify-source-v6 (ip6_addr | *) port ip_port ; notify-to-soa yes_or_no ; - also-notify { ip_addr port ip_port ; - ip_addr port ip_port ; ... }; + also-notify { ip_addr + port ip_port key keyname ; + ip_addr port ip_port key keyname ; ... }; max-ixfr-log-size number; max-journal-size size_spec; coresize size_spec ; @@ -7554,6 +7555,11 @@ avoid-v6-udp-ports {}; also-notify address to send the notify messages to a port other than the default of 53. + An optional TSIG key can also be specified with each + address to cause the notify messages to be signed; this + can be useful when sending notifies to multiple views. + + If an also-notify list is given in a zone statement, it will override @@ -10048,8 +10054,9 @@ zone zone_name class dnssec-loadkeys-interval number; dnssec-secure-to-insecure yes_or_no ; try-tcp-refresh yes_or_no; - also-notify { ip_addr port ip_port ; - ip_addr port ip_port ; ... }; + also-notify { ip_addr + port ip_port key keyname ; + ip_addr port ip_port ; ... key keyname ; ... }; check-names (warn|fail|ignore) ; dialup dialup_option ; file string ; @@ -10560,6 +10567,9 @@ zone zone_name classalso-notify address to send the notify messages to a port other than the default of 53. + A TSIG key may also be specified to cause the + NOTIFY to be signed by the + given key. also-notify is not meaningful for stub zones. The default is the empty list. diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 629a5bebfc..043d0371cb 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.187 2011/04/29 21:37:15 each Exp $ */ +/* $Id: zone.h,v 1.188 2011/05/06 21:23:51 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -557,10 +557,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. diff --git a/lib/dns/zone.c b/lib/dns/zone.c index ca6619c328..aaee6345c7 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.603 2011/04/29 23:47:18 tbox Exp $ */ +/* $Id: zone.c,v 1.604 2011/05/06 21:23:51 each Exp $ */ /*! \file */ @@ -229,6 +229,7 @@ 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; @@ -448,6 +449,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; }; @@ -787,6 +789,7 @@ 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; @@ -4194,48 +4197,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; @@ -4265,15 +4228,172 @@ 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; + addrs = *addrsp; + keynames = *keynamesp; + + if (addrs != NULL) { + isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t)); + addrs = *addrsp = NULL; + } + + 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 *)); + keynames = *keynamesp = NULL; + } + + count = *countp = 0; +} + +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; @@ -4291,38 +4411,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 @@ -4331,75 +4437,33 @@ 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->masters = new; zone->mastersok = newok; - zone->masterkeynames = newname; + zone->masters = newaddrs; + zone->masterkeynames = newnames; zone->masterscnt = count; DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS); @@ -8480,6 +8544,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); @@ -8501,6 +8567,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); @@ -8645,15 +8712,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) { @@ -8855,14 +8930,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) diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 8546878aa2..6fc5323dde 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.135 2011/04/29 21:37:15 each Exp $ */ +/* $Id: namedconf.c,v 1.136 2011/05/06 21:23:51 each Exp $ */ /*! \file */ @@ -228,9 +228,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 +237,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 }; /*% @@ -1329,7 +1328,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 }, { "check-dup-records", &cfg_type_checkmode, 0 },