diff --git a/CHANGES b/CHANGES index c1a8d34b24..9a715f35a4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +1515. [func] Allow transfer source to be set in a server statement. + [RT #6496] + 1514. [bug] named: isc_hash_destroy() was being called to early. [RT #9160] diff --git a/bin/named/server.c b/bin/named/server.c index d63fd4ed76..66350a7325 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.403 2003/09/19 12:39:47 marka Exp $ */ +/* $Id: server.c,v 1.404 2003/09/25 18:16:43 jinmei Exp $ */ #include @@ -553,6 +553,18 @@ configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { if (result != ISC_R_SUCCESS) goto cleanup; } + + obj = NULL; + if (isc_sockaddr_pf(sa) == AF_INET) + (void)cfg_map_get(cpeer, "transfer-source", &obj); + else + (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); + if (obj != NULL) { + result = dns_peer_settransfersource(peer, + cfg_obj_assockaddr(obj)); + if (result != ISC_R_SUCCESS) + goto cleanup; + } *peerp = peer; return (ISC_R_SUCCESS); diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 3d2f903525..b054a14eb3 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -2,7 +2,7 @@ - + BIND 9 Administrator Reference Manual @@ -4247,6 +4247,8 @@ to be incremented, and may additionally cause the transfers number ; transfer-format ( one-answer | many-answers ) ; ] keys { string ; string ; ... } ; + transfer-source (ip4_addr | *) port ip_port ; + transfer-source-v6 (ip6_addr | *) port ip_port ; }; @@ -4328,6 +4330,18 @@ to be signed by this key. allows for multiple keys, only a single key per server is currently supported. +The transfer-source and +transfer-source-v6 clauses specify the IPv4 and IPv6 source +address to be used for zone transfer with the remote server, respectively. +For an IPv4 remote server, only transfer-source can +be specified. +Similarly, for an IPv6 remote server, only +transfer-source-v6 can be specified. +Form more details, see the description of +transfer-source and +transfer-source-v6 in +. + <command>trusted-keys</command> Statement Grammar diff --git a/lib/bind9/check.c b/lib/bind9/check.c index e82c371442..f90b57a1d9 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.40 2003/09/19 12:39:48 marka Exp $ */ +/* $Id: check.c,v 1.41 2003/09/25 18:16:47 jinmei Exp $ */ #include @@ -806,10 +806,30 @@ check_servers(cfg_obj_t *servers, isc_log_t *logctx) { cfg_obj_t *v1, *v2; isc_sockaddr_t *s1, *s2; isc_netaddr_t na; + cfg_obj_t *ts; + char buf[128]; + const char *xfr; + isc_buffer_t target; for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) { v1 = cfg_listelt_value(e1); s1 = cfg_obj_assockaddr(cfg_map_getname(v1)); + ts = NULL; + if (isc_sockaddr_pf(s1) == AF_INET) + xfr = "transfer-source-v6"; + else + xfr = "transfer-source"; + (void)cfg_map_get(v1, xfr, &ts); + if (ts != NULL) { + isc_netaddr_fromsockaddr(&na, s1); + isc_buffer_init(&target, buf, sizeof(buf) - 1); + RUNTIME_CHECK(isc_netaddr_totext(&na, &target) + == ISC_R_SUCCESS); + buf[isc_buffer_usedlength(&target)] = '\0'; + cfg_obj_log(v1, logctx, ISC_LOG_ERROR, + "server '%s': %s not valid", buf, xfr); + result = ISC_R_FAILURE; + } e2 = e1; while ((e2 = cfg_list_next(e2)) != NULL) { v2 = cfg_listelt_value(e2); @@ -817,8 +837,6 @@ check_servers(cfg_obj_t *servers, isc_log_t *logctx) { if (isc_sockaddr_eqaddr(s1, s2)) { const char *file = cfg_obj_file(v1); unsigned int line = cfg_obj_line(v1); - isc_buffer_t target; - char buf[128]; if (file == NULL) file = ""; diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h index d5d47df92f..0a27421475 100644 --- a/lib/dns/include/dns/peer.h +++ b/lib/dns/include/dns/peer.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.h,v 1.18 2001/11/30 01:59:26 gson Exp $ */ +/* $Id: peer.h,v 1.19 2003/09/25 18:16:49 jinmei Exp $ */ #ifndef DNS_PEER_H #define DNS_PEER_H 1 @@ -72,6 +72,7 @@ struct dns_peer { isc_boolean_t request_ixfr; isc_boolean_t support_edns; dns_name_t *key; + isc_sockaddr_t *transfer_source; isc_uint32_t bitflags; @@ -165,6 +166,12 @@ dns_peer_getkey(dns_peer_t *peer, dns_name_t **retval); isc_result_t dns_peer_setkey(dns_peer_t *peer, dns_name_t **keyval); +isc_result_t +dns_peer_settransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source); + +isc_result_t +dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source); + ISC_LANG_ENDDECLS #endif /* DNS_PEER_H */ diff --git a/lib/dns/peer.c b/lib/dns/peer.c index 1e589cf49d..0dc1a4fac9 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -15,13 +15,14 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.c,v 1.17 2001/11/30 01:59:14 gson Exp $ */ +/* $Id: peer.c,v 1.18 2003/09/25 18:16:47 jinmei Exp $ */ #include #include #include #include +#include #include #include @@ -193,6 +194,7 @@ dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) { peer->provide_ixfr = ISC_FALSE; peer->key = NULL; peer->refs = 1; + peer->transfer_source = NULL; memset(&peer->bitflags, 0x0, sizeof(peer->bitflags)); @@ -256,6 +258,11 @@ peer_delete(dns_peer_t **peer) { isc_mem_put(mem, p->key, sizeof(dns_name_t)); } + if (p->transfer_source != NULL) { + isc_mem_put(mem, p->transfer_source, + sizeof(*p->transfer_source)); + } + isc_mem_put(mem, p, sizeof(*p)); *peer = NULL; @@ -482,3 +489,34 @@ dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) { return (result); } + +isc_result_t +dns_peer_settransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source) { + REQUIRE(DNS_PEER_VALID(peer)); + + if (peer->transfer_source != NULL) { + isc_mem_put(peer->mem, peer->transfer_source, + sizeof(*peer->transfer_source)); + peer->transfer_source = NULL; + } + if (transfer_source != NULL) { + peer->transfer_source = isc_mem_get(peer->mem, + sizeof(*peer->transfer_source)); + if (peer->transfer_source == NULL) + return (ISC_R_NOMEMORY); + + *peer->transfer_source = *transfer_source; + } + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source) { + REQUIRE(DNS_PEER_VALID(peer)); + REQUIRE(transfer_source != NULL); + + if (peer->transfer_source == NULL) + return (ISC_R_NOTFOUND); + *transfer_source = *peer->transfer_source; + return (ISC_R_SUCCESS); +} diff --git a/lib/dns/zone.c b/lib/dns/zone.c index b0e8b5adca..4c236ef5eb 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.398 2003/09/24 01:03:37 marka Exp $ */ +/* $Id: zone.c,v 1.399 2003/09/25 18:16:47 jinmei Exp $ */ #include @@ -3824,6 +3824,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { isc_uint32_t options; isc_boolean_t cancel = ISC_TRUE; int timeout; + isc_boolean_t have_xfrsource; REQUIRE(DNS_ZONE_VALID(zone)); @@ -3853,30 +3854,6 @@ soa_query(isc_task_t *task, isc_event_t *event) { zone->masteraddr = zone->masters[zone->curmaster]; - switch (isc_sockaddr_pf(&zone->masteraddr)) { - case PF_INET: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - if (isc_sockaddr_equal(&zone->altxfrsource4, - &zone->xfrsource4)) - goto skip_master; - zone->sourceaddr = zone->altxfrsource4; - } else - zone->sourceaddr = zone->xfrsource4; - break; - case PF_INET6: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - if (isc_sockaddr_equal(&zone->altxfrsource6, - &zone->xfrsource6)) - goto skip_master; - zone->sourceaddr = zone->altxfrsource6; - } else - zone->sourceaddr = zone->xfrsource6; - break; - default: - result = ISC_R_NOTIMPLEMENTED; - goto cleanup; - } - isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr); /* * First, look for a tsig key in the master statement, then @@ -3897,15 +3874,45 @@ soa_query(isc_task_t *task, isc_event_t *event) { if (key == NULL) (void)dns_view_getpeertsig(zone->view, &masterip, &key); + have_xfrsource = ISC_FALSE; if (zone->view->peers != NULL) { dns_peer_t *peer = NULL; isc_boolean_t edns; result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { result = dns_peer_getsupportedns(peer, &edns); - if (result == ISC_R_SUCCESS && !edns) - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + if (result == ISC_R_SUCCESS && !edns) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + result = dns_peer_gettransfersource(peer, + &zone->sourceaddr); + if (result == ISC_R_SUCCESS) + have_xfrsource = ISC_TRUE; + } + } + + switch (isc_sockaddr_pf(&zone->masteraddr)) { + case PF_INET: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + if (isc_sockaddr_equal(&zone->altxfrsource4, + &zone->xfrsource4)) + goto skip_master; + zone->sourceaddr = zone->altxfrsource4; + } else if (!have_xfrsource) + zone->sourceaddr = zone->xfrsource4; + break; + case PF_INET6: + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { + if (isc_sockaddr_equal(&zone->altxfrsource6, + &zone->xfrsource6)) + goto skip_master; + zone->sourceaddr = zone->altxfrsource6; + } else if (!have_xfrsource) + zone->sourceaddr = zone->xfrsource6; + break; + default: + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; } options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? @@ -3968,6 +3975,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { dns_tsigkey_t *key = NULL; dns_dbnode_t *node = NULL; int timeout; + isc_boolean_t have_xfrsource = ISC_FALSE; REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE((soardataset != NULL && stub == NULL) || @@ -4078,10 +4086,16 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { isc_boolean_t edns; result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { result = dns_peer_getsupportedns(peer, &edns); - if (result == ISC_R_SUCCESS && !edns) - DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + if (result == ISC_R_SUCCESS && !edns) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); + result = dns_peer_gettransfersource(peer, + &zone->sourceaddr); + if (result == ISC_R_SUCCESS) + have_xfrsource = ISC_TRUE; + } + } if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { result = add_opt(message); @@ -4098,13 +4112,13 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { case PF_INET: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) zone->sourceaddr = zone->altxfrsource4; - else + else if (!have_xfrsource) zone->sourceaddr = zone->xfrsource4; break; case PF_INET6: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) zone->sourceaddr = zone->altxfrsource6; - else + else if (!have_xfrsource) zone->sourceaddr = zone->xfrsource6; break; default: diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 8450a23b53..82447e51e2 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.23 2003/09/19 12:39:49 marka Exp $ */ +/* $Id: namedconf.c,v 1.24 2003/09/25 18:16:50 jinmei Exp $ */ #include @@ -824,6 +824,8 @@ server_clauses[] = { { "transfer-format", &cfg_type_transferformat, 0 }, { "keys", &cfg_type_server_key_kludge, 0 }, { "edns", &cfg_type_boolean, 0 }, + { "transfer-source", &cfg_type_sockaddr4wild, 0 }, + { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 }, { NULL, NULL, 0 } }; static cfg_clausedef_t * @@ -1579,8 +1581,8 @@ static cfg_type_t cfg_type_sockaddr4wild = { static unsigned int sockaddr6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK; static cfg_type_t cfg_type_sockaddr6wild = { - "v6addrportwild", cfg_parse_sockaddr, cfg_print_sockaddr, cfg_doc_sockaddr, - &cfg_rep_sockaddr, &sockaddr6wild_flags + "v6addrportwild", cfg_parse_sockaddr, cfg_print_sockaddr, + cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr6wild_flags }; /*