mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
2375. [security] Fully randomize UDP query ports to improve
forgery resilience. [RT #17949, #18098]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -24,7 +24,8 @@
|
||||
|
||||
2376. [bug] Change #2144 was not complete.
|
||||
|
||||
2375. [placeholder]
|
||||
2375. [security] Fully randomize UDP query ports to improve
|
||||
forgery resilience. [RT #17949, #18098]
|
||||
|
||||
2374. [bug] "blackhole" ACLs could cause named to segfault due
|
||||
to some uninitialized memory. [RT #18095]
|
||||
|
@@ -15,7 +15,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- $Id: bind9.xsl,v 1.17 2008/04/09 22:48:17 jinmei Exp $ -->
|
||||
<!-- $Id: bind9.xsl,v 1.18 2008/06/23 19:41:18 jinmei Exp $ -->
|
||||
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
@@ -86,7 +86,6 @@ td, th {
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">Bind 9 Configuration and Statistics</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<table>
|
||||
|
@@ -91,7 +91,6 @@ static char xslmsg[] =
|
||||
" </head>\n"
|
||||
" <body>\n"
|
||||
" <div class=\"header\">Bind 9 Configuration and Statistics</div>\n"
|
||||
"\n"
|
||||
" <br/>\n"
|
||||
"\n"
|
||||
" <table>\n"
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: client.c,v 1.257 2008/04/03 06:09:04 tbox Exp $ */
|
||||
/* $Id: client.c,v 1.258 2008/06/23 19:41:18 jinmei Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -1524,14 +1524,6 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
||||
dns_generalstats_increment(ns_g_server->nsstats,
|
||||
dns_nsstatscounter_tcp);
|
||||
|
||||
/*
|
||||
* Hash the incoming request here as it is after
|
||||
* dns_dispatch_importrecv().
|
||||
*/
|
||||
dns_dispatch_hash(&client->now, sizeof(client->now));
|
||||
dns_dispatch_hash(isc_buffer_base(buffer),
|
||||
isc_buffer_usedlength(buffer));
|
||||
|
||||
/*
|
||||
* It's a request. Parse it.
|
||||
*/
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.508 2008/05/21 23:47:00 tbox Exp $ */
|
||||
/* $Id: server.c,v 1.509 2008/06/23 19:41:18 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <isc/httpd.h>
|
||||
#include <isc/lex.h>
|
||||
#include <isc/parseint.h>
|
||||
#include <isc/portset.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/resource.h>
|
||||
#include <isc/stdio.h>
|
||||
@@ -538,13 +539,15 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver)
|
||||
*/
|
||||
static isc_result_t
|
||||
get_view_querysource_dispatch(const cfg_obj_t **maps,
|
||||
int af, dns_dispatch_t **dispatchp)
|
||||
int af, dns_dispatch_t **dispatchp,
|
||||
isc_boolean_t is_firstview)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_dispatch_t *disp;
|
||||
isc_sockaddr_t sa;
|
||||
unsigned int attrs, attrmask;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
unsigned int maxdispatchbuffers;
|
||||
|
||||
/*
|
||||
* Make compiler happy.
|
||||
@@ -596,6 +599,20 @@ get_view_querysource_dispatch(const cfg_obj_t **maps,
|
||||
attrs |= DNS_DISPATCHATTR_IPV6;
|
||||
break;
|
||||
}
|
||||
if (isc_sockaddr_getport(&sa) == 0) {
|
||||
attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
|
||||
maxdispatchbuffers = 4096;
|
||||
} else {
|
||||
INSIST(obj != NULL);
|
||||
if (is_firstview) {
|
||||
cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
|
||||
"using specific query-source port "
|
||||
"suppresses port randomization and can be "
|
||||
"insecure.");
|
||||
}
|
||||
maxdispatchbuffers = 1000;
|
||||
}
|
||||
|
||||
attrmask = 0;
|
||||
attrmask |= DNS_DISPATCHATTR_UDP;
|
||||
attrmask |= DNS_DISPATCHATTR_TCP;
|
||||
@@ -605,7 +622,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps,
|
||||
disp = NULL;
|
||||
result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
|
||||
ns_g_taskmgr, &sa, 4096,
|
||||
1000, 32768, 16411, 16433,
|
||||
maxdispatchbuffers, 32768, 16411, 16433,
|
||||
attrs, attrmask, &disp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_sockaddr_t any;
|
||||
@@ -1015,7 +1032,6 @@ 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;
|
||||
dns_stats_t *resstats = NULL;
|
||||
dns_stats_t *resquerystats = NULL;
|
||||
|
||||
@@ -1272,8 +1288,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
|
||||
*
|
||||
* XXXRTH Hardwired number of tasks.
|
||||
*/
|
||||
CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4));
|
||||
CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6));
|
||||
CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
|
||||
ISC_TF(ISC_LIST_PREV(view, link)
|
||||
== NULL)));
|
||||
CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
|
||||
ISC_TF(ISC_LIST_PREV(view, link)
|
||||
== NULL)));
|
||||
if (dispatch4 == NULL && dispatch6 == NULL) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"unable to obtain neither an IPv4 nor"
|
||||
@@ -1281,93 +1301,11 @@ 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,
|
||||
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));
|
||||
}
|
||||
|
||||
if (resstats == NULL) {
|
||||
CHECK(dns_generalstats_create(mctx, &resstats,
|
||||
dns_resstatscounter_max));
|
||||
@@ -2674,8 +2612,6 @@ 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)
|
||||
@@ -2683,19 +2619,16 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
|
||||
result = dns_dispatch_getlocaladdress(dispatch6, &addr);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto fail;
|
||||
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);
|
||||
|
||||
/*
|
||||
* We always add non-wildcard address regardless of whether
|
||||
* the port is 'any' (the fourth arg is TRUE): if the port is
|
||||
* specific, we need to add it since it may conflict with a
|
||||
* listening interface; if it's zero, we'll dynamically open
|
||||
* query ports, and some of them may override an existing
|
||||
* wildcard IPv6 port.
|
||||
*/
|
||||
result = add_listenelt(mctx, list, &addr, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
@@ -2884,24 +2817,41 @@ set_limits(const cfg_obj_t **maps) {
|
||||
SETLIMIT("files", openfiles, "open files");
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
portlist_fromconf(dns_portlist_t *portlist, unsigned int family,
|
||||
const cfg_obj_t *ports)
|
||||
static void
|
||||
portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
|
||||
isc_boolean_t positive)
|
||||
{
|
||||
const cfg_listelt_t *element;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
for (element = cfg_list_first(ports);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element)) {
|
||||
const cfg_obj_t *obj = cfg_listelt_value(element);
|
||||
in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
|
||||
|
||||
result = dns_portlist_add(portlist, family, port);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
if (cfg_obj_isuint32(obj)) {
|
||||
in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
|
||||
|
||||
if (positive)
|
||||
isc_portset_add(portset, port);
|
||||
else
|
||||
isc_portset_remove(portset, port);
|
||||
} else {
|
||||
const cfg_obj_t *obj_loport, *obj_hiport;
|
||||
in_port_t loport, hiport;
|
||||
|
||||
obj_loport = cfg_tuple_get(obj, "loport");
|
||||
loport = (in_port_t)cfg_obj_asuint32(obj_loport);
|
||||
obj_hiport = cfg_tuple_get(obj, "hiport");
|
||||
hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
|
||||
|
||||
if (positive)
|
||||
isc_portset_addrange(portset, loport, hiport);
|
||||
else {
|
||||
isc_portset_removerange(portset, loport,
|
||||
hiport);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@@ -2940,7 +2890,7 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
const cfg_obj_t *options;
|
||||
const cfg_obj_t *views;
|
||||
const cfg_obj_t *obj;
|
||||
const cfg_obj_t *v4ports, *v6ports;
|
||||
const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
|
||||
const cfg_obj_t *maps[3];
|
||||
const cfg_obj_t *builtin_views;
|
||||
const cfg_listelt_t *element;
|
||||
@@ -2952,7 +2902,9 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
isc_uint32_t interface_interval;
|
||||
isc_uint32_t heartbeat_interval;
|
||||
isc_uint32_t udpsize;
|
||||
in_port_t listen_port;
|
||||
in_port_t listen_port, udpport_low, udpport_high;
|
||||
isc_portset_t *v4portset = NULL;
|
||||
isc_portset_t *v6portset = NULL;
|
||||
int i;
|
||||
|
||||
cfg_aclconfctx_init(&aclconfctx);
|
||||
@@ -3069,24 +3021,64 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),
|
||||
"configuring statistics server(s)");
|
||||
|
||||
v4ports = NULL;
|
||||
v6ports = NULL;
|
||||
(void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports);
|
||||
(void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports);
|
||||
if (v4ports != NULL || v6ports != NULL) {
|
||||
dns_portlist_t *portlist = NULL;
|
||||
result = dns_portlist_create(ns_g_mctx, &portlist);
|
||||
if (result == ISC_R_SUCCESS && v4ports != NULL)
|
||||
result = portlist_fromconf(portlist, AF_INET, v4ports);
|
||||
if (result == ISC_R_SUCCESS && v6ports != NULL)
|
||||
portlist_fromconf(portlist, AF_INET6, v6ports);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist);
|
||||
if (portlist != NULL)
|
||||
dns_portlist_detach(&portlist);
|
||||
CHECK(result);
|
||||
} else
|
||||
dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL);
|
||||
/*
|
||||
* Configure sets of UDP query source ports.
|
||||
*/
|
||||
CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
|
||||
"creating UDP port set");
|
||||
CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
|
||||
"creating UDP port set");
|
||||
|
||||
usev4ports = NULL;
|
||||
usev6ports = NULL;
|
||||
avoidv4ports = NULL;
|
||||
avoidv6ports = NULL;
|
||||
|
||||
(void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
|
||||
if (usev4ports != NULL)
|
||||
portset_fromconf(v4portset, usev4ports, ISC_TRUE);
|
||||
else {
|
||||
CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
|
||||
&udpport_high),
|
||||
"get the default UDP/IPv4 port range");
|
||||
if (udpport_low == udpport_high)
|
||||
isc_portset_add(v4portset, udpport_low);
|
||||
else {
|
||||
isc_portset_addrange(v4portset, udpport_low,
|
||||
udpport_high);
|
||||
}
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"using default UDP/IPv4 port range: [%d, %d]",
|
||||
udpport_low, udpport_high);
|
||||
}
|
||||
(void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
|
||||
if (avoidv4ports != NULL)
|
||||
portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
|
||||
|
||||
(void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
|
||||
if (usev6ports != NULL)
|
||||
portset_fromconf(v6portset, usev6ports, ISC_TRUE);
|
||||
else {
|
||||
CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
|
||||
&udpport_high),
|
||||
"get the default UDP/IPv6 port range");
|
||||
if (udpport_low == udpport_high)
|
||||
isc_portset_add(v6portset, udpport_low);
|
||||
else {
|
||||
isc_portset_addrange(v6portset, udpport_low,
|
||||
udpport_high);
|
||||
}
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"using default UDP/IPv6 port range: [%d, %d]",
|
||||
udpport_low, udpport_high);
|
||||
}
|
||||
(void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
|
||||
if (avoidv6ports != NULL)
|
||||
portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
|
||||
|
||||
dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
|
||||
|
||||
/*
|
||||
* Set the EDNS UDP size when we don't match a view.
|
||||
@@ -3569,6 +3561,12 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (v4portset != NULL)
|
||||
isc_portset_destroy(ns_g_mctx, &v4portset);
|
||||
|
||||
if (v6portset != NULL)
|
||||
isc_portset_destroy(ns_g_mctx, &v6portset);
|
||||
|
||||
cfg_aclconfctx_destroy(&aclconfctx);
|
||||
|
||||
if (parser != NULL) {
|
||||
|
39
configure.in
39
configure.in
@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl
|
||||
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
|
||||
AC_DIVERT_POP()dnl
|
||||
|
||||
AC_REVISION($Revision: 1.443 $)
|
||||
AC_REVISION($Revision: 1.444 $)
|
||||
|
||||
AC_INIT(lib/dns/name.c)
|
||||
AC_PREREQ(2.59)
|
||||
@@ -317,6 +317,43 @@ lifconf.lifc_len = 0;
|
||||
ISC_PLATFORM_HAVELIFCONF="#undef ISC_PLATFORM_HAVELIFCONF"])
|
||||
AC_SUBST(ISC_PLATFORM_HAVELIFCONF)
|
||||
|
||||
#
|
||||
# check if we have kqueue
|
||||
#
|
||||
AC_CHECK_FUNC(kqueue, ac_cv_have_kqueue=yes, ac_cv_have_kqueue=no)
|
||||
case $ac_cv_have_kqueue in
|
||||
yes)
|
||||
ISC_PLATFORM_HAVEKQUEUE="#define ISC_PLATFORM_HAVEKQUEUE 1"
|
||||
;;
|
||||
*)
|
||||
ISC_PLATFORM_HAVEKQUEUE="#undef ISC_PLATFORM_HAVEKQUEUE"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(ISC_PLATFORM_HAVEKQUEUE)
|
||||
|
||||
#
|
||||
# check if we have epoll
|
||||
#
|
||||
AC_CHECK_FUNC(epoll_create, ac_cv_have_epoll=yes, ac_cv_have_epoll=no)
|
||||
case $ac_cv_have_epoll in
|
||||
yes)
|
||||
ISC_PLATFORM_HAVEEPOLL="#define ISC_PLATFORM_HAVEEPOLL 1"
|
||||
;;
|
||||
*)
|
||||
ISC_PLATFORM_HAVEEPOLL="#undef ISC_PLATFORM_HAVEEPOLL"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(ISC_PLATFORM_HAVEEPOLL)
|
||||
|
||||
#
|
||||
# check if we support /dev/poll
|
||||
#
|
||||
AC_CHECK_HEADERS(sys/devpoll.h,
|
||||
ISC_PLATFORM_HAVEDEVPOLL="#define ISC_PLATFORM_HAVEDEVPOLL 1"
|
||||
,
|
||||
ISC_PLATFORM_HAVEDEVPOLL="#undef ISC_PLATFORM_HAVEDEVPOLL"
|
||||
)
|
||||
AC_SUBST(ISC_PLATFORM_HAVEDEVPOLL)
|
||||
|
||||
#
|
||||
# check if we need to #include sys/select.h explicitly
|
||||
|
@@ -18,7 +18,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.359 2008/06/17 20:59:25 jreed Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.360 2008/06/23 19:41:18 jinmei Exp $ -->
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
||||
@@ -2955,6 +2955,33 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row rowsep="0">
|
||||
<entry colname="1">
|
||||
<para>
|
||||
<varname>port_list</varname>
|
||||
</para>
|
||||
</entry>
|
||||
<entry colname="2">
|
||||
<para>
|
||||
A list of an <varname>ip_port</varname> or a port
|
||||
range.
|
||||
A port range is specified in the form of
|
||||
<userinput>range</userinput> followed by
|
||||
two <varname>ip_port</varname>s,
|
||||
<varname>port_low</varname> and
|
||||
<varname>port_high</varname>, which represents
|
||||
port numbers from <varname>port_low</varname> through
|
||||
<varname>port_high</varname>, inclusive.
|
||||
<varname>port_low</varname> must not be larger than
|
||||
<varname>port_high</varname>.
|
||||
For example,
|
||||
<userinput>range 1024 65535</userinput> represents
|
||||
ports from 1024 through 65535.
|
||||
In either case an asterisk (`*') character is not
|
||||
allowed as a valid <varname>ip_port</varname>.
|
||||
</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row rowsep="0">
|
||||
<entry colname="1">
|
||||
<para>
|
||||
@@ -4513,7 +4540,9 @@ category notify { null; };
|
||||
<optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
|
||||
<optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
<optional> blackhole { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
<optional> use-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
|
||||
<optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
|
||||
<optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
|
||||
<optional> avoid-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
|
||||
<optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
<optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
@@ -6269,32 +6298,104 @@ listen-on-v6 port 1234 { !2001:db8::/32; any; };
|
||||
If <command>address</command> is <command>*</command> (asterisk) or is omitted,
|
||||
a wildcard IP address (<command>INADDR_ANY</command>)
|
||||
will be used.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If <command>port</command> is <command>*</command> or is omitted,
|
||||
a pool of random unprivileged ports will be used. See the
|
||||
<command>use-queryport-pool</command>,
|
||||
<command>queryport-pool-ports</command> and
|
||||
<command>queryport-pool-updateinterval</command> options below 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:
|
||||
a random port number from a pre-configured
|
||||
range is picked up and will be used for each query.
|
||||
The port range(s) is that specified in
|
||||
the <command>use-v4-udp-ports</command> (for IPv4)
|
||||
and <command>use-v6-udp-ports</command> (for IPv6)
|
||||
options, excluding the ranges specified in
|
||||
the <command>avoid-v4-udp-ports</command>
|
||||
and <command>avoid-v6-udp-ports</command> options, respectively.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The defaults of the <command>query-source</command> and
|
||||
<command>query-source-v6</command> options
|
||||
are:
|
||||
</para>
|
||||
|
||||
<programlisting>query-source address * port *;
|
||||
query-source-v6 address * port *;
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
If <command>use-v4-udp-ports</command> or
|
||||
<command>use-v6-udp-ports</command> is unspecified,
|
||||
<command>named</command> will check if the operating
|
||||
system provides a programming interface to retrieve the
|
||||
system's default range for ephemeral ports.
|
||||
If such an interface is available,
|
||||
<command>named</command> will use the corresponding system
|
||||
default range; otherwise, it will use its own defaults:
|
||||
</para>
|
||||
|
||||
<programlisting>use-v4-udp-ports { range 1024 65535; };
|
||||
use-v6-udp-ports { range 1024 65535; };
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Note: make sure the ranges be sufficiently large for
|
||||
security. A desirable size depends on various parameters,
|
||||
but we generally recommend it contain at least 16384 ports
|
||||
(14 bits of entropy).
|
||||
Note also that the system's default range when used may be
|
||||
too small for this purpose, and that the range may even be
|
||||
changed while <command>named</command> is running; the new
|
||||
range will automatically be applied when <command>named</command>
|
||||
is reloaded.
|
||||
It is encouraged to
|
||||
configure <command>use-v4-udp-ports</command> and
|
||||
<command>use-v6-udp-ports</command> explicitly so that the
|
||||
ranges are sufficiently large and are reasonably
|
||||
independent from the ranges used by other applications.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note: the operational configuration
|
||||
where <command>named</command> runs may prohibit the use
|
||||
of some ports. For example, UNIX systems will not allow
|
||||
<command>named</command> running without a root privilege
|
||||
to use ports less than 1024.
|
||||
If such ports are included in the specified (or detected)
|
||||
set of query ports, the corresponding query attempts will
|
||||
fail, resulting in resolution failures or delay.
|
||||
It is therefore important to configure the set of ports
|
||||
that can be safely used in the expected operational environment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The defaults of the <command>avoid-v4-udp-ports</command> and
|
||||
<command>avoid-v6-udp-ports</command> options
|
||||
are:
|
||||
</para>
|
||||
|
||||
<programlisting>avoid-v4-udp-ports {};
|
||||
avoid-v6-udp-ports {};
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Note: BIND 9.5.0 introduced
|
||||
the <command>use-queryport-pool</command>
|
||||
option to support a pool of such random ports, but this
|
||||
option is now obsolete because reusing the same ports in
|
||||
the pool may not be sufficiently secure.
|
||||
For the same reason, it is generally strongly discouraged to
|
||||
specify a particular port for the
|
||||
<command>query-source</command> or
|
||||
<command>query-source-v6</command> options;
|
||||
it implicitly disables the use of randomized port numbers.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>use-queryport-pool</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Enable the 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>.
|
||||
This option is obsolete.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -6303,7 +6404,7 @@ query-source-v6 address * port *;
|
||||
<term><command>queryport-pool-ports</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specify how many pool ports to use. The default is 8.
|
||||
This option is obsolete.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -6312,9 +6413,7 @@ query-source-v6 address * port *;
|
||||
<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.
|
||||
This option is obsolete.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -6664,17 +6763,48 @@ query-source-v6 address * port *;
|
||||
</sect3>
|
||||
|
||||
<sect3>
|
||||
<title>Bad UDP Port Lists</title>
|
||||
<para><command>avoid-v4-udp-ports</command>
|
||||
and <command>avoid-v6-udp-ports</command> specify a list
|
||||
of IPv4 and IPv6 UDP ports that will not be used as system
|
||||
assigned source ports for UDP sockets. These lists
|
||||
prevent named from choosing as its random source port a
|
||||
port that is blocked by your firewall. If a query went
|
||||
out with such a source port, the answer would not get by
|
||||
the firewall and the name server would have to query
|
||||
again.
|
||||
<title>UDP Port Lists</title>
|
||||
<para>
|
||||
<command>use-v4-udp-ports</command>,
|
||||
<command>avoid-v4-udp-ports</command>,
|
||||
<command>use-v6-udp-ports</command>, and
|
||||
<command>avoid-v6-udp-ports</command>
|
||||
specify a list of IPv4 and IPv6 UDP ports that will be
|
||||
used or not used as source ports for UDP messages.
|
||||
See <xref linkend="query_address"/> about how the
|
||||
available ports are determined.
|
||||
For example, with the following configuration
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
use-v6-udp-ports { range 32768 65535; };
|
||||
avoid-v6-udp-ports { 40000; range 50000 60000; };
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
UDP ports of IPv6 messages sent
|
||||
from <command>named</command> will be in one
|
||||
of the following ranges: 32768 to 39999, 40001 to 49999,
|
||||
and 60001 to 65535.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>avoid-v4-udp-ports</command> and
|
||||
<command>avoid-v6-udp-ports</command> can be used
|
||||
to prevent <command>named</command> from choosing as its random source port a
|
||||
port that is blocked by your firewall or a port that is
|
||||
used by other applications;
|
||||
if a query went out with a source port blocked by a
|
||||
firewall, the
|
||||
answer would not get by the firewall and the name server would
|
||||
have to query again.
|
||||
Note: the desired range can also be represented only with
|
||||
<command>use-v4-udp-ports</command> and
|
||||
<command>use-v6-udp-ports</command>, and the
|
||||
<command>avoid-</command> options are redundant in that
|
||||
sense; they are provided for backward compatibility and
|
||||
to possibly simplify the port specification.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3>
|
||||
|
1842
lib/dns/dispatch.c
1842
lib/dns/dispatch.c
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dispatch.h,v 1.58 2008/04/03 06:09:04 tbox Exp $ */
|
||||
/* $Id: dispatch.h,v 1.59 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#ifndef DNS_DISPATCH_H
|
||||
#define DNS_DISPATCH_H 1
|
||||
@@ -105,7 +105,7 @@ struct dns_dispatchevent {
|
||||
* The dispatcher is a TCP or UDP socket.
|
||||
*
|
||||
* _IPV4, _IPV6
|
||||
* The dispatcher uses an ipv4 or ipv6 socket.
|
||||
* The dispatcher uses an IPv4 or IPv6 socket.
|
||||
*
|
||||
* _NOLISTEN
|
||||
* The dispatcher should not listen on the socket.
|
||||
@@ -115,7 +115,12 @@ struct dns_dispatchevent {
|
||||
* accept replies from them.
|
||||
*
|
||||
* _RANDOMPORT
|
||||
* TBD
|
||||
* Previously used to indicate that the port of a dispatch UDP must be
|
||||
* chosen randomly. This behavior now always applies and the attribute
|
||||
* is obsoleted.
|
||||
*
|
||||
* _EXCLUSIVE
|
||||
* A separate socket will be used on-demand for each transaction.
|
||||
*/
|
||||
#define DNS_DISPATCHATTR_PRIVATE 0x00000001U
|
||||
#define DNS_DISPATCHATTR_TCP 0x00000002U
|
||||
@@ -125,7 +130,8 @@ struct dns_dispatchevent {
|
||||
#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U
|
||||
#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
|
||||
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
|
||||
#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U
|
||||
/*#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U*/
|
||||
#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U
|
||||
/*@}*/
|
||||
|
||||
isc_result_t
|
||||
@@ -189,23 +195,33 @@ void
|
||||
dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
|
||||
dns_portlist_t *portlist);
|
||||
/*%<
|
||||
* Sets a list of UDP ports that won't be used when creating a udp
|
||||
* dispatch with a wildcard port.
|
||||
* This function is deprecated. Use dns_dispatchmgr_setavailports() instead.
|
||||
*
|
||||
* Requires:
|
||||
*\li mgr is a valid dispatchmgr
|
||||
*\li portlist to be NULL or a valid port list.
|
||||
*/
|
||||
|
||||
dns_portlist_t *
|
||||
dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
|
||||
/*%<
|
||||
* Return the current port list.
|
||||
* This function is deprecated and always returns NULL.
|
||||
*
|
||||
* Requires:
|
||||
*\li mgr is a valid dispatchmgr
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
|
||||
isc_portset_t *v6portset);
|
||||
/*%<
|
||||
* Sets a list of UDP ports that can be used for outgoing UDP messages.
|
||||
*
|
||||
* Requires:
|
||||
*\li mgr is a valid dispatchmgr
|
||||
*\li v4portset is NULL or a valid port set
|
||||
*\li v6portset is NULL or a valid port set
|
||||
*/
|
||||
|
||||
void
|
||||
dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, dns_stats_t *stats);
|
||||
/*%<
|
||||
@@ -331,6 +347,12 @@ dns_dispatch_starttcp(dns_dispatch_t *disp);
|
||||
*\li 'disp' is valid.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
|
||||
isc_task_t *task, isc_taskaction_t action, void *arg,
|
||||
isc_uint16_t *idp, dns_dispentry_t **resp,
|
||||
isc_socketmgr_t *sockmgr);
|
||||
|
||||
isc_result_t
|
||||
dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
|
||||
isc_task_t *task, isc_taskaction_t action, void *arg,
|
||||
@@ -354,6 +376,10 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
|
||||
*
|
||||
*\li "resp" be non-NULL and *resp be NULL
|
||||
*
|
||||
*\li "sockmgr" be NULL or a valid socket manager. If 'disp' has
|
||||
* the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL,
|
||||
* which also means dns_dispatch_addresponse() cannot be used.
|
||||
*
|
||||
* Ensures:
|
||||
*
|
||||
*\li <id, dest> is a unique tuple. That means incoming messages
|
||||
@@ -384,6 +410,8 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
|
||||
* argument to dns_dispatch_addresponse() when allocating '*resp'.
|
||||
*/
|
||||
|
||||
isc_socket_t *
|
||||
dns_dispatch_getentrysocket(dns_dispentry_t *resp);
|
||||
|
||||
isc_socket_t *
|
||||
dns_dispatch_getsocket(dns_dispatch_t *disp);
|
||||
@@ -421,6 +449,16 @@ dns_dispatch_cancel(dns_dispatch_t *disp);
|
||||
*\li disp is valid.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
dns_dispatch_getattributes(dns_dispatch_t *disp);
|
||||
/*%<
|
||||
* Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the
|
||||
* non-changeable attributes are expected to be referenced by the caller.
|
||||
*
|
||||
* Requires:
|
||||
*\li disp is valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_dispatch_changeattributes(dns_dispatch_t *disp,
|
||||
unsigned int attributes, unsigned int mask);
|
||||
@@ -458,13 +496,6 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event);
|
||||
* event != NULL
|
||||
*/
|
||||
|
||||
void
|
||||
dns_dispatch_hash(void *data, size_t len);
|
||||
/*%<
|
||||
* Feed 'data' to the dispatch query id generator where 'len' is the size
|
||||
* of 'data'.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_DISPATCH_H */
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: resolver.h,v 1.58 2008/04/03 06:09:05 tbox Exp $ */
|
||||
/* $Id: resolver.h,v 1.59 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#ifndef DNS_RESOLVER_H
|
||||
#define DNS_RESOLVER_H 1
|
||||
@@ -107,8 +107,6 @@ 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,
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: request.c,v 1.79 2007/06/19 23:47:16 tbox Exp $ */
|
||||
/* $Id: request.c,v 1.80 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -121,6 +121,7 @@ static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
|
||||
static void req_senddone(isc_task_t *task, isc_event_t *event);
|
||||
static void req_response(isc_task_t *task, isc_event_t *event);
|
||||
static void req_timeout(isc_task_t *task, isc_event_t *event);
|
||||
static isc_socket_t * req_getsocket(dns_request_t *request);
|
||||
static void req_connected(isc_task_t *task, isc_event_t *event);
|
||||
static void req_sendevent(dns_request_t *request, isc_result_t result);
|
||||
static void req_cancel(dns_request_t *request);
|
||||
@@ -146,6 +147,7 @@ dns_requestmgr_create(isc_mem_t *mctx,
|
||||
isc_socket_t *socket;
|
||||
isc_result_t result;
|
||||
int i;
|
||||
unsigned int dispattr;
|
||||
|
||||
req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
|
||||
|
||||
@@ -154,13 +156,14 @@ dns_requestmgr_create(isc_mem_t *mctx,
|
||||
REQUIRE(socketmgr != NULL);
|
||||
REQUIRE(taskmgr != NULL);
|
||||
REQUIRE(dispatchmgr != NULL);
|
||||
UNUSED(socket);
|
||||
if (dispatchv4 != NULL) {
|
||||
socket = dns_dispatch_getsocket(dispatchv4);
|
||||
REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
|
||||
dispattr = dns_dispatch_getattributes(dispatchv4);
|
||||
REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
|
||||
}
|
||||
if (dispatchv6 != NULL) {
|
||||
socket = dns_dispatch_getsocket(dispatchv6);
|
||||
REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
|
||||
dispattr = dns_dispatch_getattributes(dispatchv6);
|
||||
REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
|
||||
}
|
||||
|
||||
requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
|
||||
@@ -425,12 +428,19 @@ req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
|
||||
isc_region_t r;
|
||||
isc_socket_t *socket;
|
||||
isc_result_t result;
|
||||
unsigned int dispattr;
|
||||
|
||||
req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
dispattr = dns_dispatch_getattributes(request->dispatch);
|
||||
socket = req_getsocket(request);
|
||||
isc_buffer_usedregion(request->query, &r);
|
||||
/*
|
||||
* We could connect the socket when we are using an exclusive dispatch
|
||||
* as we do in resolver.c, but we prefer implementation simplicity
|
||||
* at this moment.
|
||||
*/
|
||||
result = isc_socket_sendto(socket, &r, task, req_senddone,
|
||||
request, address, NULL);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
@@ -742,14 +752,16 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
INSIST(socket != NULL);
|
||||
result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
|
||||
req_response, request, &id,
|
||||
&request->dispentry);
|
||||
result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
|
||||
req_response, request, &id,
|
||||
&request->dispentry,
|
||||
requestmgr->socketmgr);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
socket = req_getsocket(request);
|
||||
INSIST(socket != NULL);
|
||||
|
||||
result = isc_buffer_allocate(mctx, &request->query,
|
||||
r.length + (tcp ? 2 : 0));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@@ -935,13 +947,14 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
INSIST(socket != NULL);
|
||||
result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
|
||||
req_response, request, &id,
|
||||
&request->dispentry);
|
||||
result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
|
||||
req_response, request, &id,
|
||||
&request->dispentry,
|
||||
requestmgr->socketmgr);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
socket = req_getsocket(request);
|
||||
INSIST(socket != NULL);
|
||||
|
||||
message->id = id;
|
||||
if (setkey) {
|
||||
@@ -1226,6 +1239,21 @@ dns_request_destroy(dns_request_t **requestp) {
|
||||
*** Private: request.
|
||||
***/
|
||||
|
||||
static isc_socket_t *
|
||||
req_getsocket(dns_request_t *request) {
|
||||
unsigned int dispattr;
|
||||
isc_socket_t *socket;
|
||||
|
||||
dispattr = dns_dispatch_getattributes(request->dispatch);
|
||||
if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
|
||||
INSIST(request->dispentry != NULL);
|
||||
socket = dns_dispatch_getentrysocket(request->dispentry);
|
||||
} else
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
|
||||
return (socket);
|
||||
}
|
||||
|
||||
static void
|
||||
req_connected(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
||||
@@ -1425,6 +1453,7 @@ req_destroy(dns_request_t *request) {
|
||||
static void
|
||||
req_cancel(dns_request_t *request) {
|
||||
isc_socket_t *socket;
|
||||
unsigned int dispattr;
|
||||
|
||||
REQUIRE(VALID_REQUEST(request));
|
||||
|
||||
@@ -1437,16 +1466,23 @@ req_cancel(dns_request_t *request) {
|
||||
|
||||
if (request->timer != NULL)
|
||||
isc_timer_detach(&request->timer);
|
||||
dispattr = dns_dispatch_getattributes(request->dispatch);
|
||||
socket = NULL;
|
||||
if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) {
|
||||
if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
|
||||
if (request->dispentry != NULL) {
|
||||
socket = dns_dispatch_getentrysocket(
|
||||
request->dispentry);
|
||||
}
|
||||
} else
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
if (DNS_REQUEST_CONNECTING(request) && socket != NULL)
|
||||
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
|
||||
if (DNS_REQUEST_SENDING(request) && socket != NULL)
|
||||
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
|
||||
}
|
||||
if (request->dispentry != NULL)
|
||||
dns_dispatch_removeresponse(&request->dispentry, NULL);
|
||||
if (DNS_REQUEST_CONNECTING(request)) {
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
|
||||
}
|
||||
if (DNS_REQUEST_SENDING(request)) {
|
||||
socket = dns_dispatch_getsocket(request->dispatch);
|
||||
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
|
||||
}
|
||||
dns_dispatch_detach(&request->dispatch);
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: resolver.c,v 1.372 2008/06/17 22:35:08 jinmei Exp $ */
|
||||
/* $Id: resolver.c,v 1.373 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -124,6 +124,7 @@ typedef struct query {
|
||||
isc_mem_t * mctx;
|
||||
dns_dispatchmgr_t * dispatchmgr;
|
||||
dns_dispatch_t * dispatch;
|
||||
isc_boolean_t exclusivesocket;
|
||||
dns_adbaddrinfo_t * addrinfo;
|
||||
isc_socket_t * tcpsocket;
|
||||
isc_time_t start;
|
||||
@@ -294,24 +295,6 @@ 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;
|
||||
@@ -319,11 +302,6 @@ struct dns_resolver {
|
||||
isc_mutex_t lock;
|
||||
isc_mutex_t nlock;
|
||||
isc_mutex_t primelock;
|
||||
#if DNS_RESOLVER_USERWLOCK
|
||||
isc_rwlock_t poollock;
|
||||
#else
|
||||
isc_mutex_t poollock;
|
||||
#endif
|
||||
dns_rdataclass_t rdclass;
|
||||
isc_socketmgr_t * socketmgr;
|
||||
isc_timermgr_t * timermgr;
|
||||
@@ -333,7 +311,9 @@ struct dns_resolver {
|
||||
unsigned int options;
|
||||
dns_dispatchmgr_t * dispatchmgr;
|
||||
dns_dispatch_t * dispatchv4;
|
||||
isc_boolean_t exclusivev4;
|
||||
dns_dispatch_t * dispatchv6;
|
||||
isc_boolean_t exclusivev6;
|
||||
unsigned int ndisps;
|
||||
unsigned int nbuckets;
|
||||
fctxbucket_t * buckets;
|
||||
@@ -352,7 +332,6 @@ struct dns_resolver {
|
||||
unsigned int spillatmin;
|
||||
isc_timer_t * spillattimer;
|
||||
isc_boolean_t zero_no_soa_ttl;
|
||||
isc_timer_t * disppooltimer;
|
||||
|
||||
/* Locked by lock. */
|
||||
unsigned int references;
|
||||
@@ -366,9 +345,6 @@ struct dns_resolver {
|
||||
dns_fetch_t * primefetch;
|
||||
/* Locked by nlock. */
|
||||
unsigned int nfctx;
|
||||
/* Locked by poollock. */
|
||||
dns_dispatch_t ** dispatchv4pool;
|
||||
dns_dispatch_t ** dispatchv6pool;
|
||||
};
|
||||
|
||||
#define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
|
||||
@@ -603,6 +579,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
|
||||
unsigned int factor;
|
||||
dns_adbfind_t *find;
|
||||
dns_adbaddrinfo_t *addrinfo;
|
||||
isc_socket_t *socket;
|
||||
|
||||
query = *queryp;
|
||||
fctx = query->fctx;
|
||||
@@ -684,6 +661,38 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
|
||||
0, factor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for any outstanding socket events. If they exist, cancel
|
||||
* them and let the event handlers finish the cleanup. The resolver
|
||||
* only needs to worry about managing the connect and send events;
|
||||
* the dispatcher manages the recv events.
|
||||
*/
|
||||
if (RESQUERY_CONNECTING(query)) {
|
||||
/*
|
||||
* Cancel the connect.
|
||||
*/
|
||||
if (query->tcpsocket != NULL) {
|
||||
isc_socket_cancel(query->tcpsocket, NULL,
|
||||
ISC_SOCKCANCEL_CONNECT);
|
||||
} else if (query->dispentry != NULL) {
|
||||
INSIST(query->exclusivesocket);
|
||||
socket = dns_dispatch_getentrysocket(query->dispentry);
|
||||
if (socket != NULL)
|
||||
isc_socket_cancel(socket, NULL,
|
||||
ISC_SOCKCANCEL_CONNECT);
|
||||
}
|
||||
} else if (RESQUERY_SENDING(query)) {
|
||||
/*
|
||||
* Cancel the pending send.
|
||||
*/
|
||||
if (query->exclusivesocket && query->dispentry != NULL)
|
||||
socket = dns_dispatch_getentrysocket(query->dispentry);
|
||||
else
|
||||
socket = dns_dispatch_getsocket(query->dispatch);
|
||||
if (socket != NULL)
|
||||
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
|
||||
}
|
||||
|
||||
if (query->dispentry != NULL)
|
||||
dns_dispatch_removeresponse(&query->dispentry, deventp);
|
||||
|
||||
@@ -695,25 +704,6 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
|
||||
if (query->tsigkey != NULL)
|
||||
dns_tsigkey_detach(&query->tsigkey);
|
||||
|
||||
/*
|
||||
* Check for any outstanding socket events. If they exist, cancel
|
||||
* them and let the event handlers finish the cleanup. The resolver
|
||||
* only needs to worry about managing the connect and send events;
|
||||
* the dispatcher manages the recv events.
|
||||
*/
|
||||
if (RESQUERY_CONNECTING(query))
|
||||
/*
|
||||
* Cancel the connect.
|
||||
*/
|
||||
isc_socket_cancel(query->tcpsocket, NULL,
|
||||
ISC_SOCKCANCEL_CONNECT);
|
||||
else if (RESQUERY_SENDING(query))
|
||||
/*
|
||||
* Cancel the pending send.
|
||||
*/
|
||||
isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
|
||||
NULL, ISC_SOCKCANCEL_SEND);
|
||||
|
||||
if (query->dispatch != NULL)
|
||||
dns_dispatch_detach(&query->dispatch);
|
||||
|
||||
@@ -912,43 +902,25 @@ fctx_done(fetchctx_t *fctx, isc_result_t result) {
|
||||
}
|
||||
|
||||
static void
|
||||
resquery_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
process_sendevent(resquery_t *query, isc_event_t *event) {
|
||||
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
||||
resquery_t *query = event->ev_arg;
|
||||
isc_boolean_t retry = ISC_FALSE;
|
||||
isc_result_t result;
|
||||
fetchctx_t *fctx;
|
||||
|
||||
REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
|
||||
|
||||
QTRACE("senddone");
|
||||
|
||||
/*
|
||||
* XXXRTH
|
||||
*
|
||||
* Currently we don't wait for the senddone event before retrying
|
||||
* a query. This means that if we get really behind, we may end
|
||||
* up doing extra work!
|
||||
*/
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
INSIST(RESQUERY_SENDING(query));
|
||||
|
||||
query->sends--;
|
||||
fctx = query->fctx;
|
||||
|
||||
if (RESQUERY_CANCELED(query)) {
|
||||
if (query->sends == 0) {
|
||||
if (query->sends == 0 && query->connects == 0) {
|
||||
/*
|
||||
* This query was canceled while the
|
||||
* isc_socket_sendto() was in progress.
|
||||
* isc_socket_sendto/connect() was in progress.
|
||||
*/
|
||||
if (query->tcpsocket != NULL)
|
||||
isc_socket_detach(&query->tcpsocket);
|
||||
resquery_destroy(&query);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
switch (sevent->result) {
|
||||
case ISC_R_SUCCESS:
|
||||
break;
|
||||
@@ -970,6 +942,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
@@ -987,6 +960,48 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
|
||||
resquery_t *query = event->ev_arg;
|
||||
|
||||
REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
|
||||
|
||||
QTRACE("udpconnected");
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
INSIST(RESQUERY_CONNECTING(query));
|
||||
|
||||
query->connects--;
|
||||
|
||||
process_sendevent(query, event);
|
||||
}
|
||||
|
||||
static void
|
||||
resquery_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
resquery_t *query = event->ev_arg;
|
||||
|
||||
REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
|
||||
|
||||
QTRACE("senddone");
|
||||
|
||||
/*
|
||||
* XXXRTH
|
||||
*
|
||||
* Currently we don't wait for the senddone event before retrying
|
||||
* a query. This means that if we get really behind, we may end
|
||||
* up doing extra work!
|
||||
*/
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
INSIST(RESQUERY_SENDING(query));
|
||||
|
||||
query->sends--;
|
||||
|
||||
process_sendevent(query, event);
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
fctx_addopt(dns_message_t *message, unsigned int version,
|
||||
isc_uint16_t udpsize, isc_boolean_t request_nsid)
|
||||
@@ -1139,6 +1154,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
*/
|
||||
query->dispatchmgr = res->dispatchmgr;
|
||||
query->dispatch = NULL;
|
||||
query->exclusivesocket = ISC_FALSE;
|
||||
query->tcpsocket = NULL;
|
||||
if (res->view->peers != NULL) {
|
||||
dns_peer_t *peer = NULL;
|
||||
@@ -1221,39 +1237,16 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_query;
|
||||
} 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)) {
|
||||
case PF_INET:
|
||||
if (res->dispatchv4pool != NULL) {
|
||||
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);
|
||||
}
|
||||
dns_dispatch_attach(res->dispatchv4,
|
||||
&query->dispatch);
|
||||
query->exclusivesocket = res->exclusivev4;
|
||||
break;
|
||||
case PF_INET6:
|
||||
if (res->dispatchv6pool != NULL) {
|
||||
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);
|
||||
}
|
||||
dns_dispatch_attach(res->dispatchv6,
|
||||
&query->dispatch);
|
||||
query->exclusivesocket = res->exclusivev6;
|
||||
break;
|
||||
default:
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
@@ -1449,13 +1442,14 @@ resquery_send(resquery_t *query) {
|
||||
/*
|
||||
* Get a query id from the dispatch.
|
||||
*/
|
||||
result = dns_dispatch_addresponse(query->dispatch,
|
||||
&query->addrinfo->sockaddr,
|
||||
task,
|
||||
resquery_response,
|
||||
query,
|
||||
&query->id,
|
||||
&query->dispentry);
|
||||
result = dns_dispatch_addresponse2(query->dispatch,
|
||||
&query->addrinfo->sockaddr,
|
||||
task,
|
||||
resquery_response,
|
||||
query,
|
||||
&query->id,
|
||||
&query->dispentry,
|
||||
res->socketmgr);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_temps;
|
||||
|
||||
@@ -1672,12 +1666,24 @@ resquery_send(resquery_t *query) {
|
||||
*/
|
||||
dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
|
||||
|
||||
socket = dns_dispatch_getsocket(query->dispatch);
|
||||
if (query->exclusivesocket)
|
||||
socket = dns_dispatch_getentrysocket(query->dispentry);
|
||||
else
|
||||
socket = dns_dispatch_getsocket(query->dispatch);
|
||||
/*
|
||||
* Send the query!
|
||||
*/
|
||||
if ((query->options & DNS_FETCHOPT_TCP) == 0)
|
||||
if ((query->options & DNS_FETCHOPT_TCP) == 0) {
|
||||
address = &query->addrinfo->sockaddr;
|
||||
if (query->exclusivesocket) {
|
||||
result = isc_socket_connect(socket, address, task,
|
||||
resquery_udpconnected,
|
||||
query);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_message;
|
||||
query->connects++;
|
||||
}
|
||||
}
|
||||
isc_buffer_usedregion(buffer, &r);
|
||||
|
||||
/*
|
||||
@@ -2779,6 +2785,8 @@ fctx_destroy(fetchctx_t *fctx) {
|
||||
static void
|
||||
fctx_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
fetchctx_t *fctx = event->ev_arg;
|
||||
isc_timerevent_t *tevent = (isc_timerevent_t *)event;
|
||||
resquery_t *query;
|
||||
|
||||
REQUIRE(VALID_FCTX(fctx));
|
||||
|
||||
@@ -2794,8 +2802,18 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
fctx->timeouts++;
|
||||
/*
|
||||
* We could cancel the running queries here, or we could let
|
||||
* them keep going. Right now we choose the latter...
|
||||
* them keep going. Since we normally use separate sockets for
|
||||
* different queries, we adopt the former approach to reduce
|
||||
* the number of open sockets: cancel the oldest query if it
|
||||
* expired before the query had started (this is usually the
|
||||
* case but is not always so, depending on the task schedule
|
||||
* timing).
|
||||
*/
|
||||
query = ISC_LIST_HEAD(fctx->queries);
|
||||
if (query != NULL &&
|
||||
isc_time_compare(&tevent->due, &query->start) >= 0) {
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
|
||||
}
|
||||
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
|
||||
/*
|
||||
* Our timer has triggered. Reestablish the fctx lifetime
|
||||
@@ -5659,6 +5677,19 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
* There's no hope for this query.
|
||||
*/
|
||||
keep_trying = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* If this is a network error on an exclusive query
|
||||
* socket, mark the server as bad so that we won't try
|
||||
* it for this fetch again.
|
||||
*/
|
||||
if (query->exclusivesocket &&
|
||||
(devent->result == ISC_R_HOSTUNREACH ||
|
||||
devent->result == ISC_R_NETUNREACH ||
|
||||
devent->result == ISC_R_CONNREFUSED ||
|
||||
devent->result == ISC_R_CANCELED)) {
|
||||
broken_server = devent->result;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
@@ -6262,7 +6293,6 @@ destroy(dns_resolver_t *res) {
|
||||
|
||||
INSIST(res->nfctx == 0);
|
||||
|
||||
RES_DESTROYLOCK(&res->poollock);
|
||||
DESTROYLOCK(&res->primelock);
|
||||
DESTROYLOCK(&res->nlock);
|
||||
DESTROYLOCK(&res->lock);
|
||||
@@ -6279,26 +6309,12 @@ destroy(dns_resolver_t *res) {
|
||||
dns_dispatch_detach(&res->dispatchv4);
|
||||
if (res->dispatchv6 != NULL)
|
||||
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) {
|
||||
ISC_LIST_UNLINK(res->alternates, a, link);
|
||||
if (!a->isaddress)
|
||||
dns_name_free(&a->_u._n.name, res->mctx);
|
||||
isc_mem_put(res->mctx, a, sizeof(*a));
|
||||
}
|
||||
if (res->disppooltimer != NULL)
|
||||
isc_timer_detach(&res->disppooltimer);
|
||||
dns_resolver_reset_algorithms(res);
|
||||
dns_resolver_resetmustbesecure(res);
|
||||
#if USE_ALGLOCK
|
||||
@@ -6395,6 +6411,7 @@ dns_resolver_create(dns_view_t *view,
|
||||
unsigned int i, buckets_created = 0;
|
||||
isc_task_t *task = NULL;
|
||||
char name[16];
|
||||
unsigned dispattr;
|
||||
|
||||
/*
|
||||
* Create a resolver.
|
||||
@@ -6429,9 +6446,6 @@ dns_resolver_create(dns_view_t *view,
|
||||
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->activebuckets = ntasks;
|
||||
res->buckets = isc_mem_get(view->mctx,
|
||||
@@ -6475,12 +6489,20 @@ dns_resolver_create(dns_view_t *view,
|
||||
}
|
||||
|
||||
res->dispatchv4 = NULL;
|
||||
if (dispatchv4 != NULL)
|
||||
dns_dispatch_attach(dispatchv4, &res->dispatchv4);
|
||||
if (dispatchv4 != NULL) {
|
||||
dns_dispatch_attach(dispatchv4, &res->dispatchv4);
|
||||
dispattr = dns_dispatch_getattributes(dispatchv4);
|
||||
res->exclusivev4 =
|
||||
ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
|
||||
}
|
||||
|
||||
res->dispatchv6 = NULL;
|
||||
if (dispatchv6 != NULL)
|
||||
if (dispatchv6 != NULL) {
|
||||
dns_dispatch_attach(dispatchv6, &res->dispatchv6);
|
||||
dispattr = dns_dispatch_getattributes(dispatchv6);
|
||||
res->exclusivev6 =
|
||||
ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
|
||||
}
|
||||
|
||||
res->references = 1;
|
||||
res->exiting = ISC_FALSE;
|
||||
@@ -6502,21 +6524,17 @@ dns_resolver_create(dns_view_t *view,
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_nlock;
|
||||
|
||||
result = RES_INITLOCK(&res->poollock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_primelock;
|
||||
|
||||
task = NULL;
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_poollock;
|
||||
goto cleanup_primelock;
|
||||
|
||||
result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
|
||||
task, spillattimer_countdown, res,
|
||||
&res->spillattimer);
|
||||
isc_task_detach(&task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_poollock;
|
||||
goto cleanup_primelock;
|
||||
|
||||
#if USE_ALGLOCK
|
||||
result = isc_rwlock_init(&res->alglock, 0, 0);
|
||||
@@ -6546,9 +6564,6 @@ dns_resolver_create(dns_view_t *view,
|
||||
isc_timer_detach(&res->spillattimer);
|
||||
#endif
|
||||
|
||||
cleanup_poollock:
|
||||
RES_DESTROYLOCK(&res->poollock);
|
||||
|
||||
cleanup_primelock:
|
||||
DESTROYLOCK(&res->primelock);
|
||||
|
||||
@@ -6770,12 +6785,12 @@ dns_resolver_shutdown(dns_resolver_t *res) {
|
||||
fctx != NULL;
|
||||
fctx = ISC_LIST_NEXT(fctx, link))
|
||||
fctx_shutdown(fctx);
|
||||
if (res->dispatchv4 != NULL) {
|
||||
if (res->dispatchv4 != NULL && !res->exclusivev4) {
|
||||
sock = dns_dispatch_getsocket(res->dispatchv4);
|
||||
isc_socket_cancel(sock, res->buckets[i].task,
|
||||
ISC_SOCKCANCEL_ALL);
|
||||
}
|
||||
if (res->dispatchv6 != NULL) {
|
||||
if (res->dispatchv6 != NULL && !res->exclusivev6) {
|
||||
sock = dns_dispatch_getsocket(res->dispatchv6);
|
||||
isc_socket_cancel(sock, res->buckets[i].task,
|
||||
ISC_SOCKCANCEL_ALL);
|
||||
@@ -7459,245 +7474,3 @@ dns_resolver_getoptions(dns_resolver_t *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 = NULL, *disp6 = NULL;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
if (res->dispatchv4pool != NULL) {
|
||||
for (i = 0; i < ndisps; i++)
|
||||
if (res->dispatchv4pool[i] != NULL)
|
||||
dns_dispatch_detach(&res->dispatchv4pool[i]);
|
||||
isc_mem_put(res->mctx, res->dispatchv4pool,
|
||||
sizeof(dns_dispatch_t *) * ndisps);
|
||||
}
|
||||
if (res->dispatchv6pool != NULL) {
|
||||
for (i = 0; i < ndisps; i++)
|
||||
if (res->dispatchv6pool[i] != NULL)
|
||||
dns_dispatch_detach(&res->dispatchv6pool[i]);
|
||||
isc_mem_put(res->mctx, res->dispatchv6pool,
|
||||
sizeof(dns_dispatch_t *) * ndisps);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.93 2007/09/14 03:39:29 marka Exp $
|
||||
# $Id: Makefile.in,v 1.94 2008/06/23 19:41:19 jinmei Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -58,7 +58,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
|
||||
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
||||
md5.@O@ mem.@O@ mutexblock.@O@ \
|
||||
netaddr.@O@ netscope.@O@ ondestroy.@O@ \
|
||||
parseint.@O@ quota.@O@ radix.@O@ random.@O@ \
|
||||
parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \
|
||||
ratelimiter.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \
|
||||
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ \
|
||||
string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
|
||||
@@ -73,7 +73,7 @@ SRCS = @ISC_EXTRA_SRCS@ \
|
||||
lex.c lfsr.c lib.c log.c \
|
||||
md5.c mem.c mutexblock.c \
|
||||
netaddr.c netscope.c ondestroy.c \
|
||||
parseint.c quota.c radix.c random.c \
|
||||
parseint.c portset.c quota.c radix.c random.c \
|
||||
ratelimiter.c refcount.c region.c result.c rwlock.c \
|
||||
serial.c sha1.c sha2.c sockaddr.c string.c strtoul.c \
|
||||
symtab.c task.c taskpool.c timer.c version.c
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: platform.h.in,v 1.47 2008/01/24 23:47:00 tbox Exp $ */
|
||||
/* $Id: platform.h.in,v 1.48 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#ifndef ISC_PLATFORM_H
|
||||
#define ISC_PLATFORM_H 1
|
||||
@@ -136,6 +136,21 @@
|
||||
*/
|
||||
@ISC_PLATFORM_FIXIN6ISADDR@
|
||||
|
||||
/*! \brief
|
||||
* Define if the system supports kqueue multiplexing
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEKQUEUE@
|
||||
|
||||
/*! \brief
|
||||
* Define if the system supports epoll multiplexing
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEEPOLL@
|
||||
|
||||
/*! \brief
|
||||
* Define if the system supports /dev/poll multiplexing
|
||||
*/
|
||||
@ISC_PLATFORM_HAVEDEVPOLL@
|
||||
|
||||
/*
|
||||
*** Printing.
|
||||
***/
|
||||
|
141
lib/isc/include/isc/portset.h
Normal file
141
lib/isc/include/isc/portset.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: portset.h,v 1.2 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
/*! \file isc/portset.h
|
||||
* \brief Transport Protocol Port Manipuration Module
|
||||
*
|
||||
* This module provides simple utilities to handle a set of transport protocol
|
||||
* (UDP or TCP) port numbers, e.g., for creating an ACL list. An isc_portset_t
|
||||
* object is an opaque instance of a port set, for which the user can add or
|
||||
* remove a specific port or a range of consecutive ports. This object is
|
||||
* expected to be used as a temporary work space only, and does not protect
|
||||
* simultaneous access from multiple threads. Therefore it must not be stored
|
||||
* in a place that can be accessed from multiple threads.
|
||||
*/
|
||||
|
||||
#ifndef ISC_PORTSET_H
|
||||
#define ISC_PORTSET_H 1
|
||||
|
||||
/***
|
||||
*** Imports
|
||||
***/
|
||||
|
||||
#include <isc/net.h>
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
isc_result_t
|
||||
isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp);
|
||||
/*%<
|
||||
* Create a port set and initialize it as an empty set.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'mctx' to be valid.
|
||||
*\li 'portsetp' to be non NULL and '*portsetp' to be NULL;
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #ISC_R_NOMEMORY
|
||||
*/
|
||||
|
||||
void
|
||||
isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp);
|
||||
/*%<
|
||||
* Destroy a port set.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'mctx' to be valid and must be the same context given when the port set
|
||||
* was created.
|
||||
*\li '*portsetp' to be a valid set.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
isc_portset_isset(isc_portset_t *portset, in_port_t port);
|
||||
/*%<
|
||||
* Test whether the given port is stored in the portset.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'portset' to be a valid set.
|
||||
*
|
||||
* Returns
|
||||
* \li #ISC_TRUE if the port is found, ISC_FALSE otherwise.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
isc_portset_nports(isc_portset_t *portset);
|
||||
/*%<
|
||||
* Provides the number of ports stored in the given portset.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'portset' to be a valid set.
|
||||
*
|
||||
* Returns
|
||||
* \li the number of ports stored in portset.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_portset_add(isc_portset_t *portset, in_port_t port);
|
||||
/*%<
|
||||
* Add the given port to the portset. The port may or may not be stored in
|
||||
* the portset.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'portlist' to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_portset_remove(isc_portset_t *portset, in_port_t port);
|
||||
/*%<
|
||||
* Remove the given port to the portset. The port may or may not be stored in
|
||||
* the portset.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'portlist' to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
|
||||
in_port_t port_hi);
|
||||
/*%<
|
||||
* Add a subset of [port_lo, port_hi] (inclusive) to the portset. Ports in the
|
||||
* subset may or may not be stored in portset.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'portlist' to be valid.
|
||||
*\li port_lo <= port_hi
|
||||
*/
|
||||
|
||||
void
|
||||
isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
|
||||
in_port_t port_hi);
|
||||
/*%<
|
||||
* Subtract a subset of [port_lo, port_hi] (inclusive) from the portset. Ports
|
||||
* in the subset may or may not be stored in portset.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'portlist' to be valid.
|
||||
*\li port_lo <= port_hi
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISC_NETADDR_H */
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket.h,v 1.74 2008/06/04 23:47:11 tbox Exp $ */
|
||||
/* $Id: socket.h,v 1.75 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#ifndef ISC_SOCKET_H
|
||||
#define ISC_SOCKET_H 1
|
||||
@@ -360,6 +360,45 @@ isc_socket_detach(isc_socket_t **socketp);
|
||||
* All resources used by the socket have been freed
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_open(isc_socket_t *sock);
|
||||
/*%<
|
||||
* Open a new socket file descriptor of the given socket structure. It simply
|
||||
* opens a new descriptor; all of the other parameters including the socket
|
||||
* type are inherited from the existing socket. This function is provided to
|
||||
* avoid overhead of destroying and creating sockets when many short-lived
|
||||
* sockets are frequently opened and closed. When the efficiency is not an
|
||||
* issue, it should be safer to detach the unused socket and re-create a new
|
||||
* one.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li there must be no other reference to this socket.
|
||||
*
|
||||
* \li 'socket' is a valid and previously closed by isc_socket_close()
|
||||
*
|
||||
* Returns:
|
||||
* Same as isc_socket_create().
|
||||
*/
|
||||
|
||||
void
|
||||
isc_socket_close(isc_socket_t *sock);
|
||||
/*%<
|
||||
* Close a socket file descriptor of the given socket structure. This function
|
||||
* is provided as an alternative to destroying an unused socket when overhead
|
||||
* destroying/re-creating sockets can be significant, and is expected to be
|
||||
* used with isc_socket_open().
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
* \li The socket must have a valid descriptor.
|
||||
*
|
||||
* \li There must be no other reference to this socket.
|
||||
*
|
||||
* \li There must be no pending I/O requests.
|
||||
*
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp);
|
||||
/*%<
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: timer.h,v 1.38 2007/06/19 23:47:18 tbox Exp $ */
|
||||
/* $Id: timer.h,v 1.39 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#ifndef ISC_TIMER_H
|
||||
#define ISC_TIMER_H 1
|
||||
@@ -76,6 +76,7 @@
|
||||
#include <isc/event.h>
|
||||
#include <isc/eventclass.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/time.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
@@ -93,6 +94,7 @@ typedef enum {
|
||||
|
||||
typedef struct isc_timerevent {
|
||||
struct isc_event common;
|
||||
isc_time_t due;
|
||||
} isc_timerevent_t;
|
||||
|
||||
#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0)
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: types.h,v 1.45 2008/01/17 23:47:00 tbox Exp $ */
|
||||
/* $Id: types.h,v 1.46 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#ifndef ISC_TYPES_H
|
||||
#define ISC_TYPES_H 1
|
||||
@@ -70,6 +70,7 @@ typedef struct isc_mempool isc_mempool_t; /*%< Memory Pool */
|
||||
typedef struct isc_msgcat isc_msgcat_t; /*%< Message Catalog */
|
||||
typedef struct isc_ondestroy isc_ondestroy_t; /*%< On Destroy */
|
||||
typedef struct isc_netaddr isc_netaddr_t; /*%< Net Address */
|
||||
typedef struct isc_portset isc_portset_t; /*%< Port Set */
|
||||
typedef struct isc_quota isc_quota_t; /*%< Quota */
|
||||
typedef struct isc_random isc_random_t; /*%< Random */
|
||||
typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */
|
||||
|
140
lib/isc/portset.c
Normal file
140
lib/isc/portset.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: portset.c,v 1.2 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
#include <isc/mem.h>
|
||||
#include <isc/portset.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#define ISC_PORTSET_BUFSIZE (65536 / (sizeof(isc_uint32_t) * 8))
|
||||
|
||||
/*%
|
||||
* Internal representation of portset. It's an array of 32-bit integers, each
|
||||
* bit corresponding to a single port in the ascending order. For example,
|
||||
* the second most significant bit of buf[0] corresponds to port 1.
|
||||
*/
|
||||
struct isc_portset {
|
||||
unsigned int nports; /*%< number of ports in the set */
|
||||
isc_uint32_t buf[ISC_PORTSET_BUFSIZE];
|
||||
};
|
||||
|
||||
static inline isc_boolean_t
|
||||
portset_isset(isc_portset_t *portset, in_port_t port) {
|
||||
return (ISC_TF((portset->buf[port >> 5] & (1 << (port & 31))) != 0));
|
||||
}
|
||||
|
||||
static inline void
|
||||
portset_add(isc_portset_t *portset, in_port_t port) {
|
||||
if (!portset_isset(portset, port)) {
|
||||
portset->nports++;
|
||||
portset->buf[port >> 5] |= (1 << (port & 31));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
portset_remove(isc_portset_t *portset, in_port_t port) {
|
||||
if (portset_isset(portset, port)) {
|
||||
portset->nports--;
|
||||
portset->buf[port >> 5] &= ~(1 << (port & 31));
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) {
|
||||
isc_portset_t *portset;
|
||||
|
||||
REQUIRE(portsetp != NULL && *portsetp == NULL);
|
||||
|
||||
portset = isc_mem_get(mctx, sizeof(*portset));
|
||||
if (portset == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
/* Make the set 'empty' by default */
|
||||
memset(portset, 0, sizeof(*portset));
|
||||
*portsetp = portset;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) {
|
||||
isc_portset_t *portset;
|
||||
|
||||
REQUIRE(portsetp != NULL);
|
||||
portset = *portsetp;
|
||||
|
||||
isc_mem_put(mctx, portset, sizeof(*portset));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
isc_portset_isset(isc_portset_t *portset, in_port_t port) {
|
||||
REQUIRE(portset != NULL);
|
||||
|
||||
return (portset_isset(portset, port));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_portset_nports(isc_portset_t *portset) {
|
||||
REQUIRE(portset != NULL);
|
||||
|
||||
return (portset->nports);
|
||||
}
|
||||
|
||||
void
|
||||
isc_portset_add(isc_portset_t *portset, in_port_t port) {
|
||||
REQUIRE(portset != NULL);
|
||||
|
||||
portset_add(portset, port);
|
||||
}
|
||||
|
||||
void
|
||||
isc_portset_remove(isc_portset_t *portset, in_port_t port) {
|
||||
portset_remove(portset, port);
|
||||
}
|
||||
|
||||
void
|
||||
isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
|
||||
in_port_t port_hi)
|
||||
{
|
||||
in_port_t p;
|
||||
|
||||
REQUIRE(portset != NULL);
|
||||
REQUIRE(port_lo <= port_hi);
|
||||
|
||||
p = port_lo;
|
||||
do {
|
||||
portset_add(portset, p);
|
||||
} while (p++ < port_hi);
|
||||
}
|
||||
|
||||
void
|
||||
isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
|
||||
in_port_t port_hi)
|
||||
{
|
||||
in_port_t p;
|
||||
|
||||
REQUIRE(portset != NULL);
|
||||
REQUIRE(port_lo <= port_hi);
|
||||
|
||||
p = port_lo;
|
||||
do {
|
||||
portset_remove(portset, p);
|
||||
} while (p++ < port_hi);
|
||||
}
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: timer.c,v 1.81 2007/10/24 00:57:23 marka Exp $ */
|
||||
/* $Id: timer.c,v 1.82 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -577,7 +577,7 @@ isc_timer_detach(isc_timer_t **timerp) {
|
||||
static void
|
||||
dispatch(isc_timermgr_t *manager, isc_time_t *now) {
|
||||
isc_boolean_t done = ISC_FALSE, post_event, need_schedule;
|
||||
isc_event_t *event;
|
||||
isc_timerevent_t *event;
|
||||
isc_eventtype_t type = 0;
|
||||
isc_timer_t *timer;
|
||||
isc_result_t result;
|
||||
@@ -650,16 +650,18 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) {
|
||||
/*
|
||||
* XXX We could preallocate this event.
|
||||
*/
|
||||
event = isc_event_allocate(manager->mctx,
|
||||
event = (isc_timerevent_t *)isc_event_allocate(manager->mctx,
|
||||
timer,
|
||||
type,
|
||||
timer->action,
|
||||
timer->arg,
|
||||
sizeof(*event));
|
||||
|
||||
if (event != NULL)
|
||||
isc_task_send(timer->task, &event);
|
||||
else
|
||||
if (event != NULL) {
|
||||
event->due = timer->due;
|
||||
isc_task_send(timer->task,
|
||||
(isc_event_t **)&event);
|
||||
} else
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
isc_msgcat_get(isc_msgcat,
|
||||
ISC_MSGSET_TIMER,
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: app.c,v 1.57 2008/01/18 23:46:58 tbox Exp $ */
|
||||
/* $Id: app.c,v 1.58 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_EPOLL
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
#include <isc/app.h>
|
||||
#include <isc/boolean.h>
|
||||
@@ -303,8 +306,7 @@ evloop() {
|
||||
int n;
|
||||
isc_time_t when, now;
|
||||
struct timeval tv, *tvp;
|
||||
fd_set readfds, writefds;
|
||||
int maxfd;
|
||||
isc_socketwait_t *swait;
|
||||
isc_boolean_t readytasks;
|
||||
isc_boolean_t call_timer_dispatch = ISC_FALSE;
|
||||
|
||||
@@ -331,8 +333,8 @@ evloop() {
|
||||
}
|
||||
}
|
||||
|
||||
isc__socketmgr_getfdsets(&readfds, &writefds, &maxfd);
|
||||
n = select(maxfd, &readfds, &writefds, NULL, tvp);
|
||||
swait = NULL;
|
||||
n = isc__socketmgr_waitevents(tvp, &swait);
|
||||
|
||||
if (n == 0 || call_timer_dispatch) {
|
||||
/*
|
||||
@@ -352,8 +354,7 @@ evloop() {
|
||||
isc__timermgr_dispatch();
|
||||
}
|
||||
if (n > 0)
|
||||
(void)isc__socketmgr_dispatch(&readfds, &writefds,
|
||||
maxfd);
|
||||
(void)isc__socketmgr_dispatch(swait);
|
||||
(void)isc__taskmgr_dispatch();
|
||||
|
||||
if (want_reload) {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: net.h,v 1.46 2007/06/19 23:47:19 tbox Exp $ */
|
||||
/* $Id: net.h,v 1.47 2008/06/23 19:41:20 jinmei Exp $ */
|
||||
|
||||
#ifndef ISC_NET_H
|
||||
#define ISC_NET_H 1
|
||||
@@ -324,6 +324,23 @@ isc_net_probeunix(void);
|
||||
* Returns whether UNIX domain sockets are supported.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
|
||||
/*%<
|
||||
* Returns system's default range of ephemeral UDP ports, if defined.
|
||||
* If the range is not available or unknown, ISC_NET_PORTRANGELOW and
|
||||
* ISC_NET_PORTRANGEHIGH will be returned.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'low' and 'high' must be non NULL.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li *low and *high will be the ports specifying the low and high ends of
|
||||
* the range.
|
||||
*/
|
||||
|
||||
#ifdef ISC_PLATFORM_NEEDNTOP
|
||||
const char *
|
||||
isc_net_ntop(int af, const void *src, char *dst, size_t size);
|
||||
|
@@ -15,10 +15,13 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: net.c,v 1.36 2007/09/13 04:45:18 each Exp $ */
|
||||
/* $Id: net.c,v 1.37 2008/06/23 19:41:19 jinmei Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -30,6 +33,50 @@
|
||||
#include <isc/string.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
/*%
|
||||
* Definitions about UDP port range specification. This is a total mess of
|
||||
* portability variants: some use sysctl (but the sysctl names vary), some use
|
||||
* system-specific interfaces, some have the same interface for IPv4 and IPv6,
|
||||
* some separate them, etc...
|
||||
*/
|
||||
|
||||
/*%
|
||||
* The last resort defaults: use all non well known port space
|
||||
*/
|
||||
#ifndef ISC_NET_PORTRANGELOW
|
||||
#define ISC_NET_PORTRANGELOW 1024
|
||||
#endif /* ISC_NET_PORTRANGELOW */
|
||||
#ifndef ISC_NET_PORTRANGEHIGH
|
||||
#define ISC_NET_PORTRANGEHIGH 65535
|
||||
#endif /* ISC_NET_PORTRANGEHIGH */
|
||||
|
||||
/*%
|
||||
* sysctl variants
|
||||
*/
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#define USE_SYSCTL_PORTRANGE
|
||||
#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portrange.first"
|
||||
#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portrange.last"
|
||||
#define SYSCTL_V6PORTRANGE_LOW "net.inet.ip.portrange.first"
|
||||
#define SYSCTL_V6PORTRANGE_HIGH "net.inet.ip.portrange.last"
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define USE_SYSCTL_PORTRANGE
|
||||
#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.anonportmin"
|
||||
#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.anonportmax"
|
||||
#define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.portrange.first"
|
||||
#define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.portrange.last"
|
||||
#endif
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define USE_SYSCTL_PORTRANGE
|
||||
#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portfirst"
|
||||
#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portlast"
|
||||
#define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.portrange.first"
|
||||
#define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.portrange.last"
|
||||
#endif
|
||||
|
||||
#if defined(ISC_PLATFORM_HAVEIPV6)
|
||||
# if defined(ISC_PLATFORM_NEEDIN6ADDRANY)
|
||||
const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
|
||||
@@ -338,6 +385,60 @@ isc_net_probe_ipv6pktinfo(void) {
|
||||
return (ipv6pktinfo_result);
|
||||
}
|
||||
|
||||
#ifdef USE_SYSCTL_PORTRANGE
|
||||
static isc_result_t
|
||||
getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
|
||||
int port_low, port_high;
|
||||
size_t portlen;
|
||||
const char *sysctlname_lowport, *sysctlname_hiport;
|
||||
|
||||
if (af == AF_INET) {
|
||||
sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW;
|
||||
sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH;
|
||||
} else {
|
||||
sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW;
|
||||
sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH;
|
||||
}
|
||||
portlen = sizeof(portlen);
|
||||
if (sysctlbyname(sysctlname_lowport, &port_low, &portlen,
|
||||
NULL, 0) < 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
portlen = sizeof(portlen);
|
||||
if (sysctlbyname(sysctlname_hiport, &port_high, &portlen,
|
||||
NULL, 0) < 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
|
||||
return (ISC_R_RANGE);
|
||||
|
||||
*low = (in_port_t)port_low;
|
||||
*high = (in_port_t)port_high;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
isc_result_t
|
||||
isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
|
||||
int result = ISC_R_FAILURE;
|
||||
|
||||
REQUIRE(low != NULL && high != NULL);
|
||||
|
||||
#ifdef USE_SYSCTL_PORTRANGE
|
||||
result = getudpportrange_sysctl(af, low, high);
|
||||
#else
|
||||
UNUSED(af);
|
||||
#endif
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
*low = ISC_NET_PORTRANGELOW;
|
||||
*high = ISC_NET_PORTRANGEHIGH;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS); /* we currently never fail in this function */
|
||||
}
|
||||
|
||||
void
|
||||
isc_net_disableipv4(void) {
|
||||
initialize();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket_p.h,v 1.11 2007/06/19 23:47:18 tbox Exp $ */
|
||||
/* $Id: socket_p.h,v 1.12 2008/06/23 19:41:20 jinmei Exp $ */
|
||||
|
||||
#ifndef ISC_SOCKET_P_H
|
||||
#define ISC_SOCKET_P_H
|
||||
@@ -26,10 +26,7 @@
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
isc__socketmgr_getfdsets(fd_set *readset, fd_set *writeset, int *maxfd);
|
||||
|
||||
isc_result_t
|
||||
isc__socketmgr_dispatch(fd_set *readset, fd_set *writeset, int maxfd);
|
||||
|
||||
typedef struct isc_socketwait isc_socketwait_t;
|
||||
int isc__socketmgr_waitevents(struct timeval *, isc_socketwait_t **);
|
||||
isc_result_t isc__socketmgr_dispatch(isc_socketwait_t *);
|
||||
#endif /* ISC_SOCKET_P_H */
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: namedconf.c,v 1.87 2008/04/03 02:01:08 marka Exp $ */
|
||||
/* $Id: namedconf.c,v 1.88 2008/06/23 19:41:20 jinmei Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -547,11 +547,19 @@ static cfg_type_t cfg_type_serverid = {
|
||||
/*%
|
||||
* Port list.
|
||||
*/
|
||||
static isc_result_t
|
||||
parse_port(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
static cfg_tuplefielddef_t porttuple_fields[] = {
|
||||
{ "loport", &cfg_type_uint32, 0 },
|
||||
{ "hiport", &cfg_type_uint32, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_porttuple = {
|
||||
"porttuple", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
|
||||
&cfg_rep_tuple, porttuple_fields
|
||||
};
|
||||
|
||||
UNUSED(type);
|
||||
static isc_result_t
|
||||
parse_port(cfg_parser_t *pctx, cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
|
||||
CHECK(cfg_parse_uint32(pctx, NULL, ret));
|
||||
if ((*ret)->value.uint32 > 0xffff) {
|
||||
@@ -559,18 +567,60 @@ parse_port(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
cfg_obj_destroy(pctx, ret);
|
||||
result = ISC_R_RANGE;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return (result);
|
||||
}
|
||||
|
||||
static cfg_type_t cfg_type_port = {
|
||||
"port", parse_port, NULL, cfg_doc_terminal,
|
||||
static isc_result_t
|
||||
parse_portrange(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
|
||||
isc_result_t result;
|
||||
cfg_obj_t *obj = NULL;
|
||||
|
||||
UNUSED(type);
|
||||
|
||||
CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
|
||||
if (pctx->token.type == isc_tokentype_number)
|
||||
CHECK(parse_port(pctx, ret));
|
||||
else {
|
||||
CHECK(cfg_gettoken(pctx, 0));
|
||||
if (pctx->token.type != isc_tokentype_string ||
|
||||
strcasecmp(TOKEN_STRING(pctx), "range") != 0) {
|
||||
cfg_parser_error(pctx, CFG_LOG_NEAR,
|
||||
"expected integer or 'range'");
|
||||
return (ISC_R_UNEXPECTEDTOKEN);
|
||||
}
|
||||
CHECK(cfg_create_tuple(pctx, &cfg_type_porttuple, &obj));
|
||||
CHECK(parse_port(pctx, &obj->value.tuple[0]));
|
||||
CHECK(parse_port(pctx, &obj->value.tuple[1]));
|
||||
if (obj->value.tuple[0]->value.uint32 >
|
||||
obj->value.tuple[1]->value.uint32) {
|
||||
cfg_parser_error(pctx, CFG_LOG_NOPREP,
|
||||
"low port '%u' must not be larger "
|
||||
"than high port",
|
||||
obj->value.tuple[0]->value.uint32);
|
||||
result = ISC_R_RANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
*ret = obj;
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (obj != NULL)
|
||||
cfg_obj_destroy(pctx, &obj);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static cfg_type_t cfg_type_portrange = {
|
||||
"portrange", parse_portrange, NULL, cfg_doc_terminal,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_bracketed_portlist = {
|
||||
"bracketed_sockaddrlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
|
||||
&cfg_rep_list, &cfg_type_port
|
||||
"bracketed_sockaddrlist", cfg_parse_bracketed_list,
|
||||
cfg_print_bracketed_list, cfg_doc_bracketed_list,
|
||||
&cfg_rep_list, &cfg_type_portrange
|
||||
};
|
||||
|
||||
/*%
|
||||
@@ -611,6 +661,8 @@ namedconf_or_view_clauses[] = {
|
||||
*/
|
||||
static cfg_clausedef_t
|
||||
options_clauses[] = {
|
||||
{ "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
|
||||
{ "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
|
||||
{ "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
|
||||
{ "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
|
||||
{ "blackhole", &cfg_type_bracketed_aml, 0 },
|
||||
@@ -782,8 +834,9 @@ view_clauses[] = {
|
||||
*/
|
||||
{ "query-source", &cfg_type_querysource4, 0 },
|
||||
{ "query-source-v6", &cfg_type_querysource6, 0 },
|
||||
{ "queryport-pool-ports", &cfg_type_uint32, 0 },
|
||||
{ "queryport-pool-updateinterval", &cfg_type_uint32, 0 },
|
||||
{ "queryport-pool-ports", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
|
||||
{ "queryport-pool-updateinterval", &cfg_type_uint32,
|
||||
CFG_CLAUSEFLAG_OBSOLETE },
|
||||
{ "recursion", &cfg_type_boolean, 0 },
|
||||
{ "request-ixfr", &cfg_type_boolean, 0 },
|
||||
{ "request-nsid", &cfg_type_boolean, 0 },
|
||||
@@ -794,7 +847,7 @@ view_clauses[] = {
|
||||
{ "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
|
||||
{ "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
|
||||
{ "transfer-format", &cfg_type_transferformat, 0 },
|
||||
{ "use-queryport-pool", &cfg_type_boolean, 0 },
|
||||
{ "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
|
||||
{ "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
Reference in New Issue
Block a user