2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 15:05:23 +00:00

2129. [func] Provide a pool of UDP sockets for queries to be

made over. See use-queryport-pool, queryport-pool-ports
                        and queryport-pool-updateinterval.  [RT #16415]
This commit is contained in:
Mark Andrews
2007-02-02 02:18:06 +00:00
parent 1f369c2581
commit 281bab0f36
10 changed files with 622 additions and 50 deletions

View File

@@ -1,3 +1,7 @@
2129. [func] Provide a pool of UDP sockets for queries to be
made over. See use-queryport-pool, queryport-pool-ports
and queryport-pool-updateinterval. [RT #16415]
2128. [doc] xsltproc --nonet, update DTD versions. [RT #16635] 2128. [doc] xsltproc --nonet, update DTD versions. [RT #16635]
2127. [port] Improved OpenSSL 0.9.8 support. [RT #16563] 2127. [port] Improved OpenSSL 0.9.8 support. [RT #16563]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: interfacemgr.c,v 1.85 2006/07/20 01:10:31 marka Exp $ */ /* $Id: interfacemgr.c,v 1.86 2007/02/02 02:18:03 marka Exp $ */
/*! \file */ /*! \file */
@@ -802,7 +802,9 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
(void)dns_acl_match(&listen_netaddr, (void)dns_acl_match(&listen_netaddr,
NULL, ele->acl, NULL, ele->acl,
NULL, &match, NULL); NULL, &match, NULL);
if (match > 0 && ele->port == le->port) if (match > 0 &&
(ele->port == le->port ||
ele->port == 0))
break; break;
else else
match = 0; match = 0;

View File

@@ -17,7 +17,7 @@
- PERFORMANCE OF THIS SOFTWARE. - PERFORMANCE OF THIS SOFTWARE.
--> -->
<!-- $Id: named.conf.docbook,v 1.26 2007/01/29 23:57:22 marka Exp $ --> <!-- $Id: named.conf.docbook,v 1.27 2007/02/02 02:18:04 marka Exp $ -->
<refentry> <refentry>
<refentryinfo> <refentryinfo>
<date>Aug 13, 2004</date> <date>Aug 13, 2004</date>
@@ -235,6 +235,9 @@ options {
additional-from-cache <replaceable>boolean</replaceable>; additional-from-cache <replaceable>boolean</replaceable>;
query-source ( ( <replaceable>ipv4_address</replaceable> | * ) | <optional> address ( <replaceable>ipv4_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>; query-source ( ( <replaceable>ipv4_address</replaceable> | * ) | <optional> address ( <replaceable>ipv4_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
query-source-v6 ( ( <replaceable>ipv6_address</replaceable> | * ) | <optional> address ( <replaceable>ipv6_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>; query-source-v6 ( ( <replaceable>ipv6_address</replaceable> | * ) | <optional> address ( <replaceable>ipv6_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
use-queryport-pool <replaceable>boolean</replaceable>;
queryport-pool-ports <replaceable>integer</replaceable>;
queryport-pool-updateinterval <replaceable>integer</replaceable>;
cleaning-interval <replaceable>integer</replaceable>; cleaning-interval <replaceable>integer</replaceable>;
min-roots <replaceable>integer</replaceable>; // not implemented min-roots <replaceable>integer</replaceable>; // not implemented
lame-ttl <replaceable>integer</replaceable>; lame-ttl <replaceable>integer</replaceable>;
@@ -384,6 +387,9 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
additional-from-cache <replaceable>boolean</replaceable>; additional-from-cache <replaceable>boolean</replaceable>;
query-source ( ( <replaceable>ipv4_address</replaceable> | * ) | <optional> address ( <replaceable>ipv4_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>; query-source ( ( <replaceable>ipv4_address</replaceable> | * ) | <optional> address ( <replaceable>ipv4_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
query-source-v6 ( ( <replaceable>ipv6_address</replaceable> | * ) | <optional> address ( <replaceable>ipv6_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>; query-source-v6 ( ( <replaceable>ipv6_address</replaceable> | * ) | <optional> address ( <replaceable>ipv6_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
use-queryport-pool <replaceable>boolean</replaceable>;
queryport-pool-ports <replaceable>integer</replaceable>;
queryport-pool-updateinterval <replaceable>integer</replaceable>;
cleaning-interval <replaceable>integer</replaceable>; cleaning-interval <replaceable>integer</replaceable>;
min-roots <replaceable>integer</replaceable>; // not implemented min-roots <replaceable>integer</replaceable>; // not implemented
lame-ttl <replaceable>integer</replaceable>; lame-ttl <replaceable>integer</replaceable>;

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: server.c,v 1.475 2007/01/12 00:14:51 marka Exp $ */ /* $Id: server.c,v 1.476 2007/02/02 02:18:05 marka Exp $ */
/*! \file */ /*! \file */
@@ -953,7 +953,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
const char *str; const char *str;
dns_order_t *order = NULL; dns_order_t *order = NULL;
isc_uint32_t udpsize; isc_uint32_t udpsize;
unsigned int check = 0; unsigned int resopts = 0;
dns_zone_t *zone = NULL; dns_zone_t *zone = NULL;
isc_uint32_t max_clients_per_query; isc_uint32_t max_clients_per_query;
const char *sep = ": view "; const char *sep = ": view ";
@@ -962,6 +962,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
isc_boolean_t rfc1918; isc_boolean_t rfc1918;
isc_boolean_t empty_zones_enable; isc_boolean_t empty_zones_enable;
const cfg_obj_t *disablelist = NULL; const cfg_obj_t *disablelist = NULL;
isc_uint32_t nqports, qports_updateinterval;
REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(DNS_VIEW_VALID(view));
@@ -1184,14 +1185,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
str = cfg_obj_asstring(obj); str = cfg_obj_asstring(obj);
if (strcasecmp(str, "fail") == 0) { if (strcasecmp(str, "fail") == 0) {
check = DNS_RESOLVER_CHECKNAMES | resopts |= DNS_RESOLVER_CHECKNAMES |
DNS_RESOLVER_CHECKNAMESFAIL; DNS_RESOLVER_CHECKNAMESFAIL;
view->checknames = ISC_TRUE; view->checknames = ISC_TRUE;
} else if (strcasecmp(str, "warn") == 0) { } else if (strcasecmp(str, "warn") == 0) {
check = DNS_RESOLVER_CHECKNAMES; resopts |= DNS_RESOLVER_CHECKNAMES;
view->checknames = ISC_FALSE; view->checknames = ISC_FALSE;
} else if (strcasecmp(str, "ignore") == 0) { } else if (strcasecmp(str, "ignore") == 0) {
check = 0;
view->checknames = ISC_FALSE; view->checknames = ISC_FALSE;
} else } else
INSIST(0); INSIST(0);
@@ -1210,11 +1210,93 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
result = ISC_R_UNEXPECTED; result = ISC_R_UNEXPECTED;
goto cleanup; goto cleanup;
} }
obj = NULL;
(void)ns_config_get(maps, "use-queryport-pool", &obj);
if (obj == NULL || cfg_obj_asboolean(obj)) {
isc_sockaddr_t sa;
isc_boolean_t logit4 = ISC_FALSE, logit6 = ISC_FALSE;
resopts |= (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6);
/* Check consistency with query-source(-v6) */
if (dispatch4 == NULL)
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL4;
else {
result = dns_dispatch_getlocaladdress(dispatch4, &sa);
INSIST(result == ISC_R_SUCCESS);
if (isc_sockaddr_getport(&sa) != 0) {
logit4 = ISC_TRUE;
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL4;
}
}
if (dispatch6 == NULL)
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL6;
else {
result = dns_dispatch_getlocaladdress(dispatch6, &sa);
INSIST(result == ISC_R_SUCCESS);
if (isc_sockaddr_getport(&sa) != 0) {
logit6 = ISC_TRUE;
resopts &= ~DNS_RESOLVER_USEDISPATCHPOOL6;
}
}
if (logit4 && obj != NULL)
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"specific query-source port "
"cannot coexist with queryport-pool. "
"(Pool disabled)");
if (logit6 && obj != NULL)
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"specific query-source-v6 port "
"cannot coexist with queryport-pool. "
"(Pool disabled)");
}
CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
ns_g_socketmgr, ns_g_timermgr, ns_g_socketmgr, ns_g_timermgr,
check, ns_g_dispatchmgr, resopts, ns_g_dispatchmgr,
dispatch4, dispatch6)); dispatch4, dispatch6));
/*
* Query-port pool parameters.
*/
obj = NULL;
nqports = 8;
result = ns_config_get(maps, "queryport-pool-ports", &obj);
if (result == ISC_R_SUCCESS) {
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) == 0) {
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"queryport-pool-ports is effective only "
"with 'use-queryport-pool yes' (ignored)");
} else
nqports = cfg_obj_asuint32(obj);
}
obj = NULL;
qports_updateinterval = 15;
result = ns_config_get(maps, "queryport-pool-updateinterval", &obj);
if (result == ISC_R_SUCCESS) {
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) == 0) {
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
"queryport-pool-updateinterval is "
"effective only with 'use-queryport-pool "
"yes' (ignored)");
} else
qports_updateinterval = cfg_obj_asuint32(obj);
}
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) != 0) {
CHECK(dns_resolver_createdispatchpool(view->resolver,
nqports,
qports_updateinterval
* 60));
}
/* /*
* Set the ADB cache size to 1/8th of the max-cache-size. * Set the ADB cache size to 1/8th of the max-cache-size.
*/ */
@@ -1241,7 +1323,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj); result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj)); dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj));
/* /*
* Set the resolver's EDNS UDP size. * Set the resolver's EDNS UDP size.
*/ */
@@ -2376,7 +2458,9 @@ scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
} }
static isc_result_t static isc_result_t
add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) { add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
isc_boolean_t wcardport_ok)
{
ns_listenelt_t *lelt = NULL; ns_listenelt_t *lelt = NULL;
dns_acl_t *src_acl = NULL; dns_acl_t *src_acl = NULL;
dns_aclelement_t aelt; dns_aclelement_t aelt;
@@ -2386,7 +2470,8 @@ add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) {
REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
isc_sockaddr_any6(&any_sa6); isc_sockaddr_any6(&any_sa6);
if (!isc_sockaddr_equal(&any_sa6, addr)) { if (!isc_sockaddr_equal(&any_sa6, addr) &&
(wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
aelt.type = dns_aclelementtype_ipprefix; aelt.type = dns_aclelementtype_ipprefix;
aelt.negative = ISC_FALSE; aelt.negative = ISC_FALSE;
aelt.u.ip_prefix.prefixlen = 128; aelt.u.ip_prefix.prefixlen = 128;
@@ -2438,6 +2523,8 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
view != NULL; view != NULL;
view = ISC_LIST_NEXT(view, link)) { view = ISC_LIST_NEXT(view, link)) {
dns_dispatch_t *dispatch6; dns_dispatch_t *dispatch6;
isc_boolean_t use_portpool = ISC_FALSE;
unsigned int resopts;
dispatch6 = dns_resolver_dispatchv6(view->resolver); dispatch6 = dns_resolver_dispatchv6(view->resolver);
if (dispatch6 == NULL) if (dispatch6 == NULL)
@@ -2445,7 +2532,19 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
result = dns_dispatch_getlocaladdress(dispatch6, &addr); result = dns_dispatch_getlocaladdress(dispatch6, &addr);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto fail; goto fail;
result = add_listenelt(mctx, list, &addr); resopts = dns_resolver_getoptions(view->resolver);
if ((resopts & (DNS_RESOLVER_USEDISPATCHPOOL4 |
DNS_RESOLVER_USEDISPATCHPOOL6)) != 0) {
/*
* If the resolver uses a dynamic pool of query ports
* with a specific source address, some of the current
* and future ports may override an existing wildcard
* IPv6 port. So we need to allow wildcard match
* in this case.
*/
use_portpool = ISC_TRUE;
}
result = add_listenelt(mctx, list, &addr, use_portpool);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto fail; goto fail;
} }
@@ -2475,12 +2574,12 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
continue; continue;
addrp = dns_zone_getnotifysrc6(zone); addrp = dns_zone_getnotifysrc6(zone);
result = add_listenelt(mctx, list, addrp); result = add_listenelt(mctx, list, addrp, ISC_FALSE);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto fail; goto fail;
addrp = dns_zone_getxfrsource6(zone); addrp = dns_zone_getxfrsource6(zone);
result = add_listenelt(mctx, list, addrp); result = add_listenelt(mctx, list, addrp, ISC_FALSE);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto fail; goto fail;
} }

View File

@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE. - PERFORMANCE OF THIS SOFTWARE.
--> -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.312 2007/01/29 23:57:22 marka Exp $ --> <!-- File: $Id: Bv9ARM-book.xml,v 1.313 2007/02/02 02:18:05 marka Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude"> <book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title> <title>BIND 9 Administrator Reference Manual</title>
@@ -4443,6 +4443,9 @@ category notify { null; };
<optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> | <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> |
<optional> address ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> address ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
<optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> ) ; </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> ) ; </optional>
<optional> use-queryport-pool <replaceable>yse_or_no</replaceable>; </optional>
<optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
<optional> queryport-pool-interval <replaceable>number</replaceable>; </optional>
<optional> max-transfer-time-in <replaceable>number</replaceable>; </optional> <optional> max-transfer-time-in <replaceable>number</replaceable>; </optional>
<optional> max-transfer-time-out <replaceable>number</replaceable>; </optional> <optional> max-transfer-time-out <replaceable>number</replaceable>; </optional>
<optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional> <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional>
@@ -6074,7 +6077,7 @@ listen-on-v6 port 1234 { !2001:db8::/32; any; };
</para> </para>
</sect3> </sect3>
<sect3> <sect3 id="query_address">
<title>Query Address</title> <title>Query Address</title>
<para> <para>
If the server doesn't know the answer to a question, it will If the server doesn't know the answer to a question, it will
@@ -6085,22 +6088,61 @@ listen-on-v6 port 1234 { !2001:db8::/32; any; };
a wildcard IP address (<command>INADDR_ANY</command>) a wildcard IP address (<command>INADDR_ANY</command>)
will be used. will be used.
If <command>port</command> is <command>*</command> or is omitted, If <command>port</command> is <command>*</command> or is omitted,
a random unprivileged port will be used. The <command>avoid-v4-udp-ports</command> a pool of random unprivileged port will be used. See
<command>use-queryport-pool</command>,
<command>queryport-pool-ports</command> and
<command>queryport-pool-updateinterval</command> for how the pool
is configured.
The <command>avoid-v4-udp-ports</command>
and <command>avoid-v6-udp-ports</command> options can be used and <command>avoid-v6-udp-ports</command> options can be used
to prevent named to prevent named
from selecting certain ports. The defaults are: from selecting certain ports.
The defaults are:
</para> </para>
<programlisting>query-source address * port *; <programlisting>query-source address * port *;
query-source-v6 address * port *; query-source-v6 address * port *;
</programlisting> </programlisting>
<variablelist>
<varlistentry>
<term><command>use-queryport-pool</command></term>
<listitem>
<para>
Enable they use of query port pools. By default query port
pools are enabled unless there is a explicit port defined
in <command>query-source</command> or
<command>query-source-v6</command>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>queryport-pool-ports</command></term>
<listitem>
<para>
Specify how many pool ports to use. The default is 8.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>queryport-pool-updateinterval</command></term>
<listitem>
<para>
Specify how often, in minutes, that the queryport pool
should be recreated (new ports selected). The default
is 15 minutes.
</para>
</listitem>
</varlistentry>
</variablelist>
<note> <note>
<para> <para>
The address specified in the <command>query-source</command> option The address specified in the <command>query-source</command> option
is used for both UDP and TCP queries, but the port applies only is used for both UDP and TCP queries, but the port applies only
to to UDP queries. TCP queries always use a random
UDP queries. TCP queries always use a random
unprivileged port. unprivileged port.
</para> </para>
</note> </note>
@@ -7669,6 +7711,9 @@ query-source-v6 address * port *;
<optional> query-source <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional> <optional> query-source <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional>
<optional> query-source-v6 <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional> <optional> query-source-v6 <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional>
}; };
<optional> use-queryport-pool <replaceable>yse_or_no</replaceable>; </optional>
<optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
<optional> queryport-pool-interval <replaceable>number</replaceable>; </optional>
</programlisting> </programlisting>
</sect2> </sect2>

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: dispatch.c,v 1.127 2006/07/19 00:42:13 marka Exp $ */ /* $Id: dispatch.c,v 1.128 2007/02/02 02:18:06 marka Exp $ */
/*! \file */ /*! \file */
@@ -282,6 +282,20 @@ reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
lfsr->state = random(); lfsr->state = random();
} }
/*
* Return an unpredictable non-reserved UDP port. We share the QID
* framework for this purpose.
*/
static in_port_t
get_randomport(dns_qid_t *qid) {
isc_uint32_t p;
p = isc_lfsr_generate32(&qid->qid_lfsr1, &qid->qid_lfsr2);
/* XXX: should the range be configurable? */
return ((in_port_t)(1024 + (p % (65535 - 1024))));
}
/* /*
* Return an unpredictable message ID. * Return an unpredictable message ID.
*/ */
@@ -1290,20 +1304,26 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
} }
static isc_boolean_t static isc_boolean_t
blacklisted(dns_dispatchmgr_t *mgr, isc_socket_t *sock) { blacklisted(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
isc_sockaddr_t *sockaddrp)
{
isc_sockaddr_t sockaddr; isc_sockaddr_t sockaddr;
isc_result_t result; isc_result_t result;
REQUIRE(sock != NULL || sockaddrp != NULL);
if (mgr->portlist == NULL) if (mgr->portlist == NULL)
return (ISC_FALSE); return (ISC_FALSE);
result = isc_socket_getsockname(sock, &sockaddr); if (sock != NULL) {
if (result != ISC_R_SUCCESS) sockaddrp = &sockaddr;
return (ISC_FALSE); result = isc_socket_getsockname(sock, sockaddrp);
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
}
if (mgr->portlist != NULL && if (dns_portlist_match(mgr->portlist, isc_sockaddr_pf(sockaddrp),
dns_portlist_match(mgr->portlist, isc_sockaddr_pf(&sockaddr), isc_sockaddr_getport(sockaddrp)))
isc_sockaddr_getport(&sockaddr)))
return (ISC_TRUE); return (ISC_TRUE);
return (ISC_FALSE); return (ISC_FALSE);
} }
@@ -1324,7 +1344,7 @@ local_addr_match(dns_dispatch_t *disp, isc_sockaddr_t *addr) {
if (disp->mgr->portlist != NULL && if (disp->mgr->portlist != NULL &&
isc_sockaddr_getport(addr) == 0 && isc_sockaddr_getport(addr) == 0 &&
isc_sockaddr_getport(&disp->local) == 0 && isc_sockaddr_getport(&disp->local) == 0 &&
blacklisted(disp->mgr, disp->socket)) blacklisted(disp->mgr, disp->socket, NULL))
return (ISC_FALSE); return (ISC_FALSE);
/* /*
@@ -1669,7 +1689,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
dns_dispatch_t **dispp) dns_dispatch_t **dispp)
{ {
isc_result_t result; isc_result_t result;
dns_dispatch_t *disp; dns_dispatch_t *disp = NULL;
REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(sockmgr != NULL); REQUIRE(sockmgr != NULL);
@@ -1689,10 +1709,14 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
LOCK(&mgr->lock); LOCK(&mgr->lock);
if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) != 0) {
REQUIRE(isc_sockaddr_getport(localaddr) == 0);
goto createudp;
}
/* /*
* First, see if we have a dispatcher that matches. * See if we have a dispatcher that matches.
*/ */
disp = NULL;
result = dispatch_find(mgr, localaddr, attributes, mask, &disp); result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
disp->refcount++; disp->refcount++;
@@ -1717,6 +1741,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
createudp:
/* /*
* Nope, create one. * Nope, create one.
*/ */
@@ -1752,7 +1777,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
dns_dispatch_t *disp; dns_dispatch_t *disp;
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc_socket_t *held[DNS_DISPATCH_HELD]; isc_socket_t *held[DNS_DISPATCH_HELD];
unsigned int i = 0, j = 0; unsigned int i = 0, j = 0, k = 0;
isc_sockaddr_t localaddr_bound;
/* /*
* dispatch_allocate() checks mgr for us. * dispatch_allocate() checks mgr for us.
@@ -1768,11 +1794,30 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
* from returning the same port to us too quickly. * from returning the same port to us too quickly.
*/ */
memset(held, 0, sizeof(held)); memset(held, 0, sizeof(held));
localaddr_bound = *localaddr;
getsocket: getsocket:
result = create_socket(sockmgr, localaddr, &sock); if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) != 0) {
isc_sockaddr_setport(&localaddr_bound,
get_randomport(mgr->qid));
if (blacklisted(mgr, NULL, &localaddr_bound)) {
if (++k == 1024)
attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
goto getsocket;
}
result = create_socket(sockmgr, &localaddr_bound, &sock);
if (result == ISC_R_ADDRINUSE) {
if (++k == 1024)
attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
goto getsocket;
}
} else
result = create_socket(sockmgr, localaddr, &sock);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto deallocate_dispatch; goto deallocate_dispatch;
if (isc_sockaddr_getport(localaddr) == 0 && blacklisted(mgr, sock)) { if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) == 0 &&
isc_sockaddr_getport(localaddr) == 0 &&
blacklisted(mgr, sock, NULL))
{
if (held[i] != NULL) if (held[i] != NULL)
isc_socket_detach(&held[i]); isc_socket_detach(&held[i]);
held[i++] = sock; held[i++] = sock;

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: dispatch.h,v 1.52 2006/12/22 01:59:43 marka Exp $ */ /* $Id: dispatch.h,v 1.53 2007/02/02 02:18:06 marka Exp $ */
#ifndef DNS_DISPATCH_H #ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1 #define DNS_DISPATCH_H 1
@@ -113,6 +113,9 @@ struct dns_dispatchevent {
* _MAKEQUERY * _MAKEQUERY
* The dispatcher can be used to issue queries to other servers, and * The dispatcher can be used to issue queries to other servers, and
* accept replies from them. * accept replies from them.
*
* _RANDOMPORT
* TBD
*/ */
#define DNS_DISPATCHATTR_PRIVATE 0x00000001U #define DNS_DISPATCHATTR_PRIVATE 0x00000001U
#define DNS_DISPATCHATTR_TCP 0x00000002U #define DNS_DISPATCHATTR_TCP 0x00000002U
@@ -122,6 +125,7 @@ struct dns_dispatchevent {
#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U #define DNS_DISPATCHATTR_NOLISTEN 0x00000020U
#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U #define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U #define DNS_DISPATCHATTR_CONNECTED 0x00000080U
#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U
/*@}*/ /*@}*/
isc_result_t isc_result_t

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: resolver.h,v 1.53 2006/12/22 01:45:00 marka Exp $ */ /* $Id: resolver.h,v 1.54 2007/02/02 02:18:06 marka Exp $ */
#ifndef DNS_RESOLVER_H #ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1 #define DNS_RESOLVER_H 1
@@ -106,6 +106,8 @@ typedef struct dns_fetchevent {
#define DNS_RESOLVER_CHECKNAMES 0x01 #define DNS_RESOLVER_CHECKNAMES 0x01
#define DNS_RESOLVER_CHECKNAMESFAIL 0x02 #define DNS_RESOLVER_CHECKNAMESFAIL 0x02
#define DNS_RESOLVER_USEDISPATCHPOOL4 0x04
#define DNS_RESOLVER_USEDISPATCHPOOL6 0x08
isc_result_t isc_result_t
dns_resolver_create(dns_view_t *view, dns_resolver_create(dns_view_t *view,
@@ -126,8 +128,6 @@ dns_resolver_create(dns_view_t *view,
*\li Generally, applications should not create a resolver directly, but *\li Generally, applications should not create a resolver directly, but
* should instead call dns_view_createresolver(). * should instead call dns_view_createresolver().
* *
*\li No options are currently defined.
*
* Requires: * Requires:
* *
*\li 'view' is a valid view. *\li 'view' is a valid view.
@@ -474,6 +474,36 @@ dns_resolver_getzeronosoattl(dns_resolver_t *resolver);
void void
dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state); dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
unsigned int
dns_resolver_getoptions(dns_resolver_t *resolver);
isc_result_t
dns_resolver_createdispatchpool(dns_resolver_t *res, unsigned int ndisps,
unsigned int interval);
/*%<
* Create a pool of dispatches
*
* Notes:
*
*\li Generally, applications should not create a resolver directly, but
* should instead call dns_view_createresolver().
*
* Requires:
*
*\li 'res' is a valid resolver that has not been frozen. Also it must have
* either the _USEDISPATCHPOOL4 or _USEDISPATCHPOOL6 option.
*
*\li 'taskmgr' is a valid task manager.
*
*\li 'ndisps' > 0.
*
* Returns:
*
*\li #ISC_R_SUCCESS On success.
*
*\li Anything else Failure.
*/
ISC_LANG_ENDDECLS ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */ #endif /* DNS_RESOLVER_H */

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: resolver.c,v 1.340 2007/01/08 01:13:38 marka Exp $ */ /* $Id: resolver.c,v 1.341 2007/02/02 02:18:06 marka Exp $ */
/*! \file */ /*! \file */
@@ -23,6 +23,7 @@
#include <isc/print.h> #include <isc/print.h>
#include <isc/string.h> #include <isc/string.h>
#include <isc/random.h>
#include <isc/task.h> #include <isc/task.h>
#include <isc/timer.h> #include <isc/timer.h>
#include <isc/util.h> #include <isc/util.h>
@@ -290,13 +291,36 @@ typedef struct alternate {
ISC_LINK(struct alternate) link; ISC_LINK(struct alternate) link;
} alternate_t; } alternate_t;
#ifdef ISC_RWLOCK_USEATOMIC
#define DNS_RESOLVER_USERWLOCK 1
#else
#define DNS_RESOLVER_USERWLOCK 0
#endif
#if DNS_RESOLVER_USERWLOCK
#define RES_INITLOCK(l) isc_rwlock_init((l), 0, 0)
#define RES_DESTROYLOCK(l) isc_rwlock_destroy(l)
#define RES_LOCK(l, t) RWLOCK((l), (t))
#define RES_UNLOCK(l, t) RWUNLOCK((l), (t))
#else
#define RES_INITLOCK(l) isc_mutex_init(l)
#define RES_DESTROYLOCK(l) DESTROYLOCK(l)
#define RES_LOCK(l, t) LOCK(l)
#define RES_UNLOCK(l, t) UNLOCK(l)
#endif
struct dns_resolver { struct dns_resolver {
/* Unlocked. */ /* Unlocked. */
unsigned int magic; unsigned int magic;
isc_mem_t * mctx; isc_mem_t * mctx;
isc_mutex_t lock; isc_mutex_t lock;
isc_mutex_t nlock; isc_mutex_t nlock;
isc_mutex_t primelock; isc_mutex_t primelock;
#if DNS_RESOLVER_USERWLOCK
isc_rwlock_t poollock;
#else
isc_mutex_t poollock;
#endif
dns_rdataclass_t rdclass; dns_rdataclass_t rdclass;
isc_socketmgr_t * socketmgr; isc_socketmgr_t * socketmgr;
isc_timermgr_t * timermgr; isc_timermgr_t * timermgr;
@@ -307,6 +331,7 @@ struct dns_resolver {
dns_dispatchmgr_t * dispatchmgr; dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatchv4; dns_dispatch_t * dispatchv4;
dns_dispatch_t * dispatchv6; dns_dispatch_t * dispatchv6;
unsigned int ndisps;
unsigned int nbuckets; unsigned int nbuckets;
fctxbucket_t * buckets; fctxbucket_t * buckets;
isc_uint32_t lame_ttl; isc_uint32_t lame_ttl;
@@ -324,6 +349,7 @@ struct dns_resolver {
unsigned int spillatmin; unsigned int spillatmin;
isc_timer_t * spillattimer; isc_timer_t * spillattimer;
isc_boolean_t zero_no_soa_ttl; isc_boolean_t zero_no_soa_ttl;
isc_timer_t * disppooltimer;
/* Locked by lock. */ /* Locked by lock. */
unsigned int references; unsigned int references;
isc_boolean_t exiting; isc_boolean_t exiting;
@@ -331,10 +357,14 @@ struct dns_resolver {
unsigned int activebuckets; unsigned int activebuckets;
isc_boolean_t priming; isc_boolean_t priming;
unsigned int spillat; unsigned int spillat;
unsigned int nextdisp;
/* Locked by primelock. */ /* Locked by primelock. */
dns_fetch_t * primefetch; dns_fetch_t * primefetch;
/* Locked by nlock. */ /* Locked by nlock. */
unsigned int nfctx; unsigned int nfctx;
/* Locked by poollock. */
dns_dispatch_t ** dispatchv4pool;
dns_dispatch_t ** dispatchv6pool;
}; };
#define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!') #define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
@@ -1143,14 +1173,39 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_query; goto cleanup_query;
} else { } else {
int did = 0;
isc_uint32_t val;
if (res->ndisps > 0) {
isc_random_get(&val);
did = val % res->ndisps;
}
switch (isc_sockaddr_pf(&addrinfo->sockaddr)) { switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
case PF_INET: case PF_INET:
dns_dispatch_attach(res->dispatchv4, if (res->ndisps > 0) {
&query->dispatch); RES_LOCK(&res->poollock,
isc_rwlocktype_read);
dns_dispatch_attach(res->dispatchv4pool[did],
&query->dispatch);
RES_UNLOCK(&res->poollock,
isc_rwlocktype_read);
} else {
dns_dispatch_attach(res->dispatchv4,
&query->dispatch);
}
break; break;
case PF_INET6: case PF_INET6:
dns_dispatch_attach(res->dispatchv6, if (res->ndisps > 0) {
&query->dispatch); RES_LOCK(&res->poollock,
isc_rwlocktype_read);
dns_dispatch_attach(res->dispatchv6pool[did],
&query->dispatch);
RES_UNLOCK(&res->poollock,
isc_rwlocktype_read);
} else {
dns_dispatch_attach(res->dispatchv6,
&query->dispatch);
}
break; break;
default: default:
result = ISC_R_NOTIMPLEMENTED; result = ISC_R_NOTIMPLEMENTED;
@@ -5962,6 +6017,7 @@ destroy(dns_resolver_t *res) {
INSIST(res->nfctx == 0); INSIST(res->nfctx == 0);
RES_DESTROYLOCK(&res->poollock);
DESTROYLOCK(&res->primelock); DESTROYLOCK(&res->primelock);
DESTROYLOCK(&res->nlock); DESTROYLOCK(&res->nlock);
DESTROYLOCK(&res->lock); DESTROYLOCK(&res->lock);
@@ -5978,12 +6034,26 @@ destroy(dns_resolver_t *res) {
dns_dispatch_detach(&res->dispatchv4); dns_dispatch_detach(&res->dispatchv4);
if (res->dispatchv6 != NULL) if (res->dispatchv6 != NULL)
dns_dispatch_detach(&res->dispatchv6); dns_dispatch_detach(&res->dispatchv6);
if (res->dispatchv4pool != NULL) {
for (i = 0; i < res->ndisps; i++)
dns_dispatch_detach(&res->dispatchv4pool[i]);
isc_mem_put(res->mctx, res->dispatchv4pool,
res->ndisps * sizeof(dns_dispatch_t *));
}
if (res->dispatchv6pool != NULL) {
for (i = 0; i < res->ndisps; i++)
dns_dispatch_detach(&res->dispatchv6pool[i]);
isc_mem_put(res->mctx, res->dispatchv6pool,
res->ndisps * sizeof(dns_dispatch_t *));
}
while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) { while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
ISC_LIST_UNLINK(res->alternates, a, link); ISC_LIST_UNLINK(res->alternates, a, link);
if (!a->isaddress) if (!a->isaddress)
dns_name_free(&a->_u._n.name, res->mctx); dns_name_free(&a->_u._n.name, res->mctx);
isc_mem_put(res->mctx, a, sizeof(*a)); isc_mem_put(res->mctx, a, sizeof(*a));
} }
if (res->disppooltimer != NULL)
isc_timer_detach(&res->disppooltimer);
dns_resolver_reset_algorithms(res); dns_resolver_reset_algorithms(res);
dns_resolver_resetmustbesecure(res); dns_resolver_resetmustbesecure(res);
#if USE_ALGLOCK #if USE_ALGLOCK
@@ -6112,6 +6182,11 @@ dns_resolver_create(dns_view_t *view,
res->spillatmax = 100; res->spillatmax = 100;
res->spillattimer = NULL; res->spillattimer = NULL;
res->zero_no_soa_ttl = ISC_FALSE; res->zero_no_soa_ttl = ISC_FALSE;
res->ndisps = 0;
res->nextdisp = 0; /* meaningless at this point, but init it */
res->dispatchv4pool = NULL;
res->dispatchv6pool = NULL;
res->disppooltimer = NULL;
res->nbuckets = ntasks; res->nbuckets = ntasks;
res->activebuckets = ntasks; res->activebuckets = ntasks;
@@ -6147,7 +6222,8 @@ dns_resolver_create(dns_view_t *view,
res->dispatchv4 = NULL; res->dispatchv4 = NULL;
if (dispatchv4 != NULL) if (dispatchv4 != NULL)
dns_dispatch_attach(dispatchv4, &res->dispatchv4); dns_dispatch_attach(dispatchv4, &res->dispatchv4);
res->dispatchv6 = NULL; res->dispatchv6 = NULL;
if (dispatchv6 != NULL) if (dispatchv6 != NULL)
dns_dispatch_attach(dispatchv6, &res->dispatchv6); dns_dispatch_attach(dispatchv6, &res->dispatchv6);
@@ -6172,17 +6248,21 @@ dns_resolver_create(dns_view_t *view,
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_nlock; goto cleanup_nlock;
result = RES_INITLOCK(&res->poollock);
if (result != ISC_R_SUCCESS)
goto cleanup_primelock;
task = NULL; task = NULL;
result = isc_task_create(taskmgr, 0, &task); result = isc_task_create(taskmgr, 0, &task);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_primelock; goto cleanup_poollock;
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
task, spillattimer_countdown, res, task, spillattimer_countdown, res,
&res->spillattimer); &res->spillattimer);
isc_task_detach(&task); isc_task_detach(&task);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_primelock; goto cleanup_poollock;
#if USE_ALGLOCK #if USE_ALGLOCK
result = isc_rwlock_init(&res->alglock, 0, 0); result = isc_rwlock_init(&res->alglock, 0, 0);
@@ -6212,6 +6292,9 @@ dns_resolver_create(dns_view_t *view,
isc_timer_detach(&res->spillattimer); isc_timer_detach(&res->spillattimer);
#endif #endif
cleanup_poollock:
RES_DESTROYLOCK(&res->poollock);
cleanup_primelock: cleanup_primelock:
DESTROYLOCK(&res->primelock); DESTROYLOCK(&res->primelock);
@@ -7112,3 +7195,254 @@ dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
resolver->zero_no_soa_ttl = state; resolver->zero_no_soa_ttl = state;
} }
unsigned int
dns_resolver_getoptions(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->options);
}
static void
disppooltimer_update(isc_task_t *task, isc_event_t *event) {
dns_resolver_t *res = event->ev_arg;
isc_sockaddr_t addr4, addr6;
dns_dispatch_t *disp4, *disp6;
isc_result_t result;
unsigned int nxt;
unsigned int attrs_base, attrs, attrmask;
REQUIRE(VALID_RESOLVER(res));
REQUIRE((res->options & DNS_RESOLVER_USEDISPATCHPOOL4) != 0 ||
(res->options & DNS_RESOLVER_USEDISPATCHPOOL6) != 0);
UNUSED(task);
isc_event_free(&event);
LOCK(&res->lock);
nxt = res->nextdisp++;
if (res->nextdisp == res->ndisps)
res->nextdisp = 0;
UNLOCK(&res->lock);
attrs_base = 0;
attrs_base |= DNS_DISPATCHATTR_UDP;
attrs_base |= DNS_DISPATCHATTR_RANDOMPORT;
attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP;
attrmask |= DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4;
attrmask |= DNS_DISPATCHATTR_IPV6;
RES_LOCK(&res->poollock, isc_rwlocktype_read);
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL4) != 0) {
result = dns_dispatch_getlocaladdress(res->dispatchv4pool[nxt],
&addr4);
INSIST(result == ISC_R_SUCCESS);
}
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL6) != 0) {
result = dns_dispatch_getlocaladdress(res->dispatchv6pool[nxt],
&addr6);
INSIST(result == ISC_R_SUCCESS);
}
RES_UNLOCK(&res->poollock, isc_rwlocktype_read);
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL4) != 0) {
attrs = attrs_base;
attrs |= DNS_DISPATCHATTR_IPV4;
disp4 = NULL;
result = dns_dispatch_getudp(res->dispatchmgr,
res->socketmgr,
res->taskmgr, &addr4,
4096, 1000, 32768, 16411,
16433, attrs, attrmask,
&disp4);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
"could not update an IPv4 random query "
"port: %s",
isc_result_totext(result));
/* keep the old one */
}
/*
* We don't try to ensure the new dispatch is unique (see the
* comments in dns_resolver_createdispatchpool()).
*/
}
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL6) != 0) {
attrs = attrs_base;
attrs |= DNS_DISPATCHATTR_IPV6;
disp6 = NULL;
result = dns_dispatch_getudp(res->dispatchmgr,
res->socketmgr,
res->taskmgr, &addr6,
4096, 1000, 32768, 16411,
16433, attrs, attrmask,
&disp6);
if (result != ISC_R_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
"could not update an IPv6 random query "
"port: %s",
isc_result_totext(result));
}
}
RES_LOCK(&res->poollock, isc_rwlocktype_write);
if (disp4 != NULL) {
dns_dispatch_detach(&res->dispatchv4pool[nxt]);
res->dispatchv4pool[nxt] = disp4;
}
if (disp6 != NULL) {
dns_dispatch_detach(&res->dispatchv6pool[nxt]);
res->dispatchv6pool[nxt] = disp6;
}
RES_UNLOCK(&res->poollock, isc_rwlocktype_write);
return;
}
isc_result_t
dns_resolver_createdispatchpool(dns_resolver_t *res, unsigned int ndisps,
unsigned int tick)
{
unsigned int i;
isc_result_t result = ISC_R_SUCCESS;
unsigned int attrs_base, attrs, attrmask;
isc_sockaddr_t addr4, addr6;
dns_dispatch_t *disp;
isc_task_t *task;
isc_interval_t interval;
REQUIRE(VALID_RESOLVER(res));
REQUIRE(!res->frozen); /* meaning we don't have to lock res */
REQUIRE(ndisps > 0);
REQUIRE((res->options & DNS_RESOLVER_USEDISPATCHPOOL4) != 0 ||
(res->options & DNS_RESOLVER_USEDISPATCHPOOL6) != 0);
attrs_base = 0;
attrs_base |= DNS_DISPATCHATTR_UDP;
attrs_base |= DNS_DISPATCHATTR_RANDOMPORT;
attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP;
attrmask |= DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4;
attrmask |= DNS_DISPATCHATTR_IPV6;
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL4) != 0) {
INSIST(res->dispatchv4 != NULL);
result = dns_dispatch_getlocaladdress(res->dispatchv4, &addr4);
INSIST(result == ISC_R_SUCCESS &&
isc_sockaddr_getport(&addr4) == 0);
res->dispatchv4pool = isc_mem_get(res->mctx,
sizeof(dns_dispatch_t *) *
ndisps);
if (res->dispatchv4pool == NULL)
return (ISC_R_NOMEMORY);
for (i = 0; i < ndisps; i++)
res->dispatchv4pool[i] = NULL;
}
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL6) != 0) {
INSIST(res->dispatchv6 != NULL);
result = dns_dispatch_getlocaladdress(res->dispatchv6, &addr6);
INSIST(result == ISC_R_SUCCESS &&
isc_sockaddr_getport(&addr6) == 0);
res->dispatchv6pool = isc_mem_get(res->mctx,
sizeof(dns_dispatch_t *) *
ndisps);
if (res->dispatchv6pool == NULL) {
isc_mem_put(res->mctx, res->dispatchv4pool,
sizeof(dns_dispatch_t *) * ndisps);
res->dispatchv4pool = NULL;
return (ISC_R_NOMEMORY);
}
for (i = 0; i < ndisps; i++)
res->dispatchv6pool[i] = NULL;
}
for (i = 0; i < ndisps; i++) {
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL4) != 0) {
attrs = attrs_base;
attrs |= DNS_DISPATCHATTR_IPV4;
disp = NULL;
result = dns_dispatch_getudp(res->dispatchmgr,
res->socketmgr,
res->taskmgr, &addr4,
4096, 1000, 32768, 16411,
16433, attrs, attrmask,
&disp);
if (result != ISC_R_SUCCESS)
goto cleanup;
res->dispatchv4pool[i] = disp;
/*
* It might be better to ensure all ports are
* different, but in practice it's probably okay to
* assume dns_dispatch_getudp() made reasonable
* choices.
*/
}
if ((res->options & DNS_RESOLVER_USEDISPATCHPOOL6) != 0) {
attrs = attrs_base;
attrs |= DNS_DISPATCHATTR_IPV6;
disp = NULL;
result = dns_dispatch_getudp(res->dispatchmgr,
res->socketmgr,
res->taskmgr, &addr6,
4096, 1000, 32768, 16411,
16433, attrs, attrmask,
&disp);
if (result != ISC_R_SUCCESS)
goto cleanup;
res->dispatchv6pool[i] = disp;
}
}
/* start update timer */
if (tick != 0) {
task = NULL;
result = isc_task_create(res->taskmgr, 0, &task);
if (result != ISC_R_SUCCESS)
goto cleanup;
isc_interval_set(&interval, tick, 0);
result = isc_timer_create(res->timermgr, isc_timertype_ticker,
NULL, &interval, task,
disppooltimer_update,
res, &res->disppooltimer);
isc_task_detach(&task);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
res->ndisps = ndisps;
res->nextdisp = 0;
return (result);
cleanup:
for (i = 0; i < ndisps; i++) {
if (res->dispatchv4pool[i] != NULL)
dns_dispatch_detach(&res->dispatchv4pool[i]);
if (res->dispatchv6pool[i] != NULL)
dns_dispatch_detach(&res->dispatchv6pool[i]);
}
if (res->dispatchv4pool != NULL) {
isc_mem_put(res->mctx, res->dispatchv4pool,
sizeof(dns_dispatch_t *) * ndisps);
}
if (res->dispatchv6pool != NULL) {
isc_mem_put(res->mctx, res->dispatchv6pool,
sizeof(dns_dispatch_t *) * ndisps);
}
return (result);
}

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: namedconf.c,v 1.72 2006/12/21 06:02:30 marka Exp $ */ /* $Id: namedconf.c,v 1.73 2007/02/02 02:18:06 marka Exp $ */
/*! \file */ /*! \file */
@@ -790,6 +790,9 @@ view_clauses[] = {
{ "empty-zones-enable", &cfg_type_boolean, 0 }, { "empty-zones-enable", &cfg_type_boolean, 0 },
{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI }, { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
{ "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 }, { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
{ "use-queryport-pool", &cfg_type_boolean, 0 },
{ "queryport-pool-ports", &cfg_type_uint32, 0 },
{ "queryport-pool-updateinterval", &cfg_type_uint32, 0 },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };