Commit 281bab0f authored by Mark Andrews's avatar Mark Andrews

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]
parent 1f369c25
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]
2127. [port] Improved OpenSSL 0.9.8 support. [RT #16563]
......
......@@ -15,7 +15,7 @@
* 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 */
......@@ -802,7 +802,9 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
(void)dns_acl_match(&listen_netaddr,
NULL, ele->acl,
NULL, &match, NULL);
if (match > 0 && ele->port == le->port)
if (match > 0 &&
(ele->port == le->port ||
ele->port == 0))
break;
else
match = 0;
......
......@@ -17,7 +17,7 @@
- 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>
<refentryinfo>
<date>Aug 13, 2004</date>
......@@ -235,6 +235,9 @@ options {
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-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>;
min-roots <replaceable>integer</replaceable>; // not implemented
lame-ttl <replaceable>integer</replaceable>;
......@@ -384,6 +387,9 @@ view <replaceable>string</replaceable> <replaceable>optional_class</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-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>;
min-roots <replaceable>integer</replaceable>; // not implemented
lame-ttl <replaceable>integer</replaceable>;
......
......@@ -15,7 +15,7 @@
* 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 */
......@@ -953,7 +953,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
const char *str;
dns_order_t *order = NULL;
isc_uint32_t udpsize;
unsigned int check = 0;
unsigned int resopts = 0;
dns_zone_t *zone = NULL;
isc_uint32_t max_clients_per_query;
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 empty_zones_enable;
const cfg_obj_t *disablelist = NULL;
isc_uint32_t nqports, qports_updateinterval;
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);
if (strcasecmp(str, "fail") == 0) {
check = DNS_RESOLVER_CHECKNAMES |
resopts |= DNS_RESOLVER_CHECKNAMES |
DNS_RESOLVER_CHECKNAMESFAIL;
view->checknames = ISC_TRUE;
} else if (strcasecmp(str, "warn") == 0) {
check = DNS_RESOLVER_CHECKNAMES;
resopts |= DNS_RESOLVER_CHECKNAMES;
view->checknames = ISC_FALSE;
} else if (strcasecmp(str, "ignore") == 0) {
check = 0;
view->checknames = ISC_FALSE;
} else
INSIST(0);
......@@ -1210,11 +1210,93 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
result = ISC_R_UNEXPECTED;
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,
ns_g_socketmgr, ns_g_timermgr,
check, ns_g_dispatchmgr,
resopts, ns_g_dispatchmgr,
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.
*/
......@@ -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);
INSIST(result == ISC_R_SUCCESS);
dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj));
/*
* 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
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;
dns_acl_t *src_acl = NULL;
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);
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.negative = ISC_FALSE;
aelt.u.ip_prefix.prefixlen = 128;
......@@ -2438,6 +2523,8 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
dns_dispatch_t *dispatch6;
isc_boolean_t use_portpool = ISC_FALSE;
unsigned int resopts;
dispatch6 = dns_resolver_dispatchv6(view->resolver);
if (dispatch6 == NULL)
......@@ -2445,7 +2532,19 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
result = dns_dispatch_getlocaladdress(dispatch6, &addr);
if (result != ISC_R_SUCCESS)
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)
goto fail;
}
......@@ -2475,12 +2574,12 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
continue;
addrp = dns_zone_getnotifysrc6(zone);
result = add_listenelt(mctx, list, addrp);
result = add_listenelt(mctx, list, addrp, ISC_FALSE);
if (result != ISC_R_SUCCESS)
goto fail;
addrp = dns_zone_getxfrsource6(zone);
result = add_listenelt(mctx, list, addrp);
result = add_listenelt(mctx, list, addrp, ISC_FALSE);
if (result != ISC_R_SUCCESS)
goto fail;
}
......
......@@ -18,7 +18,7 @@
- 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">
<title>BIND 9 Administrator Reference Manual</title>
......@@ -4443,6 +4443,9 @@ category notify { null; };
<optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> |
<optional> address ( <replaceable>ip6_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>
<optional> max-transfer-time-in <replaceable>number</replaceable>; </optional>
<optional> max-transfer-time-out <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>
</sect3>
<sect3>
<sect3 id="query_address">
<title>Query Address</title>
<para>
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>)
will be used.
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
to prevent named
from selecting certain ports. The defaults are:
from selecting certain ports.
The defaults are:
</para>
<programlisting>query-source address * port *;
query-source-v6 address * port *;
</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>
<para>
The address specified in the <command>query-source</command> option
is used for both UDP and TCP queries, but the port applies only
to
UDP queries. TCP queries always use a random
to UDP queries. TCP queries always use a random
unprivileged port.
</para>
</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-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>
</sect2>
......
......@@ -15,7 +15,7 @@
* 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 */
......@@ -282,6 +282,20 @@ reseed_lfsr(isc_lfsr_t *lfsr, void *arg)
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.
*/
......@@ -1290,20 +1304,26 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
}
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_result_t result;
REQUIRE(sock != NULL || sockaddrp != NULL);
if (mgr->portlist == NULL)
return (ISC_FALSE);
result = isc_socket_getsockname(sock, &sockaddr);
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
if (sock != NULL) {
sockaddrp = &sockaddr;
result = isc_socket_getsockname(sock, sockaddrp);
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
}
if (mgr->portlist != NULL &&
dns_portlist_match(mgr->portlist, isc_sockaddr_pf(&sockaddr),
isc_sockaddr_getport(&sockaddr)))
if (dns_portlist_match(mgr->portlist, isc_sockaddr_pf(sockaddrp),
isc_sockaddr_getport(sockaddrp)))
return (ISC_TRUE);
return (ISC_FALSE);
}
......@@ -1324,7 +1344,7 @@ local_addr_match(dns_dispatch_t *disp, isc_sockaddr_t *addr) {
if (disp->mgr->portlist != NULL &&
isc_sockaddr_getport(addr) == 0 &&
isc_sockaddr_getport(&disp->local) == 0 &&
blacklisted(disp->mgr, disp->socket))
blacklisted(disp->mgr, disp->socket, NULL))
return (ISC_FALSE);
/*
......@@ -1669,7 +1689,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
dns_dispatch_t **dispp)
{
isc_result_t result;
dns_dispatch_t *disp;
dns_dispatch_t *disp = NULL;
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(sockmgr != NULL);
......@@ -1689,10 +1709,14 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
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);
if (result == ISC_R_SUCCESS) {
disp->refcount++;
......@@ -1717,6 +1741,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
return (ISC_R_SUCCESS);
}
createudp:
/*
* Nope, create one.
*/
......@@ -1752,7 +1777,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
dns_dispatch_t *disp;
isc_socket_t *sock = NULL;
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.
......@@ -1768,11 +1794,30 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
* from returning the same port to us too quickly.
*/
memset(held, 0, sizeof(held));
localaddr_bound = *localaddr;
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)
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)
isc_socket_detach(&held[i]);
held[i++] = sock;
......
......@@ -15,7 +15,7 @@
* 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
#define DNS_DISPATCH_H 1
......@@ -113,6 +113,9 @@ struct dns_dispatchevent {
* _MAKEQUERY
* The dispatcher can be used to issue queries to other servers, and
* accept replies from them.
*
* _RANDOMPORT
* TBD
*/
#define DNS_DISPATCHATTR_PRIVATE 0x00000001U
#define DNS_DISPATCHATTR_TCP 0x00000002U
......@@ -122,6 +125,7 @@ struct dns_dispatchevent {
#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U
#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U
/*@}*/
isc_result_t
......
......@@ -15,7 +15,7 @@
* 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
#define DNS_RESOLVER_H 1
......@@ -106,6 +106,8 @@ typedef struct dns_fetchevent {
#define DNS_RESOLVER_CHECKNAMES 0x01
#define DNS_RESOLVER_CHECKNAMESFAIL 0x02
#define DNS_RESOLVER_USEDISPATCHPOOL4 0x04
#define DNS_RESOLVER_USEDISPATCHPOOL6 0x08
isc_result_t
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
* should instead call dns_view_createresolver().
*
*\li No options are currently defined.
*
* Requires:
*
*\li 'view' is a valid view.
......@@ -474,6 +474,36 @@ dns_resolver_getzeronosoattl(dns_resolver_t *resolver);
void
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
#endif /* DNS_RESOLVER_H */
......@@ -15,7 +15,7 @@
* 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 */
......@@ -23,6 +23,7 @@
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>
......@@ -290,13 +291,36 @@ typedef struct alternate {
ISC_LINK(struct alternate) link;
} 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 {
/* Unlocked. */
unsigned int magic;
isc_mem_t * mctx;
isc_mutex_t lock;
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;