Compare commits

...
Author SHA1 Message Date
Witold Kręcicki 578a98e6e6 Create named_g_cpus network threads 2018-11-13 19:03:44 +00:00
Evan HuntandWitold Kręcicki bafc47bef5 style: one-line statement braces, line length, etc 2018-11-13 19:03:44 +00:00
Witold Kręcicki cdf097ea32 CHANGES and release notes 2018-11-13 19:03:43 +00:00
Witold Krecicki ef5cc6f9d6 FreeBSD fixes - proper affinity setting, don't use SO_REUSEPORT 2018-11-13 19:03:10 +00:00
Witold Krecicki d00d2dddb3 Don't doublelock fdlock on Solaris 2018-11-13 19:03:10 +00:00
Witold Kręcicki 3fabca3fe8 Synchronize Windows socket code with API changes. 2018-11-13 19:03:10 +00:00
Witold Kręcicki 7089e9cca4 Fix fetchlimit test to allow softquota to be overruled; Remove 'verifying that named checks for conflicting listeners' test from runtime 2018-11-13 19:03:10 +00:00
Witold Kręcicki c4780de0d4 Use multiple worker queues (using isc_task_sendto()) in unix socket code 2018-11-13 19:03:09 +00:00
Witold Kręcicki 9ec889940d use REUSEPORT only for NOLISTEN dispatchers 2018-11-13 19:02:36 +00:00
Witold Kręcicki 08a2d2d37a Make watching/unwatching sockets saner. 2018-11-13 19:02:36 +00:00
Witold Kręcicki 97b9d76f52 Use the newly accepted FD in TCP code. 2018-11-13 19:02:36 +00:00
Witold Kręcicki ea54888e2e Use isc_refcount_t in socket reference counting. 2018-11-13 19:02:36 +00:00
Witold Krecicki ce6f33ed0b Multiple network event loop threads support for Solarises /dev/poll. 2018-11-13 19:02:36 +00:00
Witold Kręcicki 901794f009 Mangle fdlocks a bit.
Mutexes are slower if they're in the same cache line. Since
fd's come in herds, and usually our listen sockets will have nearby
fd numbers, we mangle fdlocks so that the locks are further away.
2018-11-13 19:02:36 +00:00
Witold Kręcicki e478ec16f9 Fix a race between socket closing and incoming event. 2018-11-13 19:02:36 +00:00
Witold Kręcicki d15ba6eaba Set network threads CPU affintity. 2018-11-13 19:02:36 +00:00
Witold Kręcicki cde60b3085 Add runtime detection of SO_REUSEPORT, use it instead of dup() if available. 2018-11-13 19:02:36 +00:00
Witold Kręcicki 4256a29ea9 Use the same number of UDP dispatchers as CPUs. 2018-11-13 19:02:36 +00:00
Witold Krecicki 4b8bdca210 Use multiple network event loop threads with separate data structures. 2018-11-13 19:02:36 +00:00
Witold Kręcicki 1f0cffd16f Do IO after event directly in the network thread, don't queue an event in a separate task. 2018-11-13 19:02:36 +00:00
Witold Kręcicki fd36cafe5a Remove fdwatch sockets, those are not used anywhere. 2018-11-13 19:02:35 +00:00
Witold Kręcicki 5b3798661a Fix a typo in lib/isc/unix/thread.c 2018-11-13 19:02:04 +00:00
Witold Krecicki deae248984 Add some DBC checks in dighost; fix race between clear_query and send_done in dighost 2018-11-13 19:02:04 +00:00
Witold Kręcicki 74fc261ee3 CHANGES note 2018-11-13 19:02:04 +00:00
Witold Kręcicki 6cc85c208f Use larger quantum for network tasks 2018-11-13 19:02:04 +00:00
Witold Kręcicki 3ebc29b82b Use a single wake_all_queues() function to wake all queues 2018-11-13 19:02:04 +00:00
Witold Kręcicki 757b9a5351 Switch from privileged to un-privileged mode under lock 2018-11-13 19:02:04 +00:00
Witold Kręcicki 586ab26d51 Document isc_task_sendto properly, make sure that cpu we're sending to is always sane 2018-11-13 19:02:04 +00:00
Witold Kręcicki 5418603967 Use proper memory ordering for tasks_running/tasks_ready 2018-11-13 19:02:04 +00:00
Witold Kręcicki 8ece19f681 Comment about taskmgr exclusive mode, fix a REQUIRE. 2018-11-13 19:02:04 +00:00
Witold Kręcicki de667d3c08 Allow slight over-quota in'checking lame server clients are dropped at the soft limit' test 2018-11-13 19:02:04 +00:00
Witold Kręcicki 8e45de0f6f Saner exclusive task handling in taskmgr 2018-11-13 19:02:04 +00:00
Witold Kręcicki dec92aeab6 Formatting 2018-11-13 19:02:04 +00:00
Witold Kręcicki 8ddc2b0225 Get rid of isc_taskmgr_setmode, we only use it to set privileged mode 2018-11-13 19:02:04 +00:00
Witold Kręcicki 7f423f0175 Make sure all priority tasks are done before entering normal execution 2018-11-13 19:02:04 +00:00
Witold Kręcicki dccbc4086e Post shutting down tasks always to manager 0 2018-11-13 19:02:04 +00:00
Witold Kręcicki d5a3200b3d Separate structure for each thread/queue; 2-phase-locking for exclusive tasks 2018-11-13 19:02:04 +00:00
Witold Kręcicki 70f46a537a Always restart dispatchers on empty readyq 2018-11-13 19:02:04 +00:00
Witold Kręcicki 5f269f9572 Taskmgr shutdown fixes 2018-11-13 19:02:04 +00:00
Witold Kręcicki 30708dff65 Multiple worker queues 2018-11-13 19:02:04 +00:00
Witold Krecicki ff3f537167 isc_thread_setaffinity() 2018-11-13 19:02:04 +00:00
Evan HuntandWitold Kręcicki 6b70909322 CHANGES, release note 2018-11-13 19:02:04 +00:00
Tony FinchandWitold Kręcicki 4bbd2bb511 Fixes for rndc nta user interface
Tell the user explicitly about their mistakes:

* Unknown options, e.g. -list instead of -dump
  or -delete instead of -remove.

* Unknown view names.

* Excess arguments.

Include the view name in `rndc nta -dump` output, for consistency with
the NTA add and remove actions.

When removing an NTA from all views, do not abort with an error if the
NTA was not found in one of the views.
2018-11-13 19:02:04 +00:00
Ondřej SurýandWitold Kręcicki e3c37cef51 Add CHANGES entry for GL #653 2018-11-13 19:02:04 +00:00
Ondřej SurýandWitold Kręcicki 9925d4e1ad Add release notes for IDN processing update 2018-11-13 19:02:04 +00:00
Ondřej SurýandWitold Kręcicki 94c6914e72 Update the IDN documentation for nslookup 2018-11-13 19:02:04 +00:00
Ondřej SurýandWitold Kręcicki ccc614d702 Change the dig documentation 2018-11-13 19:02:04 +00:00
Ondřej SurýandWitold Kręcicki 1eadb37cf3 Update the idna tests for the new non-tty defaults 2018-11-13 19:02:04 +00:00
Ondřej SurýandWitold Kręcicki 5d2639df6d Enable IDN processing (both idnin and idnout) only on tty, disable it when the stdout is not a tty 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 154f411370 require python to be explicitly disabled 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 7d94e47c26 add CHANGES note 2018-11-13 19:02:04 +00:00
Tony FinchandWitold Kręcicki ebe69ba220 Abolish ip6.int support in dig and mdig 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 52174dc8bc add CHANGES note 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 6a172b3621 test require-server-cookie with rate-limit 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 9da63b9874 check requireservercookie even if rrl is configured 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 7b30e010b7 two dns_name_dup calls were not checked 2018-11-13 19:02:04 +00:00
Witold Kręcicki d375baa081 dighost.c: after invalidating buffer we need to reinit it 2018-11-13 19:02:04 +00:00
Witold Kręcicki 5b699987eb Cleanup fctx->finds before sending 'final' query after qname minimization.
At the beginning of qname minimization we get fctx->finds filled with what's
in the cache at this point, in worst case root servers. After doing full
run querying for NSes at different levels we need to clean it and refill
it with proper values from cache.
2018-11-13 19:02:04 +00:00
Evan HuntandWitold Kręcicki 1802f71ed1 disable QNAME minimization in the dnstap test so packet counts will be correct 2018-11-13 19:02:04 +00:00
Witold Kręcicki 5343db271d Avoid a race in qmin test 2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 8e31665541 regen 2018-11-13 19:02:04 +00:00
Tony FinchandWitold Kręcicki d95e2af91c Correctly report backtrace support when configure finishes 2018-11-13 19:02:04 +00:00
Michał KępieńandWitold Kręcicki 2dc79549a4 Check serve-stale behavior with a cold cache
Ensure that serve-stale works as expected when returning stale answers
is enabled, the authoritative server does not respond, and there is no
cached answer available.
2018-11-13 19:02:04 +00:00
Michał KępieńandWitold Kręcicki 5c34e1006d Check TTL of stale answers
Make sure that stale answers returned when the serve-stale feature is
enabled have a TTL matching the value of the stale-answer-ttl setting.
2018-11-13 19:02:04 +00:00
Michał KępieńandWitold Kręcicki 4aae4ac05f [squash] Rework code preparing a HTTP response for sending in lib/isc/httpd.c 2018-11-13 19:02:04 +00:00
Witold Kręcicki 1911a71fd5 CHANGES entry 2018-11-13 19:02:04 +00:00
Witold Kręcicki 3d58be4c15 Remove vector socket functions from Unix socket code and library headers
Remove the following functions in order to simplify socket code:

  - isc_socket_recvv()
  - isc_socket_sendtov()
  - isc_socket_sendtov2()
  - isc_socket_sendv()
2018-11-13 19:02:04 +00:00
Witold Kręcicki a4ec819b3f Remove vector socket functions from Windows socket code
Remove the following functions in order to simplify socket code:

  - isc_socket_recvv()
  - isc_socket_sendtov()
  - isc_socket_sendtov2()
  - isc_socket_sendv()
2018-11-13 19:02:04 +00:00
Witold Kręcicki 2f1f4f49b7 Do not use vector socket functions in diagnostic tools
Refactor diagnostic tools code to no longer use:

  - isc_socket_recvv()
  - isc_socket_sendtov2()
  - isc_socket_sendv()

as these functions will be removed shortly.
2018-11-13 19:02:04 +00:00
Witold Kręcicki 0fa04a2f0a Do not use vector socket functions in HTTP server code
Refactor code in lib/isc/httpd.c to no longer use isc_socket_sendv() as
this function will be removed shortly.
2018-11-13 19:02:04 +00:00
Mark AndrewsandWitold Kręcicki 7db8344162 use new packet for response; rename variable to request and response 2018-11-13 19:02:04 +00:00
Witold Kręcicki 6cf6ef336b Fix style in catz test 2018-11-13 19:02:04 +00:00
Witold Kręcicki 8b023a3d0e catz test: wait for dom8.example to be transferred before checking its availability 2018-11-13 19:02:04 +00:00
Evan HuntandWitold Kręcicki 52d63eeafc remove config.h references 2018-11-13 19:02:04 +00:00
61 changed files with 2470 additions and 2976 deletions
+41
View File
@@ -1,3 +1,44 @@
5090. [func] Use multiple event loops in socket code, and
make network threads CPU-affinitive. This
significantly improves performance on large
systems. [GL #666]
5082. [bug] Fixed a race that could cause a crash in
dig/host/nslookup. [GL #650]
5081. [func] Use per-worker queues in task manager, make task
runners CPU-affine. [GL #659]
5080. [func] Improvements to "rndc nta" user interface:
- catch and report invalid command line options
- when removing an NTA from all views, do not
abort with an error if the NTA was not found
in one of the views
- include the view name in "rndc nta -dump"
output, for consistency with the add and remove
actions
Thanks to Tony Finch. [GL !816]
5079. [func] Disable IDN processing in dig and nslookup
when not on a tty. [GL #653]
5078. [cleanup] Require python components to be explicitly disabled if
python is not available on unix platforms. [GL #601]
5077. [cleanup] Remove ip6.int support (-i) from dig and mdig.
[GL !969]
5076. [bug] "require-server-cookie" was not effective if
"rate-limit" was configured. [GL #617]
5075. [bug] Refresh nameservers from cache when sending final
query in qname minimization. [GL #16]
5074. [cleanup] Remove vector socket functions - isc_socket_recvv(),
isc_socket_sendtov(), isc_socket_sendtov2(),
isc_socket_sendv() - in order to simplify socket code.
[GL #645]
5073. [bug] Destroy a task first when destroying rpzs and catzs.
[GL #84]
+7 -7
View File
@@ -65,7 +65,7 @@ static char domainopt[DNS_NAME_MAXTEXT];
static char hexcookie[81];
static bool short_form = false, printcmd = true,
ip6_int = false, plusquest = false, pluscomm = false,
plusquest = false, pluscomm = false,
ipv4only = false, ipv6only = false;
static uint32_t splitwidth = 0xffffffff;
@@ -153,7 +153,6 @@ help(void) {
" -b address[#port] (bind to source address/port)\n"
" -c class (specify query class)\n"
" -f filename (batch mode)\n"
" -i (use IP6.INT for IPv6 reverse lookups)\n"
" -k keyfile (specify tsig key file)\n"
" -m (enable memory usage debugging)\n"
" -p port (specify port number)\n"
@@ -193,8 +192,10 @@ help(void) {
" +[no]fail (Don't try next server on SERVFAIL)\n"
" +[no]header-only (Send query without a question section)\n"
" +[no]identify (ID responders in short answers)\n"
" +[no]idnin (Parse IDN names)\n"
" +[no]idnout (Convert IDN response)\n"
#ifdef HAVE_LIBIDN2
" +[no]idnin (Parse IDN names [default=on on tty])\n"
" +[no]idnout (Convert IDN response [default=on on tty])\n"
#endif
" +[no]ignore (Don't revert to TCP for TC responses.)\n"
" +[no]keepalive (Request EDNS TCP keepalive)\n"
" +[no]keepopen (Keep the TCP socket open between queries)\n"
@@ -1606,7 +1607,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
exit(0);
break;
case 'i':
ip6_int = true;
/* deprecated */
break;
case 'm': /* memdebug */
/* memdebug is handled in preparse_args() */
@@ -1787,13 +1788,12 @@ dash_option(char *option, char *next, dig_lookup_t **lookup,
*lookup = clone_lookup(default_lookup, true);
*need_clone = true;
if (get_reverse(textname, sizeof(textname), value,
ip6_int, false) == ISC_R_SUCCESS) {
false) == ISC_R_SUCCESS) {
strlcpy((*lookup)->textname, textname,
sizeof((*lookup)->textname));
debug("looking up %s", (*lookup)->textname);
(*lookup)->trace_root = ((*lookup)->trace ||
(*lookup)->ns_search_only);
(*lookup)->ip6_int = ip6_int;
if (!(*lookup)->rdtypeset)
(*lookup)->rdtype = dns_rdatatype_ptr;
if (!(*lookup)->rdclassset)
+15 -15
View File
@@ -271,17 +271,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term>-i</term>
<listitem>
<para>
Do reverse IPv6 lookups using the obsolete RFC 1886 IP6.INT
domain, which is no longer in use. Obsolete bit string
label queries (RFC 2874) are not attempted.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-k <replaceable class="parameter">keyfile</replaceable></term>
<listitem>
@@ -394,8 +383,7 @@
<literal>94.2.0.192.in-addr.arpa</literal> and sets the
query type and class to PTR and IN respectively. IPv6
addresses are looked up using nibble format under the
IP6.ARPA domain (but see also the <option>-i</option>
option).
IP6.ARPA domain.
</para>
</listitem>
</varlistentry>
@@ -789,7 +777,13 @@
<para>
Process [do not process] IDN domain names on input.
This requires IDN SUPPORT to have been enabled at
compile time. The default is to process IDN input.
compile time.
</para>
<para>
The default is to process IDN input when standard output
is a tty. The IDN processing on input is disabled when
dig output is redirected to files, pipes, and other
non-tty file descriptors.
</para>
</listitem>
</varlistentry>
@@ -800,7 +794,13 @@
<para>
Convert [do not convert] puny code on output.
This requires IDN SUPPORT to have been enabled at
compile time. The default is to convert output.
compile time.
</para>
<para>
The default is to process puny code on output when
standard output is a tty. The puny code processing on
output is disabled when dig output is redirected to
files, pipes, and other non-tty file descriptors.
</para>
</listitem>
</varlistentry>
+106 -116
View File
@@ -312,8 +312,7 @@ reverse_octets(const char *in, char **p, char *end) {
}
isc_result_t
get_reverse(char *reverse, size_t len, char *value, bool ip6_int,
bool strict)
get_reverse(char *reverse, size_t len, char *value, bool strict)
{
int r;
isc_result_t result;
@@ -327,8 +326,6 @@ get_reverse(char *reverse, size_t len, char *value, bool ip6_int,
dns_name_t *name;
unsigned int options = 0;
if (ip6_int)
options |= DNS_BYADDROPT_IPV6INT;
name = dns_fixedname_initname(&fname);
result = dns_byaddr_createptrname(&addr, options, name);
if (result != ISC_R_SUCCESS)
@@ -628,7 +625,7 @@ make_empty_lookup(void) {
looknew->ttlunits = false;
looknew->qr = false;
#ifdef HAVE_LIBIDN2
looknew->idnin = (getenv("IDN_DISABLE") == NULL);
looknew->idnin = isatty(1)?(getenv("IDN_DISABLE") == NULL):false;
looknew->idnout = looknew->idnin;
#else
looknew->idnin = false;
@@ -652,7 +649,6 @@ make_empty_lookup(void) {
looknew->nsfound = 0;
looknew->tcp_mode = false;
looknew->tcp_mode_set = false;
looknew->ip6_int = false;
looknew->comments = true;
looknew->stats = true;
looknew->section_question = true;
@@ -1523,23 +1519,21 @@ clear_query(dig_query_t *query) {
debug("clear_query(%p)", query);
if (query->timer != NULL)
if (query->timer != NULL) {
isc_timer_detach(&query->timer);
}
lookup = query->lookup;
if (lookup->current_query == query)
if (lookup->current_query == query) {
lookup->current_query = NULL;
}
if (ISC_LINK_LINKED(query, link))
if (ISC_LINK_LINKED(query, link)) {
ISC_LIST_UNLINK(lookup->q, query, link);
if (ISC_LINK_LINKED(query, clink))
}
if (ISC_LINK_LINKED(query, clink)) {
ISC_LIST_UNLINK(lookup->connecting, query, clink);
if (ISC_LINK_LINKED(&query->recvbuf, link))
ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
link);
if (ISC_LINK_LINKED(&query->lengthbuf, link))
ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
link);
}
INSIST(query->recvspace != NULL);
if (query->sock != NULL) {
@@ -1548,12 +1542,16 @@ clear_query(dig_query_t *query) {
debug("sockcount=%d", sockcount);
}
isc_mempool_put(commctx, query->recvspace);
isc_mempool_put(commctx, query->tmpsendspace);
isc_buffer_invalidate(&query->recvbuf);
isc_buffer_invalidate(&query->lengthbuf);
if (query->waiting_senddone)
if (query->waiting_senddone) {
query->pending_free = true;
else
} else {
query->magic = 0;
isc_mem_free(mctx, query);
}
}
/*%
@@ -2461,13 +2459,14 @@ setup_lookup(dig_lookup_t *lookup) {
for (serv = ISC_LIST_HEAD(lookup->my_server_list);
serv != NULL;
serv = ISC_LIST_NEXT(serv, link)) {
serv = ISC_LIST_NEXT(serv, link))
{
query = isc_mem_allocate(mctx, sizeof(dig_query_t));
if (query == NULL)
if (query == NULL) {
fatal("memory allocation failure in %s:%d",
__FILE__, __LINE__);
debug("create query %p linked to lookup %p",
query, lookup);
}
debug("create query %p linked to lookup %p", query, lookup);
query->lookup = lookup;
query->timer = NULL;
query->waiting_connect = false;
@@ -2488,20 +2487,24 @@ setup_lookup(dig_lookup_t *lookup) {
query->msg_count = 0;
query->byte_count = 0;
query->ixfr_axfr = false;
ISC_LIST_INIT(query->recvlist);
ISC_LIST_INIT(query->lengthlist);
query->sock = NULL;
query->recvspace = isc_mempool_get(commctx);
if (query->recvspace == NULL)
query->tmpsendspace = isc_mempool_get(commctx);
if (query->recvspace == NULL) {
fatal("memory allocation failure");
}
isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
isc_buffer_init(&query->slbuf, query->slspace, 2);
isc_buffer_init(&query->tmpsendbuf, query->tmpsendspace,
COMMSIZE);
query->sendbuf = lookup->renderbuf;
ISC_LINK_INIT(query, clink);
ISC_LINK_INIT(query, link);
query->magic = DIG_QUERY_MAGIC;
ISC_LIST_ENQUEUE(lookup->q, query, link);
}
@@ -2510,9 +2513,10 @@ setup_lookup(dig_lookup_t *lookup) {
extrabytes = 0;
dighost_printmessage(ISC_LIST_HEAD(lookup->q),
lookup->sendmsg, true);
if (lookup->stats)
if (lookup->stats) {
printf(";; QUERY SIZE: %u\n\n",
isc_buffer_usedlength(&lookup->renderbuf));
}
}
return (true);
}
@@ -2523,8 +2527,6 @@ setup_lookup(dig_lookup_t *lookup) {
*/
static void
send_done(isc_task_t *_task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
isc_buffer_t *b = NULL;
dig_query_t *query, *next;
dig_lookup_t *l;
@@ -2539,28 +2541,27 @@ send_done(isc_task_t *_task, isc_event_t *event) {
debug("sendcount=%d", sendcount);
INSIST(sendcount >= 0);
for (b = ISC_LIST_HEAD(sevent->bufferlist);
b != NULL;
b = ISC_LIST_HEAD(sevent->bufferlist)) {
ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
isc_mem_free(mctx, b);
}
query = event->ev_arg;
REQUIRE(DIG_VALID_QUERY(query));
query->waiting_senddone = false;
l = query->lookup;
if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
if (!query->pending_free && l->ns_search_only &&
!l->trace_root && !l->tcp_mode)
{
debug("sending next, since searching");
next = ISC_LIST_NEXT(query, link);
if (next != NULL)
if (next != NULL) {
send_udp(next);
}
}
isc_event_free(&event);
if (query->pending_free)
if (query->pending_free) {
query->magic = 0;
isc_mem_free(mctx, query);
}
check_if_done();
UNLOCK_LOOKUP;
@@ -2578,6 +2579,7 @@ cancel_lookup(dig_lookup_t *lookup) {
debug("cancel_lookup()");
query = ISC_LIST_HEAD(lookup->q);
while (query != NULL) {
REQUIRE(DIG_VALID_QUERY(query));
next = ISC_LIST_NEXT(query, link);
if (query->sock != NULL) {
isc_socket_cancel(query->sock, global_task,
@@ -2597,6 +2599,7 @@ bringup_timer(dig_query_t *query, unsigned int default_timeout) {
dig_lookup_t *l;
unsigned int local_timeout;
isc_result_t result;
REQUIRE(DIG_VALID_QUERY(query));
debug("bringup_timer()");
/*
@@ -2661,6 +2664,7 @@ send_tcp_connect(dig_query_t *query) {
isc_result_t result;
dig_query_t *next;
dig_lookup_t *l;
REQUIRE(DIG_VALID_QUERY(query));
debug("send_tcp_connect(%p)", query);
@@ -2777,17 +2781,6 @@ send_tcp_connect(dig_query_t *query) {
}
}
static isc_buffer_t *
clone_buffer(isc_buffer_t *source) {
isc_buffer_t *buffer;
buffer = isc_mem_allocate(mctx, sizeof(*buffer));
if (buffer == NULL)
fatal("memory allocation failure in %s:%d",
__FILE__, __LINE__);
*buffer = *source;
return (buffer);
}
/*%
* Send a UDP packet to the remote nameserver, possible starting the
* recv action as well. Also make sure that the timer is running and
@@ -2797,8 +2790,10 @@ static void
send_udp(dig_query_t *query) {
dig_lookup_t *l = NULL;
isc_result_t result;
isc_buffer_t *sendbuf;
dig_query_t *next;
isc_region_t r;
isc_socketevent_t *sevent;
REQUIRE(DIG_VALID_QUERY(query));
debug("send_udp(%p)", query);
@@ -2859,29 +2854,27 @@ send_udp(dig_query_t *query) {
check_result(result, "isc_socket_bind");
query->recv_made = true;
ISC_LINK_INIT(&query->recvbuf, link);
ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
link);
isc_buffer_availableregion(&query->recvbuf, &r);
debug("recving with lookup=%p, query=%p, sock=%p",
query->lookup, query, query->sock);
result = isc_socket_recvv(query->sock, &query->recvlist, 1,
global_task, recv_done, query);
check_result(result, "isc_socket_recvv");
result = isc_socket_recv(query->sock, &r, 1,
global_task, recv_done, query);
check_result(result, "isc_socket_recv");
recvcount++;
debug("recvcount=%d", recvcount);
}
ISC_LIST_INIT(query->sendlist);
sendbuf = clone_buffer(&query->sendbuf);
ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
isc_buffer_usedregion(&query->sendbuf, &r);
debug("sending a request");
TIME_NOW(&query->time_sent);
INSIST(query->sock != NULL);
query->waiting_senddone = true;
result = isc_socket_sendtov2(query->sock, &query->sendlist,
global_task, send_done, query,
&query->sockaddr, NULL,
ISC_SOCKFLAG_NORETRY);
check_result(result, "isc_socket_sendtov");
sevent = isc_socket_socketevent(mctx, query->sock,
ISC_SOCKEVENT_SENDDONE,
send_done, query);
result = isc_socket_sendto2(query->sock, &r,
global_task, &query->sockaddr, NULL,
sevent, ISC_SOCKFLAG_NORETRY);
check_result(result, "isc_socket_sendto2");
sendcount++;
}
@@ -2902,6 +2895,7 @@ connect_timeout(isc_task_t *task, isc_event_t *event) {
LOCK_LOOKUP;
query = event->ev_arg;
REQUIRE(DIG_VALID_QUERY(query));
l = query->lookup;
isc_event_free(&event);
@@ -2971,7 +2965,8 @@ connect_timeout(isc_task_t *task, isc_event_t *event) {
static void
tcp_length_done(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent;
isc_buffer_t *b = NULL;
isc_buffer_t b;
isc_region_t r;
isc_result_t result;
dig_query_t *query = NULL;
dig_lookup_t *l, *n;
@@ -2987,14 +2982,11 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) {
LOCK_LOOKUP;
sevent = (isc_socketevent_t *)event;
query = event->ev_arg;
REQUIRE(DIG_VALID_QUERY(query));
recvcount--;
INSIST(recvcount >= 0);
b = ISC_LIST_HEAD(sevent->bufferlist);
INSIST(b == &query->lengthbuf);
ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
if (sevent->result == ISC_R_CANCELED) {
isc_event_free(&event);
l = query->lookup;
@@ -3027,7 +3019,10 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) {
UNLOCK_LOOKUP;
return;
}
length = isc_buffer_getuint16(b);
isc_buffer_init(&b, sevent->region.base, sevent->n);
isc_buffer_add(&b, sevent->n);
length = isc_buffer_getuint16(&b);
if (length == 0) {
isc_event_free(&event);
launch_next_query(query, false);
@@ -3041,13 +3036,11 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) {
*/
isc_buffer_invalidate(&query->recvbuf);
isc_buffer_init(&query->recvbuf, query->recvspace, length);
ENSURE(ISC_LIST_EMPTY(query->recvlist));
ISC_LINK_INIT(&query->recvbuf, link);
ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
isc_buffer_availableregion(&query->recvbuf, &r);
debug("recving with lookup=%p, query=%p", query->lookup, query);
result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
recv_done, query);
check_result(result, "isc_socket_recvv");
result = isc_socket_recv(query->sock, &r, length, task,
recv_done, query);
check_result(result, "isc_socket_recv");
recvcount++;
debug("resubmitted recv request with length %d, recvcount=%d",
length, recvcount);
@@ -3063,7 +3056,8 @@ static void
launch_next_query(dig_query_t *query, bool include_question) {
isc_result_t result;
dig_lookup_t *l;
isc_buffer_t *buffer;
isc_region_t r;
REQUIRE(DIG_VALID_QUERY(query));
INSIST(!free_now);
@@ -3082,35 +3076,28 @@ launch_next_query(dig_query_t *query, bool include_question) {
return;
}
isc_buffer_clear(&query->slbuf);
isc_buffer_clear(&query->lengthbuf);
isc_buffer_putuint16(&query->slbuf, (uint16_t) query->sendbuf.used);
ISC_LIST_INIT(query->sendlist);
ISC_LINK_INIT(&query->slbuf, link);
if (!query->first_soa_rcvd) {
buffer = clone_buffer(&query->slbuf);
ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
if (include_question) {
buffer = clone_buffer(&query->sendbuf);
ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
}
}
ISC_LINK_INIT(&query->lengthbuf, link);
ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
global_task, tcp_length_done, query);
check_result(result, "isc_socket_recvv");
isc_buffer_availableregion(&query->lengthbuf, &r);
result = isc_socket_recv(query->sock, &r, 0,
global_task, tcp_length_done, query);
check_result(result, "isc_socket_recv");
recvcount++;
debug("recvcount=%d", recvcount);
if (!query->first_soa_rcvd) {
debug("sending a request in launch_next_query");
TIME_NOW(&query->time_sent);
query->waiting_senddone = true;
result = isc_socket_sendv(query->sock, &query->sendlist,
global_task, send_done, query);
check_result(result, "isc_socket_sendv");
isc_buffer_clear(&query->tmpsendbuf);
isc_buffer_putuint16(&query->tmpsendbuf,
isc_buffer_usedlength(&query->sendbuf));
if (include_question) {
isc_buffer_usedregion(&query->sendbuf, &r);
isc_buffer_copyregion(&query->tmpsendbuf, &r);
}
isc_buffer_usedregion(&query->tmpsendbuf, &r);
result = isc_socket_send(query->sock, &r,
global_task, send_done, query);
check_result(result, "isc_socket_send");
sendcount++;
debug("sendcount=%d", sendcount);
}
@@ -3143,6 +3130,7 @@ connect_done(isc_task_t *task, isc_event_t *event) {
LOCK_LOOKUP;
sevent = (isc_socketevent_t *)event;
query = sevent->ev_arg;
REQUIRE(DIG_VALID_QUERY(query));
INSIST(query->waiting_connect);
@@ -3460,8 +3448,9 @@ ednsvers(dns_rdataset_t *opt) {
static void
recv_done(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = NULL;
isc_region_t r;
dig_query_t *query = NULL;
isc_buffer_t *b = NULL;
isc_buffer_t b;
dns_message_t *msg = NULL;
isc_result_t result;
dig_lookup_t *n, *l;
@@ -3491,9 +3480,8 @@ recv_done(isc_task_t *task, isc_event_t *event) {
REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
sevent = (isc_socketevent_t *)event;
b = ISC_LIST_HEAD(sevent->bufferlist);
INSIST(b == &query->recvbuf);
ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
isc_buffer_init(&b, sevent->region.base, sevent->n);
isc_buffer_add(&b, sevent->n);
if ((l->tcp_mode) && (query->timer != NULL))
isc_timer_touch(query->timer);
@@ -3569,7 +3557,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
}
}
result = dns_message_peekheader(b, &id, &msgflags);
result = dns_message_peekheader(&b, &id, &msgflags);
if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
match = false;
if (l->tcp_mode) {
@@ -3638,7 +3626,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
}
result = dns_message_parse(msg, b, parseflags);
result = dns_message_parse(msg, &b, parseflags);
if (result == DNS_R_RECOVERABLE) {
printf(";; Warning: Message parser reports malformed "
"message packet.\n");
@@ -3646,7 +3634,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
}
if (result != ISC_R_SUCCESS) {
printf(";; Got bad packet: %s\n", isc_result_totext(result));
hex_dump(b);
hex_dump(&b);
query->waiting_connect = false;
dns_message_destroy(&msg);
isc_event_free(&event);
@@ -3800,7 +3788,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
}
if (tsigkey != NULL) {
result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
result = dns_tsig_verify(&b, msg, NULL, NULL);
if (result != ISC_R_SUCCESS) {
printf(";; Couldn't verify signature: %s\n",
isc_result_totext(result));
@@ -3816,7 +3804,7 @@ recv_done(isc_task_t *task, isc_event_t *event) {
check_result(result,"dns_message_getquerytsig");
}
extrabytes = isc_buffer_remaininglength(b);
extrabytes = isc_buffer_remaininglength(&b);
debug("after parse");
if (l->doing_xfr && l->xfr_q == NULL) {
@@ -3863,8 +3851,8 @@ recv_done(isc_task_t *task, isc_event_t *event) {
(l->origin != NULL || l->need_search)) {
if (!next_origin(query->lookup) || showsearch) {
dighost_printmessage(query, msg, true);
dighost_received(b->used, &sevent->address,
query);
dighost_received(isc_buffer_usedlength(&b),
&sevent->address, query);
}
} else if (!l->trace && !l->ns_search_only) {
dighost_printmessage(query, msg, true);
@@ -3931,7 +3919,8 @@ recv_done(isc_task_t *task, isc_event_t *event) {
} else {
if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
dighost_received(b->used, &sevent->address, query);
dighost_received(isc_buffer_usedlength(&b),
&sevent->address, query);
}
if (!query->lookup->ns_search_only)
@@ -3955,10 +3944,10 @@ recv_done(isc_task_t *task, isc_event_t *event) {
udp_mismatch:
isc_buffer_invalidate(&query->recvbuf);
isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
result = isc_socket_recvv(query->sock, &query->recvlist, 1,
global_task, recv_done, query);
check_result(result, "isc_socket_recvv");
isc_buffer_availableregion(&query->recvbuf, &r);
result = isc_socket_recv(query->sock, &r, 1,
global_task, recv_done, query);
check_result(result, "isc_socket_recv");
recvcount++;
isc_event_free(&event);
UNLOCK_LOOKUP;
@@ -4033,6 +4022,7 @@ do_lookup(dig_lookup_t *lookup) {
lookup->pending = true;
query = ISC_LIST_HEAD(lookup->q);
if (query != NULL) {
REQUIRE(DIG_VALID_QUERY(query));
if (lookup->tcp_mode)
send_tcp_connect(query);
else
+3 -4
View File
@@ -143,7 +143,6 @@ show_usage(void) {
" -c specifies query class for non-IN data\n"
" -C compares SOA records on authoritative nameservers\n"
" -d is equivalent to -v\n"
" -i IP6.INT reverse lookups\n"
" -l lists all hosts in a domain, using AXFR\n"
" -m set memory debugging flag (trace|record|usage)\n"
" -N changes the number of dots allowed before root lookup is done\n"
@@ -762,7 +761,7 @@ parse_args(bool is_batchfile, int argc, char **argv) {
default_lookups = false;
break;
case 'i':
lookup->ip6_int = true;
/* deprecated */
break;
case 'n':
/* deprecated */
@@ -841,8 +840,8 @@ parse_args(bool is_batchfile, int argc, char **argv) {
check_ra = true;
lookup->pending = false;
if (get_reverse(store, sizeof(store), hostname,
lookup->ip6_int, true) == ISC_R_SUCCESS) {
if (get_reverse(store, sizeof(store), hostname, true)
== ISC_R_SUCCESS) {
strlcpy(lookup->textname, store, sizeof(lookup->textname));
lookup->rdtype = dns_rdatatype_ptr;
lookup->rdtypeset = true;
-12
View File
@@ -179,18 +179,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term>-i</term>
<listitem>
<para>
Obsolete.
Use the IP6.INT domain for reverse lookups of IPv6
addresses as defined in RFC1886 and deprecated in RFC4159.
The default is to use IP6.ARPA as specified in RFC3596.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-l</term>
<listitem>
+12 -11
View File
@@ -26,6 +26,7 @@
#include <isc/formatcheck.h>
#include <isc/lang.h>
#include <isc/list.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/sockaddr.h>
@@ -81,6 +82,11 @@ typedef struct dig_server dig_server_t;
typedef ISC_LIST(dig_server_t) dig_serverlist_t;
typedef struct dig_searchlist dig_searchlist_t;
#define DIG_QUERY_MAGIC ISC_MAGIC('D','i','g','q')
#define DIG_VALID_QUERY(x) ISC_MAGIC_VALID((x), DIG_QUERY_MAGIC)
/*% The dig_lookup structure */
struct dig_lookup {
bool
@@ -103,7 +109,6 @@ struct dig_lookup {
trace_root, /*% initial query for either +trace or +nssearch */
tcp_mode,
tcp_mode_set,
ip6_int,
comments,
stats,
section_question,
@@ -185,6 +190,7 @@ struct dig_lookup {
/*% The dig_query structure */
struct dig_query {
unsigned int magic;
dig_lookup_t *lookup;
bool waiting_connect,
pending_free,
@@ -203,15 +209,12 @@ struct dig_query {
bool ixfr_axfr;
char *servname;
char *userarg;
isc_bufferlist_t sendlist,
recvlist,
lengthlist;
isc_buffer_t recvbuf,
lengthbuf,
slbuf;
char *recvspace,
lengthspace[4],
slspace[4];
tmpsendbuf,
sendbuf;
char *recvspace, *tmpsendspace,
lengthspace[4];
isc_socket_t *sock;
ISC_LINK(dig_query_t) link;
ISC_LINK(dig_query_t) clink;
@@ -219,7 +222,6 @@ struct dig_query {
isc_time_t time_sent;
isc_time_t time_recv;
uint64_t byte_count;
isc_buffer_t sendbuf;
isc_timer_t *timer;
};
@@ -284,8 +286,7 @@ int
getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp);
isc_result_t
get_reverse(char *reverse, size_t len, char *value, bool ip6_int,
bool strict);
get_reverse(char *reverse, size_t len, char *value, bool strict);
ISC_PLATFORM_NORETURN_PRE void
fatal(const char *format, ...)
+1 -7
View File
@@ -772,7 +772,7 @@ addlookup(char *opt) {
rdclass = dns_rdataclass_in;
}
lookup = make_empty_lookup();
if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, true)
if (get_reverse(store, sizeof(store), opt, true)
== ISC_R_SUCCESS) {
strlcpy(lookup->textname, store, sizeof(lookup->textname));
lookup->rdtype = dns_rdatatype_ptr;
@@ -923,12 +923,6 @@ flush_lookup_list(void) {
ISC_SOCKCANCEL_ALL);
isc_socket_detach(&q->sock);
}
if (ISC_LINK_LINKED(&q->recvbuf, link))
ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
link);
if (ISC_LINK_LINKED(&q->lengthbuf, link))
ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
link);
isc_buffer_invalidate(&q->recvbuf);
isc_buffer_invalidate(&q->lengthbuf);
qp = q;
+2 -1
View File
@@ -489,7 +489,8 @@ nslookup -query=hinfo -timeout=10
If you'd like to turn off the IDN support for some reason, define
the <envar>IDN_DISABLE</envar> environment variable.
The IDN support is disabled if the variable is set when
<command>nslookup</command> runs.
<command>nslookup</command> runs or when the standard output is not
a tty.
</para>
</refsection>
+2 -5
View File
@@ -793,10 +793,7 @@ create_managers(void) {
named_g_udpdisp = 1;
#else
if (named_g_udpdisp == 0) {
if (named_g_cpus_detected == 1)
named_g_udpdisp = 1;
else
named_g_udpdisp = named_g_cpus_detected - 1;
named_g_udpdisp = named_g_cpus_detected;
}
if (named_g_udpdisp > named_g_cpus)
named_g_udpdisp = named_g_cpus;
@@ -824,7 +821,7 @@ create_managers(void) {
}
result = isc_socketmgr_create2(named_g_mctx, &named_g_socketmgr,
maxsocks);
maxsocks, named_g_cpus);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_socketmgr_create() failed: %s",
+54 -15
View File
@@ -9327,8 +9327,7 @@ load_zones(named_server_t *server, bool init, bool reconfig) {
* the initial server setup; it isn't necessary during
* a reload.)
*/
isc_taskmgr_setmode(named_g_taskmgr,
isc_taskmgrmode_privileged);
isc_taskmgr_setprivilegedmode(named_g_taskmgr);
}
isc_task_endexclusive(server->task);
@@ -10877,7 +10876,7 @@ named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex,
continue;
}
CHECK(putstr(text, "\n Negative trust anchors:\n\n"));
CHECK(dns_ntatable_totext(ntatable, text));
CHECK(dns_ntatable_totext(ntatable, NULL, text));
}
if (ptr != NULL)
ptr = next_token(lex, text);
@@ -14314,6 +14313,7 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
isc_result_t result = ISC_R_SUCCESS;
char *ptr, *nametext = NULL, *viewname;
char namebuf[DNS_NAME_FORMATSIZE];
char viewbuf[DNS_NAME_FORMATSIZE];
isc_stdtime_t now, when;
isc_time_t t;
char tbuf[64];
@@ -14323,8 +14323,9 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
const dns_name_t *ntaname;
dns_name_t *fname;
dns_ttl_t ntattl;
bool ttlset = false, excl = false;
bool ttlset = false, excl = false, viewfound = false;
dns_rdataclass_t rdclass = dns_rdataclass_in;
bool first = true;
UNUSED(force);
@@ -14337,18 +14338,24 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
}
for (;;) {
bool opts = true;
/* Check for options */
ptr = next_token(lex, text);
if (ptr == NULL) {
return (ISC_R_UNEXPECTEDEND);
}
if (argcheck(ptr, "dump")) {
if (!opts) {
nametext = ptr;
} else if (strcmp(ptr, "--") == 0) {
opts = false;
} else if (argcheck(ptr, "dump")) {
dump = true;
} else if (argcheck(ptr, "remove")) {
ntattl = 0;
ttlset = true;
} else if (argcheck(ptr, "force")) {
} else if (opts && argcheck(ptr, "force")) {
force = true;
continue;
} else if (argcheck(ptr, "lifetime")) {
@@ -14388,6 +14395,9 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
tr.length = strlen(ptr);
CHECK(dns_rdataclass_fromtext(&rdclass, &tr));
continue;
} else if (ptr[0] == '-') {
msg = "Unknown option";
CHECK(DNS_R_SYNTAX);
} else {
nametext = ptr;
}
@@ -14410,7 +14420,8 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
if (result == ISC_R_NOTFOUND) {
continue;
}
CHECK(dns_ntatable_totext(ntatable, text));
CHECK(dns_ntatable_totext(ntatable, view->name, text));
}
CHECK(putnull(text));
@@ -14448,6 +14459,14 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
/* Look for the view name. */
viewname = next_token(lex, text);
if (viewname != NULL) {
strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE);
viewname = viewbuf;
}
if (next_token(lex, text) != NULL) {
CHECK(DNS_R_SYNTAX);
}
isc_stdtime_get(&now);
@@ -14458,11 +14477,10 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
view != NULL;
view = ISC_LIST_NEXT(view, link))
{
static bool first = true;
if (viewname != NULL && strcmp(view->name, viewname) != 0) {
continue;
}
viewfound = true;
if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) {
continue;
@@ -14518,22 +14536,37 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
"added NTA '%s' (%d sec) in view '%s'",
namebuf, ntattl, view->name);
} else {
CHECK(dns_ntatable_delete(ntatable, ntaname));
bool removed;
result = dns_ntatable_delete(ntatable, ntaname);
if (result == ISC_R_SUCCESS) {
removed = true;
} else if (result == ISC_R_NOTFOUND) {
removed = false;
} else {
goto cleanup;
}
if (!first) {
CHECK(putstr(text, "\n"));
}
first = false;
CHECK(putstr(text, "Negative trust anchor removed: "));
CHECK(putstr(text, "Negative trust anchor "));
CHECK(putstr(text, removed ? "removed: "
: "not found: "));
CHECK(putstr(text, namebuf));
CHECK(putstr(text, "/"));
CHECK(putstr(text, view->name));
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
"removed NTA '%s' in view %s",
namebuf, view->name);
if (removed) {
isc_log_write(named_g_lctx,
NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER,
ISC_LOG_INFO,
"removed NTA '%s' in view %s",
namebuf, view->name);
}
}
result = dns_view_saventa(view);
@@ -14546,6 +14579,11 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
}
}
if (!viewfound) {
msg = "No such view";
CHECK(ISC_R_NOTFOUND);
}
CHECK(putnull(text));
cleanup:
@@ -14553,6 +14591,7 @@ named_server_nta(named_server_t *server, isc_lex_t *lex,
(void) putstr(text, msg);
(void) putnull(text);
}
if (excl) {
isc_task_endexclusive(server->task);
}
+6
View File
@@ -650,6 +650,12 @@
<option>-l</option>, <option>-r</option>, <option>-d</option>,
<option>-f</option>, and <option>-c</option>.
</para>
<para>
Unrecognized options are treated as errors. To reference
a domain or view name that begins with a hyphen,
use a double-hyphen on the command line to indicate the
end of options.
</para>
</listitem>
</varlistentry>
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 3600 SOA . . 0 0 0 0 0
@ 3600 NS .
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
options {
query-source address 10.53.0.8;
notify-source 10.53.0.8;
transfer-source 10.53.0.8;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.8; };
listen-on-v6 { none; };
dnssec-validation yes;
rate-limit {};
require-server-cookie yes;
};
zone "example" {
type master;
file "example.db";
};
+1
View File
@@ -20,3 +20,4 @@ copy_setports ns4/named.conf.in ns4/named.conf
copy_setports ns5/named.conf.in ns5/named.conf
copy_setports ns6/named.conf.in ns6/named.conf
copy_setports ns7/named.conf.in ns7/named.conf
copy_setports ns8/named.conf.in ns8/named.conf
+11
View File
@@ -169,6 +169,17 @@ if [ $linecount != 2 ]; then ret=1; fi
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "checking require-server-cookie yes with rate-limit ($n)"
ret=0
$DIG $DIGOPTS +qr +cookie +nobadcookie soa example @10.53.0.8 > dig.out.test$n
grep "flags: qr[^;]* ad[ ;]" dig.out.test$n > /dev/null && ret=1
grep BADCOOKIE dig.out.test$n > /dev/null || ret=1
linecount=`getcookie dig.out.test$n | wc -l`
if [ $linecount != 2 ]; then ret=1; fi
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
#
# Test shared cookie-secret support.
#
+6 -6
View File
@@ -1873,8 +1873,8 @@ $PERL -e 'my $delay = '$start' + 13 - time(); select(undef, undef, undef, $delay
$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n._11
lines=`grep " expiry " rndc.out.ns4.test$n._11 | wc -l`
[ "$lines" -le 2 ] || ret=1
grep "bogus.example: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1
grep "badds.example: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1
grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1
grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1
$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.11 || ret=1
grep "status: SERVFAIL" dig.out.ns4.test$n.11 > /dev/null && ret=1
$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.12 || ret=1
@@ -1910,14 +1910,14 @@ ret=0
echo_i "testing NTA removals ($n)"
$RNDCCMD 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
grep "badds.example: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1
grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1
$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null && ret=1
grep "^a.badds.example." dig.out.ns4.test$n.1 > /dev/null || ret=1
$RNDCCMD 10.53.0.4 nta -remove badds.example > rndc.out.ns4.test$n.2
grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 > /dev/null || ret=1
$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
grep "badds.example: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1
grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1
$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -1928,7 +1928,7 @@ echo_i "remove non-existent NTA three times"
$RNDCCMD 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.4 2>&1
$RNDCCMD 10.53.0.4 nta -remove foo > rndc.out.ns4.test$n.5 2>&1
$RNDCCMD 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.6 2>&1
grep "'nta' failed: not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1
grep "not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
ret=0
@@ -2009,7 +2009,7 @@ sleep 4
$RNDCCMD 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
lines=`wc -l < rndc.out.ns4.test$n.3`
[ "$lines" -eq 1 ] || ret=1
grep "bogus.example: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1
grep "bogus.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1
$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
@@ -27,6 +27,7 @@ options {
send-cookie no;
require-server-cookie no;
dnssec-validation yes;
qname-minimization disabled;
};
key rndc_key {
@@ -27,6 +27,7 @@ options {
send-cookie no;
require-server-cookie no;
dnssec-validation yes;
qname-minimization disabled;
};
key rndc_key {
@@ -28,6 +28,7 @@ options {
require-server-cookie no;
minimal-responses no;
dnssec-validation yes;
qname-minimization disabled;
};
server 10.53.0.1 { tcp-only yes; };
@@ -27,6 +27,7 @@ options {
send-cookie no;
require-server-cookie no;
dnssec-validation yes;
qname-minimization disabled;
};
server 10.53.0.1 { tcp-only yes; };
+3 -3
View File
@@ -157,7 +157,7 @@ status=`expr $status + $ret`
copy_setports ns3/named3.conf.in ns3/named.conf
$RNDCCMD reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
echo_i "checking lame server clients are dropped at the soft limit"
echo_i "checking lame server clients are dropped near the soft limit"
ret=0
fail=0
exceeded=0
@@ -166,7 +166,7 @@ touch ans4/norespond
for try in 1 2 3 4 5; do
burst b $try 400
$DIG @10.53.0.3 -p ${PORT} a ${try}.example > dig.out.ns3.$try
stat 360 || exceeded=`expr $exceeded + 1`
stat 370 || exceeded=`expr $exceeded + 1`
grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
success=`expr $success + 1`
grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
@@ -177,7 +177,7 @@ echo_i "$success successful valid queries (expected 5)"
[ "$success" -eq 5 ] || { echo_i "failed"; ret=1; }
echo_i "$fail SERVFAIL responses (expected 0)"
[ "$fail" -eq 0 ] || { echo_i "failed"; ret=1; }
echo_i "clients count exceeded 360 on $exceeded trials (expected 0)"
echo_i "clients count exceeded 370 on $exceeded trials (expected 0)"
[ "$exceeded" -eq 0 ] || { echo_i "failed"; ret=1; }
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
+12 -12
View File
@@ -185,11 +185,11 @@ idna_enabled_test() {
# Note that ASCII characters are converted to lower-case.
text="Checking valid non-ASCII label"
idna_test "$text" "" "München" "nchen."
idna_test "$text" "" "München" "M\195\188nchen."
idna_test "$text" "+noidnin +noidnout" "München" "M\195\188nchen."
idna_test "$text" "+noidnin +idnout" "München" "M\195\188nchen."
idna_test "$text" "+idnin +noidnout" "München" "xn--mnchen-3ya."
idna_test "$text" "+idnin +idnout" "München" "münchen."
idna_test "$text" "+idnin +idnout" "München" "münchen."
# Tests of transitional processing of a valid U-label
@@ -210,7 +210,7 @@ idna_enabled_test() {
# for the valid U-label.
text="Checking that non-transitional IDNA processing is used"
idna_test "$text" "" "faß.de" "faß.de."
idna_test "$text" "" "faß.de" "fa\195\159.de."
idna_test "$text" "+noidnin +noidnout" "faß.de" "fa\195\159.de."
idna_test "$text" "+noidnin +idnout" "faß.de" "fa\195\159.de."
idna_test "$text" "+idnin +noidnout" "faß.de" "xn--fa-hia.de."
@@ -220,11 +220,11 @@ idna_enabled_test() {
# onto the Greek sigma character ("σ") in IDNA2003.
text="Second check that non-transitional IDNA processing is used"
idna_test "$text" "" "βόλος.com" "βόλος.com."
idna_test "$text" "" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com."
idna_test "$text" "+noidnin +noidnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com."
idna_test "$text" "+noidnin +idnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com."
idna_test "$text" "+idnin +noidnout" "βόλος.com" "xn--nxasmm1c.com."
idna_test "$text" "+idnin +idnout" "βόλος.com" "βόλος.com."
idna_test "$text" "+idnin +idnout" "βόλος.com" "βόλος.com."
@@ -238,9 +238,9 @@ idna_enabled_test() {
# The "+[no]idnin" flag has no effect in these cases.
text="Checking valid A-label"
idna_test "$text" "" "xn--nxasmq6b.com" "βόλοσ.com."
idna_test "$text" "" "xn--nxasmq6b.com" "xn--nxasmq6b.com."
idna_test "$text" "+noidnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com."
idna_test "$text" "+noidnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com."
idna_test "$text" "+noidnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com."
idna_test "$text" "+idnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com."
idna_test "$text" "+idnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com."
@@ -259,7 +259,7 @@ idna_enabled_test() {
# a shorter label is detected and rejected.
text="Checking punycode label shorter than minimum valid length"
idna_fail "$text" "" "xn--xx"
idna_test "$text" "" "xn--xx" "xn--xx."
idna_test "$text" "+noidnin +noidnout" "xn--xx" "xn--xx."
idna_fail "$text" "+noidnin +idnout" "xn--xx"
idna_fail "$text" "+idnin +noidnout" "xn--xx"
@@ -268,7 +268,7 @@ idna_enabled_test() {
# Fake A-label - the string does not translate to anything.
text="Checking fake A-label"
idna_fail "$text" "" "xn--ahahah"
idna_test "$text" "" "xn--ahahah" "xn--ahahah."
idna_test "$text" "+noidnin +noidnout" "xn--ahahah" "xn--ahahah."
idna_fail "$text" "+noidnin +idnout" "xn--ahahah"
idna_fail "$text" "+idnin +noidnout" "xn--ahahah"
@@ -285,7 +285,7 @@ idna_enabled_test() {
idna_fail "$text" "+idnin +noidnout" "$label"
idna_fail "$text" "+idnin +idnout" "$label"
# Tests of a valid unicode string but an invalid U-label (input)
@@ -301,7 +301,7 @@ idna_enabled_test() {
# The +[no]idnout options should not have any effect on the test.
text="Checking invalid input U-label"
idna_fail "$text" "" "√.com"
idna_test "$text" "" "√.com" "\226\136\154.com."
idna_test "$text" "+noidnin +noidnout" "√.com" "\226\136\154.com."
idna_test "$text" "+noidnin +idnout" "√.com" "\226\136\154.com."
idna_fail "$text" "+idnin +noidnout" "√.com"
@@ -323,7 +323,7 @@ idna_enabled_test() {
# The +[no]idnin options should not have any effect on the test.
text="Checking invalid output U-label"
idna_fail "$text" "" "xn--19g"
idna_test "$text" "" "xn--19g" "xn--19g."
idna_test "$text" "+noidnin +noidnout" "xn--19g" "xn--19g."
idna_fail "$text" "+noidnin +idnout" "xn--19g"
idna_test "$text" "+idnin +noidnout" "xn--19g" "xn--19g."
+3 -2
View File
@@ -150,10 +150,11 @@ $RNDCCMD 10.53.0.6 flush
$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.6 > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
sleep 1
cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
sort ans2/query.log > ans2/query.log.sorted
cat << __EOF | diff ans2/query.log.sorted - > /dev/null || ret=1
ADDR ns2.bad.
NS bad.
NS boing.bad.
ADDR ns2.bad.
__EOF
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
if [ $ret != 0 ]; then echo_i "failed"; fi
+24 -21
View File
@@ -44,39 +44,42 @@ $SIG{TERM} = \&rmpid;
sub handleUDP {
my ($buf) = @_;
my $packet;
my $request;
if ($Net::DNS::VERSION > 0.68) {
$packet = new Net::DNS::Packet(\$buf, 0);
$request = new Net::DNS::Packet(\$buf, 0);
$@ and die $@;
} else {
my $err;
($packet, $err) = new Net::DNS::Packet(\$buf, 0);
($request, $err) = new Net::DNS::Packet(\$buf, 0);
$err and die $err;
}
my @questions = $packet->question;
my @questions = $request->question;
my $qname = $questions[0]->qname;
my $qtype = $questions[0]->qtype;
my $qclass = $questions[0]->qclass;
my $id = $packet->header->id;
my $id = $request->header->id;
$packet->header->qr(1);
$packet->header->aa(1);
$packet->header->tc(0);
my $response = new Net::DNS::Packet($qname, $qtype, $qclass);
$response->header->qr(1);
$response->header->aa(1);
$response->header->tc(0);
$response->header->id($id);
# Responses to queries for no-questions/NS and ns.no-questions/A are
# _not_ malformed or truncated.
if ($qname eq "no-questions" && $qtype eq "NS") {
$packet->push("answer", new Net::DNS::RR($qname . " 300 NS ns.no-questions"));
$packet->push("additional", new Net::DNS::RR("ns.no-questions. 300 A 10.53.0.8"));
return $packet->data;
$response->push("answer", new Net::DNS::RR($qname . " 300 NS ns.no-questions"));
$response->push("additional", new Net::DNS::RR("ns.no-questions. 300 A 10.53.0.8"));
return $response->data;
} elsif ($qname eq "ns.no-questions") {
$packet->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.8"));
return $packet->data;
$response->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.8"))
if ($qtype eq "A");
return $response->data;
} elsif ($qname =~ /\.formerr-to-all$/) {
$packet->header->rcode("FORMERR");
return $packet->data;
$response->header->rcode("FORMERR");
return $response->data;
}
# don't use Net::DNS to construct the header only reply as early
@@ -110,14 +113,14 @@ sub handleTCP {
my $id = $request->header->id;
my @results = ();
my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
my $response = new Net::DNS::Packet($qname, $qtype, $qclass);
$packet->header->qr(1);
$packet->header->aa(1);
$packet->header->id($id);
$response->header->qr(1);
$response->header->aa(1);
$response->header->id($id);
$packet->push("answer", new Net::DNS::RR("$qname 300 A 1.2.3.4"));
push(@results, $packet->data);
$response->push("answer", new Net::DNS::RR("$qname 300 A 1.2.3.4"));
push(@results, $response->data);
return \@results;
}
-22
View File
@@ -24,28 +24,6 @@ grep "another named process" ns2/named.run > /dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
if [ ! "$CYGWIN" ]; then
n=`expr $n + 1`
echo_i "verifying that named checks for conflicting listeners ($n)"
ret=0
(cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X other.lock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
for i in 1 2 3 4 5 6 7 8 9
do
grep "unable to listen on any configured interface" ns2/named2.run > /dev/null && break
sleep 1
done
grep "unable to listen on any configured interface" ns2/named2.run > /dev/null || ret=1
for i in 1 2 3 4 5 6 7 8 9
do
grep "exiting (due to fatal error)" ns2/named2.run > /dev/null && break
sleep 1
done
pid=`cat ns2/named2.pid 2>/dev/null`
test "${pid:+set}" = set && $KILL -15 ${pid} >/dev/null 2>&1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
fi
n=`expr $n + 1`
echo_i "verifying that named checks for conflicting named processes ($n)"
ret=0
+29
View File
@@ -83,6 +83,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -92,6 +93,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -101,6 +103,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -166,6 +169,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -175,6 +179,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -184,6 +189,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -247,6 +253,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -256,6 +263,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -265,6 +273,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -296,6 +305,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -305,6 +315,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -314,6 +325,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -371,6 +383,17 @@ grep "syntax error" rndc.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "flush cache, re-enable serve-stale and query again ($n)"
ret=0
$RNDCCMD 10.53.0.1 flushtree example > rndc.out.test$n.1 2>&1 || ret=1
$RNDCCMD 10.53.0.1 serve-stale on > rndc.out.test$n.2 2>&1 || ret=1
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "enable responses from authoritative server ($n)"
ret=0
@@ -386,6 +409,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -395,6 +419,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -404,6 +429,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -474,6 +500,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -483,6 +510,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -492,6 +520,7 @@ ret=0
$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$n
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example.*1.*IN" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
+3 -9
View File
@@ -120,7 +120,6 @@ static char hexcookie[81];
struct query {
char textname[MXNAME]; /*% Name we're going to be looking up */
bool ip6_int;
bool recurse;
bool have_aaonly;
bool have_adflag;
@@ -774,7 +773,6 @@ help(void) {
" local opt is one of:\n"
" -c class (specify query class)\n"
" -t type (specify query type)\n"
" -i (use IP6.INT for IPv6 reverse lookups)\n"
" -x dot-notation (shortcut for reverse lookups)\n"
" +timeout=### (Set query timeout) [UDP=5,TCP=10]\n"
" +udptimeout=### (Set timeout before UDP retry)\n"
@@ -995,8 +993,7 @@ reverse_octets(const char *in, char **p, char *end) {
}
static void
get_reverse(char *reverse, size_t len, const char *value,
bool ip6_int)
get_reverse(char *reverse, size_t len, const char *value)
{
int r;
isc_result_t result;
@@ -1010,8 +1007,6 @@ get_reverse(char *reverse, size_t len, const char *value,
dns_name_t *name;
unsigned int options = 0;
if (ip6_int)
options |= DNS_BYADDROPT_IPV6INT;
name = dns_fixedname_initname(&fname);
result = dns_byaddr_createptrname(&addr, options, name);
CHECK("dns_byaddr_createptrname2", result);
@@ -1594,7 +1589,7 @@ dash_option(const char *option, char *next, struct query *query,
exit(0);
break;
case 'i':
query->ip6_int = true;
/* deprecated */
break;
case 'm':
/*
@@ -1674,7 +1669,7 @@ dash_option(const char *option, char *next, struct query *query,
query->rdtype = rdtype;
return (value_from_next);
case 'x':
get_reverse(textname, sizeof(textname), value, query->ip6_int);
get_reverse(textname, sizeof(textname), value);
strlcpy(query->textname, textname, sizeof(query->textname));
query->rdtype = dns_rdatatype_ptr;
query->rdclass = dns_rdataclass_in;
@@ -1788,7 +1783,6 @@ parse_args(bool is_batchfile, int argc, char **argv)
if (!is_batchfile) {
default_query.textname[0] = 0;
default_query.ip6_int = false;
default_query.recurse = true;
default_query.have_aaonly = false;
default_query.have_adflag = true; /*XXX*/
+1 -7
View File
@@ -420,11 +420,6 @@
a reverse lookup with the "PTR" query type.
</para>
<para>
The <option>-i</option> option sets the reverse domain for
IPv6 addresses to IP6.INT.
</para>
<para>
Reverse lookups &mdash; mapping addresses to names &mdash; are
simplified by the <option>-x</option> option.
@@ -434,8 +429,7 @@
query name like <literal>11.12.13.10.in-addr.arpa</literal> and
sets the query type and class to PTR and IN respectively.
By default, IPv6 addresses are looked up using nibble format
under the IP6.ARPA domain. To use the older RFC1886 method
using the IP6.INT domain specify the <option>-i</option> option.
under the IP6.ARPA domain.
</para>
<para>
+21
View File
@@ -75,6 +75,9 @@
/* Define to 1 if you have the <cmocka.h> header file. */
#undef HAVE_CMOCKA_H
/* Define to 1 if you have the `cpuset_setaffinty' function. */
#undef HAVE_CPUSET_SETAFFINITY
/* Define to 1 if you have the `CRYPTO_zalloc' function. */
#undef HAVE_CRYPTO_ZALLOC
@@ -285,6 +288,9 @@
/* define if OpenSSL supports Ed25519 */
#undef HAVE_OPENSSL_ED25519
/* Define to 1 if you have the `processor_bind' function. */
#undef HAVE_PROCESSOR_BIND
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
@@ -303,6 +309,9 @@
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
/* Define to 1 if you have the `pthread_setaffinity_np' function. */
#undef HAVE_PTHREAD_SETAFFINITY_NP
/* Define to 1 if you have the `pthread_setname_np' function. */
#undef HAVE_PTHREAD_SETNAME_NP
@@ -333,6 +342,9 @@
/* Define to 1 if you have the <sched.h> header file. */
#undef HAVE_SCHED_H
/* Define to 1 if you have the `sched_setaffinity' function. */
#undef HAVE_SCHED_SETAFFINITY
/* Define to 1 if you have the `sched_yield' function. */
#undef HAVE_SCHED_YIELD
@@ -387,6 +399,9 @@
/* Define to 1 if you have the <sys/capability.h> header file. */
#undef HAVE_SYS_CAPABILITY_H
/* Define to 1 if you have the <sys/cpuset.h> header file. */
#undef HAVE_SYS_CPUSET_H
/* Define to 1 if you have the <sys/devpoll.h> header file. */
#undef HAVE_SYS_DEVPOLL_H
@@ -396,6 +411,12 @@
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
/* Define to 1 if you have the <sys/procset.h> header file. */
#undef HAVE_SYS_PROCSET_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
Vendored
+62 -27
View File
@@ -844,6 +844,7 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -1003,6 +1004,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1255,6 +1257,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1392,7 +1403,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1545,6 +1556,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -12140,7 +12152,7 @@ done
if test "${with_python+set}" = set; then :
withval=$with_python; use_python="$withval"
else
use_python="unspec"
use_python="yes"
fi
@@ -12174,9 +12186,9 @@ $as_echo_n "checking for python support... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
$as_echo "disabled" >&6; }
;;
unspec|yes|*)
yes|*)
case "$use_python" in
unspec|yes|'')
yes|'')
for p in $python
do
for ac_prog in $p
@@ -12278,30 +12290,16 @@ $as_echo "not found" >&6; }
unset PYTHON
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python support" >&5
$as_echo_n "checking for python support... " >&6; }
if test "X$PYTHON" != "X"
then
case "$use_python_install_dir" in
unspec)
PYTHON_INSTALL_DIR=""
PYTHON_INSTALL_LIB=""
;;
*)
PYTHON_INSTALL_DIR="$use_python_install_dir"
PYTHON_INSTALL_LIB="--install-lib=$use_python_install_dir"
;;
esac
PYTHON_INSTALL_DIR="$use_python_install_dir"
PYTHON_INSTALL_LIB="--install-lib=$use_python_install_dir"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for python support" >&5
$as_echo_n "checking for python support... " >&6; }
case "$use_python" in
unspec)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
$as_echo "disabled" >&6; }
;;
yes)
as_fn_error $? "missing python" "$LINENO" 5
;;
esac
as_fn_error $? "no; python required for dnssec-keymgr" "$LINENO" 5
fi
;;
*)
@@ -15249,6 +15247,43 @@ fi
done
for ac_header in sys/cpuset.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "sys/cpuset.h" "ac_cv_header_sys_cpuset_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_cpuset_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_CPUSET_H 1
_ACEOF
fi
done
for ac_header in sys/procset.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "sys/procset.h" "ac_cv_header_sys_procset_h" "$ac_includes_default"
if test "x$ac_cv_header_sys_procset_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_PROCSET_H 1
_ACEOF
fi
done
for ac_func in pthread_setaffinity_np cpuset_setaffinity processor_bind sched_setaffinity
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
# Look for functions relating to thread naming
for ac_func in pthread_setname_np pthread_set_name_np
do :
@@ -23969,7 +24004,7 @@ report() {
echo " DNS Response Policy Service interface (--enable-dnsrps)"
test "yes" = "$enable_fixed" && \
echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)"
test "yes" = "$want_backtrace" && \
test "yes" = "$enable_backtrace" && \
echo " Print backtrace on crash (--enable-backtrace)"
test "minimal" = "$want_symtable" && \
echo " Use symbol table for backtrace, named only (--enable-symtable)"
@@ -24027,7 +24062,7 @@ report() {
echo " Using PKCS#11 for Public-Key Cryptography (--without-native-pkcs11)"
)
test "yes" = "$want_backtrace" || \
test "yes" = "$enable_backtrace" || \
echo " Print backtrace on crash (--enable-backtrace)"
test "yes" = "$want_querytrace" || \
echo " Very verbose query trace logging (--enable-querytrace)"
+15 -25
View File
@@ -184,7 +184,7 @@ AC_SUBST(PERL)
AC_ARG_WITH(python,
AS_HELP_STRING([--with-python=PATH],
[specify path to python interpreter]),
use_python="$withval", use_python="unspec")
use_python="$withval", use_python="yes")
AC_ARG_WITH(python-install-dir,
AS_HELP_STRING([--with-python-install-dir=PATH],
[installation directory for Python modules]),
@@ -208,11 +208,11 @@ if (sys.version_info < (2,7)) or (sys.version_info < (3,2) and sys.version_info
case "$use_python" in
no)
AC_MSG_CHECKING([for python support])
AC_MSG_RESULT(disabled)
AC_MSG_RESULT([disabled])
;;
unspec|yes|*)
yes|*)
case "$use_python" in
unspec|yes|'')
yes|'')
for p in $python
do
AC_PATH_PROGS(PYTHON, $p)
@@ -258,28 +258,14 @@ case "$use_python" in
unset PYTHON
fi
done
AC_MSG_CHECKING([for python support])
if test "X$PYTHON" != "X"
then
case "$use_python_install_dir" in
unspec)
PYTHON_INSTALL_DIR=""
PYTHON_INSTALL_LIB=""
;;
*)
PYTHON_INSTALL_DIR="$use_python_install_dir"
PYTHON_INSTALL_LIB="--install-lib=$use_python_install_dir"
;;
esac
PYTHON_INSTALL_DIR="$use_python_install_dir"
PYTHON_INSTALL_LIB="--install-lib=$use_python_install_dir"
AC_MSG_RESULT([yes])
else
AC_MSG_CHECKING([for python support])
case "$use_python" in
unspec)
AC_MSG_RESULT(disabled)
;;
yes)
AC_MSG_ERROR([missing python])
;;
esac
AC_MSG_ERROR([no; python required for dnssec-keymgr])
fi
;;
*)
@@ -715,6 +701,10 @@ AC_CHECK_HEADERS([sched.h])
AC_SEARCH_LIBS([sched_yield],[rt])
AC_CHECK_FUNCS([sched_yield pthread_yield pthread_yield_np])
AC_CHECK_HEADERS([sys/cpuset.h])
AC_CHECK_HEADERS([sys/procset.h])
AC_CHECK_FUNCS([pthread_setaffinity_np cpuset_setaffinity processor_bind sched_setaffinity])
# Look for functions relating to thread naming
AC_CHECK_FUNCS([pthread_setname_np pthread_set_name_np])
AC_CHECK_HEADERS([pthread_np.h], [], [], [#include <pthread.h>])
@@ -3225,7 +3215,7 @@ report() {
echo " DNS Response Policy Service interface (--enable-dnsrps)"
test "yes" = "$enable_fixed" && \
echo " Allow 'fixed' rrset-order (--enable-fixed-rrset)"
test "yes" = "$want_backtrace" && \
test "yes" = "$enable_backtrace" && \
echo " Print backtrace on crash (--enable-backtrace)"
test "minimal" = "$want_symtable" && \
echo " Use symbol table for backtrace, named only (--enable-symtable)"
@@ -3283,7 +3273,7 @@ report() {
echo " Using PKCS#11 for Public-Key Cryptography (--without-native-pkcs11)"
)
test "yes" = "$want_backtrace" || \
test "yes" = "$enable_backtrace" || \
echo " Print backtrace on crash (--enable-backtrace)"
test "yes" = "$want_querytrace" || \
echo " Very verbose query trace logging (--enable-querytrace)"
+26
View File
@@ -131,6 +131,15 @@
<section xml:id="relnotes_features"><info><title>New Features</title></info>
<itemizedlist>
<listitem>
<para>
Task manager and socket code have been substantially modified.
The manager uses per-cpu queues for tasks and network stack runs
multiple event loops in CPU-affinitive threads. This greatly
improves performance on large systems, especially when using
multi-queue NICs.
</para>
</listitem>
<listitem>
<para>
A new secondary zone option, <command>mirror</command>,
@@ -496,6 +505,16 @@
<command>allow-query-cache</command> work. [GL #319]
</para>
</listitem>
<listitem>
<para>
When compiled with IDN support, the <command>dig</command> and the
<command>nslookup</command> commands now disable IDN processing when
the standard output is not a tty (e.g. not used by human). The command
line options +idnin and +idnout need to be used to enable IDN
processing when <command>dig</command> or <command>nslookup</command>
is used from the shell scripts.
</para>
</listitem>
</itemizedlist>
</section>
@@ -537,6 +556,13 @@
added. This has been fixed. [GL #105]
</para>
</listitem>
<listitem>
<para>
The view name is now included in the output of
<command>rndc nta -dump</command>, for consistency with
other options. [GL !816]
</para>
</listitem>
<listitem>
<para>
<command>named</command> now rejects excessively large
+2 -5
View File
@@ -55,6 +55,7 @@ dns_byaddr_createptrname(const isc_netaddr_t *address, unsigned int options,
unsigned int len;
REQUIRE(address != NULL);
UNUSED(options);
/*
* We create the text representation and then convert to a
@@ -81,11 +82,7 @@ dns_byaddr_createptrname(const isc_netaddr_t *address, unsigned int options,
*cp++ = '.';
}
remaining = sizeof(textname) - (cp - textname);
if ((options & DNS_BYADDROPT_IPV6INT) != 0) {
strlcpy(cp, "ip6.int.", remaining);
} else {
strlcpy(cp, "ip6.arpa.", remaining);
}
strlcpy(cp, "ip6.arpa.", remaining);
} else
return (ISC_R_NOTIMPLEMENTED);
+1 -1
View File
@@ -461,7 +461,7 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx,
client->timermgr = timermgr;
client->task = NULL;
result = isc_task_create(client->taskmgr, 0, &client->task);
result = isc_task_create(client->taskmgr, 50, &client->task);
if (result != ISC_R_SUCCESS)
goto cleanup;
+53 -32
View File
@@ -299,7 +299,8 @@ static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr,
isc_socketmgr_t *sockmgr,
const isc_sockaddr_t *localaddr,
isc_socket_t **sockp,
isc_socket_t *dup_socket);
isc_socket_t *dup_socket,
bool duponly);
static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr,
@@ -317,7 +318,7 @@ static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
static isc_result_t open_socket(isc_socketmgr_t *mgr,
const isc_sockaddr_t *local,
unsigned int options, isc_socket_t **sockp,
isc_socket_t *dup_socket);
isc_socket_t *dup_socket, bool duponly);
static bool portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
isc_sockaddr_t *sockaddrp);
@@ -728,7 +729,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
if (portentry != NULL)
bindoptions |= ISC_SOCKET_REUSEADDRESS;
result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
NULL);
NULL, false);
if (result == ISC_R_SUCCESS) {
if (portentry == NULL) {
portentry = new_portentry(disp, port);
@@ -956,7 +957,6 @@ allocate_sevent(dns_dispatch_t *disp, isc_socket_t *sock,
free_sevent, disp->sepool);
ev->result = ISC_R_UNSET;
ISC_LINK_INIT(ev, ev_link);
ISC_LIST_INIT(ev->bufferlist);
ev->region.base = NULL;
ev->n = 0;
ev->offset = 0;
@@ -1668,7 +1668,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
static isc_result_t
open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
unsigned int options, isc_socket_t **sockp,
isc_socket_t *dup_socket)
isc_socket_t *dup_socket, bool duponly)
{
isc_socket_t *sock;
isc_result_t result;
@@ -1676,12 +1676,16 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
sock = *sockp;
if (sock != NULL) {
result = isc_socket_open(sock);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
return (result);
} else if (dup_socket != NULL) {
}
} else if (dup_socket != NULL &&
(!isc_socket_hasreuseport() || duponly))
{
result = isc_socket_dup(dup_socket, &sock);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
return (result);
}
isc_socket_setname(sock, "dispatcher", NULL);
*sockp = sock;
@@ -1689,8 +1693,9 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
} else {
result = isc_socket_create(mgr, isc_sockaddr_pf(local),
isc_sockettype_udp, &sock);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
return (result);
}
}
isc_socket_setname(sock, "dispatcher", NULL);
@@ -1700,9 +1705,9 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
#endif
result = isc_socket_bind(sock, local, options);
if (result != ISC_R_SUCCESS) {
if (*sockp == NULL)
if (*sockp == NULL) {
isc_socket_detach(&sock);
else {
} else {
isc_socket_close(sock);
}
return (result);
@@ -2504,7 +2509,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
disp->ntasks = 1;
disp->task[0] = NULL;
result = isc_task_create(taskmgr, 0, &disp->task[0]);
result = isc_task_create(taskmgr, 50, &disp->task[0]);
if (result != ISC_R_SUCCESS)
goto kill_socket;
@@ -2758,7 +2763,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
static isc_result_t
get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr,
isc_socket_t **sockp, isc_socket_t *dup_socket)
isc_socket_t **sockp, isc_socket_t *dup_socket, bool duponly)
{
unsigned int i, j;
isc_socket_t *held[DNS_DISPATCH_HELD];
@@ -2796,7 +2801,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
prt = ports[isc_random_uniform(nports)];
isc_sockaddr_setport(&localaddr_bound, prt);
result = open_socket(sockmgr, &localaddr_bound,
0, &sock, NULL);
0, &sock, NULL, false);
/*
* Continue if the port choosen is already in use
* or the OS has reserved it.
@@ -2817,7 +2822,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
/* Allow to reuse address for non-random ports. */
result = open_socket(sockmgr, localaddr,
ISC_SOCKET_REUSEADDRESS, &sock,
dup_socket);
dup_socket, duponly);
if (result == ISC_R_SUCCESS)
*sockp = sock;
@@ -2829,7 +2834,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
i = 0;
for (j = 0; j < 0xffffU; j++) {
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
result = open_socket(sockmgr, localaddr, 0, &sock, NULL, false);
if (result != ISC_R_SUCCESS)
goto end;
else if (portavailable(mgr, sock, NULL))
@@ -2873,22 +2878,27 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
dns_dispatch_t *disp;
isc_socket_t *sock = NULL;
int i = 0;
bool duponly = ((attributes & DNS_DISPATCHATTR_CANREUSE) == 0);
/* This is an attribute needed only at creation time */
attributes &= ~DNS_DISPATCHATTR_CANREUSE;
/*
* dispatch_allocate() checks mgr for us.
*/
disp = NULL;
result = dispatch_allocate(mgr, maxrequests, &disp);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
return (result);
}
disp->socktype = isc_sockettype_udp;
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock,
dup_socket);
if (result != ISC_R_SUCCESS)
dup_socket, duponly);
if (result != ISC_R_SUCCESS) {
goto deallocate_dispatch;
}
if (isc_log_wouldlog(dns_lctx, 90)) {
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
@@ -2911,38 +2921,45 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
*/
isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
if (sock != NULL)
result = open_socket(sockmgr, localaddr, 0,
&sock, NULL, false);
if (sock != NULL) {
isc_socket_detach(&sock);
if (result != ISC_R_SUCCESS)
}
if (result != ISC_R_SUCCESS) {
goto deallocate_dispatch;
}
}
disp->port_table = isc_mem_get(mgr->mctx,
sizeof(disp->port_table[0]) *
DNS_DISPATCH_PORTTABLESIZE);
if (disp->port_table == NULL)
if (disp->port_table == NULL) {
goto deallocate_dispatch;
for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++)
}
for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) {
ISC_LIST_INIT(disp->port_table[i]);
}
result = isc_mempool_create(mgr->mctx, sizeof(dispportentry_t),
&disp->portpool);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
goto deallocate_dispatch;
}
isc_mempool_setname(disp->portpool, "disp_portpool");
isc_mempool_setfreemax(disp->portpool, 128);
}
disp->socket = sock;
disp->local = *localaddr;
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
disp->ntasks = MAX_INTERNAL_TASKS;
else
} else {
disp->ntasks = 1;
}
for (i = 0; i < disp->ntasks; i++) {
disp->task[i] = NULL;
result = isc_task_create(taskmgr, 0, &disp->task[i]);
result = isc_task_create(taskmgr, 50, &disp->task[i]);
if (result != ISC_R_SUCCESS) {
while (--i >= 0) {
isc_task_shutdown(disp->task[i]);
@@ -2971,8 +2988,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
}
result = isc_mutex_init(&disp->sepool_lock);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
goto kill_sepool;
}
isc_mempool_setname(disp->sepool, "disp_sepool");
isc_mempool_setmaxalloc(disp->sepool, 32768);
@@ -2991,8 +3009,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); /* XXX */
if (disp->socket != NULL)
if (disp->socket != NULL) {
dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
}
*dispp = disp;
@@ -3006,11 +3025,13 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
kill_ctlevent:
isc_event_free(&disp->ctlevent);
kill_task:
for (i = 0; i < disp->ntasks; i++)
for (i = 0; i < disp->ntasks; i++) {
isc_task_detach(&disp->task[i]);
}
kill_socket:
if (disp->socket != NULL)
if (disp->socket != NULL) {
isc_socket_detach(&disp->socket);
}
deallocate_dispatch:
dispatch_free(&disp);
-9
View File
@@ -60,13 +60,6 @@ typedef struct dns_byaddrevent {
dns_namelist_t names;
} dns_byaddrevent_t;
/*
* This option is deprecated since we now only consider nibbles.
#define DNS_BYADDROPT_IPV6NIBBLE 0x0001
*/
/*% Note DNS_BYADDROPT_IPV6NIBBLE is now deprecated. */
#define DNS_BYADDROPT_IPV6INT 0x0002
isc_result_t
dns_byaddr_create(isc_mem_t *mctx, const isc_netaddr_t *address,
dns_view_t *view, unsigned int options, isc_task_t *task,
@@ -84,8 +77,6 @@ dns_byaddr_create(isc_mem_t *mctx, const isc_netaddr_t *address,
* 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.
* \endcode
*
*\li #DNS_BYADDROPT_IPV6INT can be used to get nibble lookups under ip6.int.
*
* Requires:
*
*\li 'mctx' is a valid mctx.
+1
View File
@@ -140,6 +140,7 @@ struct dns_dispatchset {
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
#define DNS_DISPATCHATTR_FIXEDID 0x00000100U
#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U
#define DNS_DISPATCHATTR_CANREUSE 0x00000400U
/*@}*/
/*
+3 -2
View File
@@ -182,9 +182,10 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
*/
isc_result_t
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf);
dns_ntatable_totext(dns_ntatable_t *ntatable, const char *view,
isc_buffer_t **buf);
/*%<
* Dump the NTA table to buffer at 'buf'
* Dump the NTA table to buffer at 'buf', with view names
*
* Requires:
* \li "ntatable" is a valid table.
+7 -3
View File
@@ -509,7 +509,9 @@ putstr(isc_buffer_t **b, const char *str) {
}
isc_result_t
dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
dns_ntatable_totext(dns_ntatable_t *ntatable, const char *view,
isc_buffer_t **buf)
{
isc_result_t result;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
@@ -552,8 +554,10 @@ dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
isc_time_formattimestamp(&t, tbuf,
sizeof(tbuf));
snprintf(obuf, sizeof(obuf), "%s%s: %s %s",
snprintf(obuf, sizeof(obuf), "%s%s%s%s: %s %s",
first ? "" : "\n", nbuf,
view != NULL ? "/" : "",
view != NULL ? view : "",
n->expiry <= now
? "expired"
: "expiry",
@@ -588,7 +592,7 @@ dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
if (result != ISC_R_SUCCESS)
return (result);
result = dns_ntatable_totext(ntatable, &text);
result = dns_ntatable_totext(ntatable, NULL, &text);
if (isc_buffer_usedlength(text) != 0) {
(void) putstr(&text, "\n");
+42 -8
View File
@@ -586,7 +586,7 @@ static void resquery_response(isc_task_t *task, isc_event_t *event);
static void resquery_connected(isc_task_t *task, isc_event_t *event);
static void fctx_try(fetchctx_t *fctx, bool retrying,
bool badcache);
void fctx_minimize_qname(fetchctx_t *fctx);
static isc_result_t fctx_minimize_qname(fetchctx_t *fctx);
static void fctx_destroy(fetchctx_t *fctx);
static bool fctx_unlink(fetchctx_t *fctx);
static isc_result_t ncache_adderesult(dns_message_t *message,
@@ -4142,7 +4142,23 @@ resume_qmin(isc_task_t *task, isc_event_t *event) {
}
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = true;
fctx_minimize_qname(fctx);
result = fctx_minimize_qname(fctx);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, result, __LINE__);
goto cleanup;
}
if (!fctx->minimized) {
/*
* We have finished minimizing, but fctx->finds was filled at
* the beginning of the run - now we need to clear it before
* sending the final query to use proper nameservers.
*/
fctx_cancelqueries(fctx, false, false);
fctx_cleanupall(fctx);
}
fctx_try(fctx, true, false);
cleanup:
@@ -4894,7 +4910,10 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
fctx->ip6arpaskip =
(options & DNS_FETCHOPT_QMIN_SKIP_IP6A) != 0 &&
dns_name_issubdomain(&fctx->name, &ip6_arpa);
fctx_minimize_qname(fctx);
result = fctx_minimize_qname(fctx);
if (result != ISC_R_SUCCESS) {
goto cleanup_mctx;
}
}
ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
@@ -4908,6 +4927,13 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
return (ISC_R_SUCCESS);
cleanup_mctx:
fctx->magic = 0;
isc_mem_detach(&fctx->mctx);
dns_adb_detach(&fctx->adb);
dns_db_detach(&fctx->cache);
isc_timer_detach(&fctx->timer);
cleanup_rmessage:
dns_message_destroy(&fctx->rmessage);
@@ -10320,19 +10346,24 @@ log_fetch(const dns_name_t *name, dns_rdatatype_t type) {
"fetch: %s/%s", namebuf, typebuf);
}
void
static isc_result_t
fctx_minimize_qname(fetchctx_t *fctx) {
isc_result_t result;
unsigned int dlabels, nlabels;
REQUIRE(VALID_FCTX(fctx));
dlabels = dns_name_countlabels(&fctx->qmindcname);
nlabels = dns_name_countlabels(&fctx->name);
dns_name_free(&fctx->qminname, fctx->mctx);
dns_name_init(&fctx->qminname, NULL);
if (dlabels > fctx->qmin_labels) {
fctx->qmin_labels = dlabels+1;
fctx->qmin_labels = dlabels + 1;
} else {
fctx->qmin_labels++;
}
if (fctx->ip6arpaskip) {
/*
* For ip6.arpa we want to skip some of the labels, with
@@ -10357,6 +10388,7 @@ fctx_minimize_qname(fetchctx_t *fctx) {
} else if (fctx->qmin_labels > DNS_QMIN_MAXLABELS) {
fctx->qmin_labels = DNS_MAX_LABELS + 1;
}
if (fctx->qmin_labels < nlabels) {
/*
* We want to query for qmin_labels from fctx->name
@@ -10366,16 +10398,18 @@ fctx_minimize_qname(fetchctx_t *fctx) {
dns_name_split(&fctx->name,
fctx->qmin_labels,
NULL, dns_fixedname_name(&fname));
dns_name_dup(dns_fixedname_name(&fname), fctx->mctx,
&fctx->qminname);
result = dns_name_dup(dns_fixedname_name(&fname), fctx->mctx,
&fctx->qminname);
fctx->qmintype = dns_rdatatype_ns;
fctx->minimized = true;
} else {
/* Minimization is done, we'll ask for whole qname */
fctx->qmintype = fctx->type;
dns_name_dup(&fctx->name, fctx->mctx, &fctx->qminname);
result = dns_name_dup(&fctx->name, fctx->mctx, &fctx->qminname);
fctx->minimized = false;
}
return (result);
}
isc_result_t
+19 -30
View File
@@ -114,9 +114,9 @@ struct isc_httpd {
* compressed HTTP data, if compression is used.
*
*/
isc_bufferlist_t bufflist;
isc_buffer_t headerbuffer;
isc_buffer_t compbuffer;
isc_buffer_t *sendbuffer;
const char *mimetype;
unsigned int retcode;
@@ -667,10 +667,9 @@ isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
}
isc_buffer_init(&httpd->headerbuffer, headerdata, HTTP_SENDGROW);
ISC_LIST_INIT(httpd->bufflist);
isc_buffer_initnull(&httpd->compbuffer);
isc_buffer_initnull(&httpd->bodybuffer);
httpd->sendbuffer = NULL;
reset_client(httpd);
r.base = (unsigned char *)httpd->recvbuf;
@@ -840,12 +839,13 @@ isc_httpd_compress(isc_httpd_t *httpd) {
static void
isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
isc_region_t r;
isc_result_t result;
isc_httpd_t *httpd = ev->ev_arg;
isc_socketevent_t *sev = (isc_socketevent_t *)ev;
isc_buffer_t *databuffer;
isc_httpdurl_t *url;
isc_time_t now;
isc_region_t r;
bool is_compressed = false;
char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
@@ -963,22 +963,24 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
isc_httpd_endheaders(httpd); /* done */
ISC_LIST_APPEND(httpd->bufflist, &httpd->headerbuffer, link);
/*
* Link the data buffer into our send queue, should we have any data
* rendered into it. If no data is present, we won't do anything
* with the buffer.
* Append either the compressed or the non-compressed response body to
* the response headers and store the result in httpd->sendbuffer.
*/
if (is_compressed == true) {
ISC_LIST_APPEND(httpd->bufflist, &httpd->compbuffer, link);
} else {
if (isc_buffer_length(&httpd->bodybuffer) > 0) {
ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);
}
}
isc_buffer_dup(httpd->mgr->mctx,
&httpd->sendbuffer, &httpd->headerbuffer);
isc_buffer_setautorealloc(httpd->sendbuffer, true);
databuffer = (is_compressed ? &httpd->compbuffer : &httpd->bodybuffer);
isc_buffer_usedregion(databuffer, &r);
result = isc_buffer_copyregion(httpd->sendbuffer, &r);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
/*
* Determine total response size.
*/
isc_buffer_usedregion(httpd->sendbuffer, &r);
/* check return code? */
(void)isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
(void)isc_socket_send(httpd->sock, &r, task,
isc_httpd_senddone, httpd);
out:
@@ -1126,13 +1128,7 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
ENTER("senddone");
INSIST(ISC_HTTPD_ISSEND(httpd));
/*
* First, unlink our header buffer from the socket's bufflist. This
* is sort of an evil hack, since we know our buffer will be there,
* and we know it's address, so we can just remove it directly.
*/
NOTICE("senddone unlinked header");
ISC_LIST_UNLINK(sev->bufferlist, &httpd->headerbuffer, link);
isc_buffer_free(&httpd->sendbuffer);
/*
* We will always want to clean up our receive buffer, even if we
@@ -1149,13 +1145,6 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
}
NOTICE("senddone free callback performed");
}
if (ISC_LINK_LINKED(&httpd->bodybuffer, link)) {
ISC_LIST_UNLINK(sev->bufferlist, &httpd->bodybuffer, link);
NOTICE("senddone body buffer unlinked");
} else if (ISC_LINK_LINKED(&httpd->compbuffer, link)) {
ISC_LIST_UNLINK(sev->bufferlist, &httpd->compbuffer, link);
NOTICE("senddone compressed data unlinked and freed");
}
if (sev->result != ISC_R_SUCCESS) {
destroy_client(&httpd);
-2
View File
@@ -16,8 +16,6 @@
#pragma once
#include <config.h>
#include <isc/lang.h>
#include <isc/md.h>
#include <isc/platform.h>
-2
View File
@@ -16,8 +16,6 @@
#pragma once
#include <config.h>
#include <isc/lang.h>
#include <isc/platform.h>
#include <isc/types.h>
+8 -123
View File
@@ -204,7 +204,6 @@ struct isc_socketevent {
unsigned int n; /*%< bytes read or written */
unsigned int offset; /*%< offset into buffer list */
isc_region_t region; /*%< for single-buffer i/o */
isc_bufferlist_t bufferlist; /*%< list of buffers */
isc_sockaddr_t address; /*%< source address */
isc_time_t timestamp; /*%< timestamp of packet recv */
struct in6_pktinfo pktinfo; /*%< ipv6 pktinfo */
@@ -244,8 +243,7 @@ typedef enum {
isc_sockettype_udp = 1,
isc_sockettype_tcp = 2,
isc_sockettype_unix = 3,
isc_sockettype_fdwatch = 4,
isc_sockettype_raw = 5
isc_sockettype_raw = 4
} isc_sockettype_t;
/*@{*/
@@ -276,14 +274,6 @@ typedef enum {
#define ISC_SOCKFLAG_NORETRY 0x00000002 /*%< drop failed UDP sends */
/*@}*/
/*@{*/
/*!
* Flags for fdwatchcreate.
*/
#define ISC_SOCKFDWATCH_READ 0x00000001 /*%< watch for readable */
#define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */
/*@}*/
/*%
* This structure is actually just the common prefix of a socket manager
* object implementation's version of an isc_socketmgr_t.
@@ -330,76 +320,6 @@ struct isc_socket {
*** those functions which return an isc_result.
***/
isc_result_t
isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
int fd,
int flags,
isc_sockfdwatch_t callback,
void *cbarg,
isc_task_t *task,
isc_socket_t **socketp);
/*%<
* Create a new file descriptor watch socket managed by 'manager'.
*
* Note:
*
*\li 'fd' is the already-opened file descriptor (must be less
* than maxsockets).
*\li This function is not available on Windows.
*\li The callback function is called "in-line" - this means the function
* needs to return as fast as possible, as all other I/O will be suspended
* until the callback completes.
*
* Requires:
*
*\li 'manager' is a valid manager
*
*\li 'socketp' is a valid pointer, and *socketp == NULL
*
*\li 'fd' be opened.
*
* Ensures:
*
* '*socketp' is attached to the newly created fdwatch socket
*
* Returns:
*
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
*\li #ISC_R_NORESOURCES
*\li #ISC_R_UNEXPECTED
*\li #ISC_R_RANGE
*/
isc_result_t
isc_socket_fdwatchpoke(isc_socket_t *sock,
int flags);
/*%<
* Poke a file descriptor watch socket informing the manager that it
* should restart watching the socket
*
* Note:
*
*\li 'sock' is the socket returned by isc_socket_fdwatchcreate
*
*\li 'flags' indicates what the manager should watch for on the socket
* in addition to what it may already be watching. It can be one or
* both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE. To
* temporarily disable watching on a socket the value indicating
* no more data should be returned from the call back routine.
*
*\li This function is not available on Windows.
*
* Requires:
*
*\li 'sock' is a valid isc socket
*
*
* Returns:
*
*\li #ISC_R_SUCCESS
*/
isc_result_t
isc_socket_create(isc_socketmgr_t *manager,
int pf,
@@ -408,9 +328,6 @@ isc_socket_create(isc_socketmgr_t *manager,
/*%<
* Create a new 'type' socket managed by 'manager'.
*
* For isc_sockettype_fdwatch sockets you should use isc_socket_fdwatchcreate()
* rather than isc_socket_create().
*
* Note:
*
*\li 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6.
@@ -421,8 +338,6 @@ isc_socket_create(isc_socketmgr_t *manager,
*
*\li 'socketp' is a valid pointer, and *socketp == NULL
*
*\li 'type' is not isc_sockettype_fdwatch
*
* Ensures:
*
* '*socketp' is attached to the newly created socket
@@ -552,17 +467,12 @@ isc_socket_open(isc_socket_t *sock);
* one. This optimization may not be available for some systems, in which
* case this function will return ISC_R_NOTIMPLEMENTED and must not be used.
*
* isc_socket_open() should not be called on sockets created by
* isc_socket_fdwatchcreate().
*
* Requires:
*
* \li there must be no other reference to this socket.
*
* \li 'socket' is a valid and previously closed by isc_socket_close()
*
* \li 'sock->type' is not isc_sockettype_fdwatch
*
* Returns:
* Same as isc_socket_create().
* \li ISC_R_NOTIMPLEMENTED
@@ -578,9 +488,6 @@ isc_socket_close(isc_socket_t *sock);
* systems, in which case this function will return ISC_R_NOTIMPLEMENTED and
* must not be used.
*
* isc_socket_close() should not be called on sockets created by
* isc_socket_fdwatchcreate().
*
* Requires:
*
* \li The socket must have a valid descriptor.
@@ -589,8 +496,6 @@ isc_socket_close(isc_socket_t *sock);
*
* \li There must be no pending I/O requests.
*
* \li 'sock->type' is not isc_sockettype_fdwatch
*
* Returns:
* \li #ISC_R_NOTIMPLEMENTED
*/
@@ -742,10 +647,6 @@ isc_result_t
isc_socket_recv(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum,
isc_task_t *task, isc_taskaction_t action, void *arg);
isc_result_t
isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
unsigned int minimum,
isc_task_t *task, isc_taskaction_t action, void *arg);
isc_result_t
isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
@@ -775,11 +676,6 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
* into this function, or any data they refer to until the completion
* event is received.
*
*\li For isc_socket_recvv():
* On successful completion, '*buflist' will be empty, and the list of
* all buffers will be returned in the done event's 'bufferlist'
* member. On error return, '*buflist' will be unchanged.
*
*\li For isc_socket_recv2():
* 'event' is not NULL, and the non-socket specific fields are
* expected to be initialized.
@@ -834,18 +730,6 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_taskaction_t action, void *arg,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
isc_result_t
isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, void *arg);
isc_result_t
isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, void *arg,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
isc_result_t
isc_socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, void *arg,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
unsigned int flags);
isc_result_t
isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
@@ -866,11 +750,6 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
* into this function, or any data they refer to until the completion
* event is received.
*
*\li For isc_socket_sendv() and isc_socket_sendtov():
* On successful completion, '*buflist' will be empty, and the list of
* all buffers will be returned in the done event's 'bufferlist'
* member. On error return, '*buflist' will be unchanged.
*
*\li For isc_socket_sendto2():
* 'event' is not NULL, and the non-socket specific fields are
* expected to be initialized.
@@ -934,7 +813,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
isc_result_t
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
unsigned int maxsocks);
unsigned int maxsocks, int nthreads);
/*%<
* Create a socket manager. If "maxsocks" is non-zero, it specifies the
* maximum number of sockets that the created manager should handle.
@@ -1131,6 +1010,12 @@ isc_socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp);
* Test interface. Drop UDP packet > 'maxudp'.
*/
bool
isc_socket_hasreuseport(void);
/*%<
* Return true if there is SO_REUSEPORT support
*/
#ifdef HAVE_LIBXML2
int
isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer);
-2
View File
@@ -13,8 +13,6 @@
/*! \file isc/strerr.h */
#include <config.h>
#include <string.h>
#if defined(strerror_r)
+11 -3
View File
@@ -208,8 +208,12 @@ isc_task_detach(isc_task_t **taskp);
void
isc_task_send(isc_task_t *task, isc_event_t **eventp);
void
isc_task_sendto(isc_task_t *task, isc_event_t **eventp, int c);
/*%<
* Send '*event' to 'task'.
* Send '*event' to 'task', if task is idle try starting it on cpu 'c'
* If 'c' is smaller than 0 then cpu is selected randomly.
*
* Requires:
*
@@ -221,11 +225,15 @@ isc_task_send(isc_task_t *task, isc_event_t **eventp);
*\li *eventp == NULL.
*/
void
isc_task_sendtoanddetach(isc_task_t **taskp, isc_event_t **eventp, int c);
void
isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
/*%<
* Send '*event' to '*taskp' and then detach '*taskp' from its
* task.
* task. If task is idle try starting it on cpu 'c'
* If 'c' is smaller than 0 then cpu is selected randomly.
*
* Requires:
*
@@ -666,7 +674,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
*/
void
isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
isc_taskmgr_setprivilegedmode(isc_taskmgr_t *manager);
isc_taskmgrmode_t
isc_taskmgr_mode(isc_taskmgr_t *manager);
+3
View File
@@ -44,6 +44,9 @@ isc_thread_yield(void);
void
isc_thread_setname(isc_thread_t thread, const char *name);
isc_result_t
isc_thread_setaffinity(int cpu);
/* XXX We could do fancier error handling... */
#define isc_thread_join(t, rp) \
+41
View File
@@ -18,6 +18,17 @@
#include <sched.h>
#endif
#if defined(HAVE_CPUSET_H)
#include <sys/param.h>
#include <sys/cpuset.h>
#endif
#if defined(HAVE_SYS_PROCSET_H)
#include <sys/types.h>
#include <sys/processor.h>
#include <sys/procset.h>
#endif
#include <isc/thread.h>
#include <isc/util.h>
@@ -91,3 +102,33 @@ isc_thread_yield(void) {
pthread_yield_np();
#endif
}
isc_result_t
isc_thread_setaffinity(int cpu) {
#if defined(HAVE_CPUSET_SETAFFINITY)
cpuset_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1,
sizeof(cpuset), &cpuset) != 0)
{
return (ISC_R_FAILURE);
}
#elif defined(HAVE_PTHREAD_SETAFFINITY_NP)
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(cpu, &set);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t),
&set) != 0)
{
return (ISC_R_FAILURE);
}
#elif defined(HAVE_PROCESSOR_BIND)
if (processor_bind(P_LWPID, P_MYID, cpu, NULL) != 0) {
return (ISC_R_FAILURE);
}
#else
UNUSED(cpu);
#endif
return (ISC_R_SUCCESS);
}
+324 -209
View File
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <isc/app.h>
#include <isc/atomic.h>
#include <isc/condition.h>
#include <isc/event.h>
#include <isc/json.h>
@@ -31,6 +32,7 @@
#include <isc/platform.h>
#include <isc/print.h>
#include <isc/string.h>
#include <isc/random.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <isc/time.h>
@@ -41,18 +43,14 @@
#include <openssl/err.h>
#endif
/*%
* For BIND9 internal applications:
* when built with threads we use multiple worker threads shared by the whole
* application.
* when built without threads we share a single global task manager and use
* an integrated event loop for socket, timer, and other generic task events.
* For generic library:
* we don't use either of them: an application can have multiple task managers
* whether or not it's threaded, and if the application is threaded each thread
* is expected to have a separate manager; no "worker threads" are shared by
* the application threads.
/*
* Task manager is built around 'as little locking as possible' concept.
* Each thread has his own queue of tasks to be run, if a task is in running
* state it will stay on the runner it's currently on, if a task is in idle
* state it can be woken up on a specific runner with isc_task_sendto - that
* helps with data locality on CPU.
*/
#ifdef ISC_TASK_TRACE
#define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
task, isc_thread_self(), (m))
@@ -86,6 +84,7 @@ static const char *statenames[] = {
typedef struct isc__task isc__task_t;
typedef struct isc__taskmgr isc__taskmgr_t;
typedef struct isc__taskqueue isc__taskqueue_t;
struct isc__task {
/* Not locked. */
@@ -104,6 +103,7 @@ struct isc__task {
isc_time_t tnow;
char name[16];
void * tag;
unsigned int threadid;
/* Locked by task manager lock. */
LINK(isc__task_t) link;
LINK(isc__task_t) ready_link;
@@ -121,27 +121,40 @@ struct isc__task {
typedef ISC_LIST(isc__task_t) isc__tasklist_t;
struct isc__taskqueue {
/* Everything locked by lock */
isc_mutex_t lock;
isc__tasklist_t ready_tasks;
isc__tasklist_t ready_priority_tasks;
isc_condition_t work_available;
isc_thread_t thread;
unsigned int threadid;
isc__taskmgr_t *manager;
};
struct isc__taskmgr {
/* Not locked. */
isc_taskmgr_t common;
isc_mem_t * mctx;
isc_mutex_t lock;
isc_mutex_t halt_lock;
isc_condition_t halt_cond;
unsigned int workers;
isc_thread_t * threads;
atomic_uint_fast32_t tasks_running;
atomic_uint_fast32_t tasks_ready;
atomic_uint_fast32_t curq;
isc__taskqueue_t *queues;
/* Locked by task manager lock. */
unsigned int default_quantum;
LIST(isc__task_t) tasks;
isc__tasklist_t ready_tasks;
isc__tasklist_t ready_priority_tasks;
isc_taskmgrmode_t mode;
isc_condition_t work_available;
isc_condition_t exclusive_granted;
isc_condition_t paused;
unsigned int tasks_running;
unsigned int tasks_ready;
bool pause_requested;
bool exclusive_requested;
bool exiting;
bool pause_requested;
bool exclusive_requested;
bool exiting;
/* Locked by halt_lock */
unsigned int halted;
/*
* Multiple threads can read/write 'excl' at the same time, so we need
@@ -175,22 +188,33 @@ isc_taskmgr_setexcltask(isc_taskmgr_t *mgr0, isc_task_t *task0);
isc_result_t
isc_taskmgr_excltask(isc_taskmgr_t *mgr0, isc_task_t **taskp);
static inline bool
empty_readyq(isc__taskmgr_t *manager);
empty_readyq(isc__taskmgr_t *manager, int c);
static inline isc__task_t *
pop_readyq(isc__taskmgr_t *manager);
pop_readyq(isc__taskmgr_t *manager, int c);
static inline void
push_readyq(isc__taskmgr_t *manager, isc__task_t *task);
push_readyq(isc__taskmgr_t *manager, isc__task_t *task, int c);
static inline void
wake_all_queues(isc__taskmgr_t *manager);
/***
*** Tasks.
***/
static inline void
wake_all_queues(isc__taskmgr_t *manager) {
for (unsigned int i = 0; i < manager->workers; i++) {
LOCK(&manager->queues[i].lock);
BROADCAST(&manager->queues[i].work_available);
UNLOCK(&manager->queues[i].lock);
}
}
static void
task_finished(isc__task_t *task) {
isc__taskmgr_t *manager = task->manager;
REQUIRE(EMPTY(task->events));
REQUIRE(task->nevents == 0);
REQUIRE(EMPTY(task->on_shutdown));
@@ -201,6 +225,7 @@ task_finished(isc__task_t *task) {
LOCK(&manager->lock);
UNLINK(manager->tasks, task, link);
UNLOCK(&manager->lock);
if (FINISHED(manager)) {
/*
* All tasks have completed and the
@@ -208,10 +233,8 @@ task_finished(isc__task_t *task) {
* any idle worker threads so they
* can exit.
*/
BROADCAST(&manager->work_available);
wake_all_queues(manager);
}
UNLOCK(&manager->lock);
DESTROYLOCK(&task->lock);
task->common.impmagic = 0;
task->common.magic = 0;
@@ -235,6 +258,9 @@ isc_task_create(isc_taskmgr_t *manager0, unsigned int quantum,
return (ISC_R_NOMEMORY);
XTRACE("isc_task_create");
task->manager = manager;
task->threadid = atomic_fetch_add_explicit(&manager->curq, 1,
memory_order_relaxed)
% manager->workers;
result = isc_mutex_init(&task->lock);
if (result != ISC_R_SUCCESS) {
isc_mem_put(manager->mctx, task, sizeof(*task));
@@ -351,12 +377,12 @@ task_ready(isc__task_t *task) {
REQUIRE(task->state == task_state_ready);
XTRACE("task_ready");
LOCK(&manager->lock);
push_readyq(manager, task);
if (manager->mode == isc_taskmgrmode_normal || has_privilege)
SIGNAL(&manager->work_available);
UNLOCK(&manager->lock);
LOCK(&manager->queues[task->threadid].lock);
push_readyq(manager, task, task->threadid);
if (manager->mode == isc_taskmgrmode_normal || has_privilege) {
SIGNAL(&manager->queues[task->threadid].work_available);
}
UNLOCK(&manager->queues[task->threadid].lock);
}
static inline bool
@@ -414,7 +440,7 @@ isc_task_detach(isc_task_t **taskp) {
}
static inline bool
task_send(isc__task_t *task, isc_event_t **eventp) {
task_send(isc__task_t *task, isc_event_t **eventp, int c) {
bool was_idle = false;
isc_event_t *event;
@@ -433,6 +459,7 @@ task_send(isc__task_t *task, isc_event_t **eventp) {
if (task->state == task_state_idle) {
was_idle = true;
task->threadid = c;
INSIST(EMPTY(task->events));
task->state = task_state_ready;
}
@@ -447,6 +474,16 @@ task_send(isc__task_t *task, isc_event_t **eventp) {
void
isc_task_send(isc_task_t *task0, isc_event_t **eventp) {
isc_task_sendto(task0, eventp, -1);
}
void
isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
isc_task_sendtoanddetach(taskp, eventp, -1);
}
void
isc_task_sendto(isc_task_t *task0, isc_event_t **eventp, int c) {
isc__task_t *task = (isc__task_t *)task0;
bool was_idle;
@@ -455,16 +492,21 @@ isc_task_send(isc_task_t *task0, isc_event_t **eventp) {
*/
REQUIRE(VALID_TASK(task));
XTRACE("isc_task_send");
if (c < 0) {
c = atomic_fetch_add_explicit(&task->manager->curq, 1,
memory_order_relaxed);
}
c %= task->manager->workers;
/*
* We're trying hard to hold locks for as short a time as possible.
* We're also trying to hold as few locks as possible. This is why
* some processing is deferred until after the lock is released.
*/
LOCK(&task->lock);
was_idle = task_send(task, eventp);
was_idle = task_send(task, eventp, c);
UNLOCK(&task->lock);
if (was_idle) {
@@ -488,7 +530,7 @@ isc_task_send(isc_task_t *task0, isc_event_t **eventp) {
}
void
isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
isc_task_sendtoanddetach(isc_task_t **taskp, isc_event_t **eventp, int c) {
bool idle1, idle2;
isc__task_t *task;
@@ -500,11 +542,16 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
REQUIRE(taskp != NULL);
task = (isc__task_t *)*taskp;
REQUIRE(VALID_TASK(task));
XTRACE("isc_task_sendanddetach");
if (c < 0) {
c = atomic_fetch_add_explicit(&task->manager->curq, 1,
memory_order_relaxed);
}
c %= task->manager->workers;
LOCK(&task->lock);
idle1 = task_send(task, eventp);
idle1 = task_send(task, eventp, c);
idle2 = task_detach(task);
UNLOCK(&task->lock);
@@ -829,13 +876,13 @@ isc_task_getcurrenttimex(isc_task_t *task0, isc_time_t *t) {
* Caller must hold the task manager lock.
*/
static inline bool
empty_readyq(isc__taskmgr_t *manager) {
empty_readyq(isc__taskmgr_t *manager, int c) {
isc__tasklist_t queue;
if (manager->mode == isc_taskmgrmode_normal)
queue = manager->ready_tasks;
queue = manager->queues[c].ready_tasks;
else
queue = manager->ready_priority_tasks;
queue = manager->queues[c].ready_priority_tasks;
return (EMPTY(queue));
}
@@ -849,19 +896,21 @@ empty_readyq(isc__taskmgr_t *manager) {
* Caller must hold the task manager lock.
*/
static inline isc__task_t *
pop_readyq(isc__taskmgr_t *manager) {
pop_readyq(isc__taskmgr_t *manager, int c) {
isc__task_t *task;
if (manager->mode == isc_taskmgrmode_normal)
task = HEAD(manager->ready_tasks);
else
task = HEAD(manager->ready_priority_tasks);
if (manager->mode == isc_taskmgrmode_normal) {
task = HEAD(manager->queues[c].ready_tasks);
} else {
task = HEAD(manager->queues[c].ready_priority_tasks);
}
if (task != NULL) {
DEQUEUE(manager->ready_tasks, task, ready_link);
if (ISC_LINK_LINKED(task, ready_priority_link))
DEQUEUE(manager->ready_priority_tasks, task,
DEQUEUE(manager->queues[c].ready_tasks, task, ready_link);
if (ISC_LINK_LINKED(task, ready_priority_link)) {
DEQUEUE(manager->queues[c].ready_priority_tasks, task,
ready_priority_link);
}
}
return (task);
@@ -874,20 +923,26 @@ pop_readyq(isc__taskmgr_t *manager) {
* Caller must hold the task manager lock.
*/
static inline void
push_readyq(isc__taskmgr_t *manager, isc__task_t *task) {
ENQUEUE(manager->ready_tasks, task, ready_link);
if ((task->flags & TASK_F_PRIVILEGED) != 0)
ENQUEUE(manager->ready_priority_tasks, task,
push_readyq(isc__taskmgr_t *manager, isc__task_t *task, int c) {
ENQUEUE(manager->queues[c].ready_tasks, task, ready_link);
if ((task->flags & TASK_F_PRIVILEGED) != 0) {
ENQUEUE(manager->queues[c].ready_priority_tasks, task,
ready_priority_link);
manager->tasks_ready++;
}
atomic_fetch_add_explicit(&manager->tasks_ready, 1,
memory_order_acquire);
}
static void
dispatch(isc__taskmgr_t *manager) {
dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
isc__task_t *task;
REQUIRE(VALID_MANAGER(manager));
/* Wait for everything to initialize */
LOCK(&manager->lock);
UNLOCK(&manager->lock);
/*
* Again we're trying to hold the lock for as short a time as possible
* and to do as little locking and unlocking as possible.
@@ -937,8 +992,7 @@ dispatch(isc__taskmgr_t *manager) {
* For N iterations of the loop, this code does N+1 locks and N+1
* unlocks. The while expression is always protected by the lock.
*/
LOCK(&manager->lock);
LOCK(&manager->queues[threadid].lock);
while (!FINISHED(manager)) {
/*
@@ -951,13 +1005,26 @@ dispatch(isc__taskmgr_t *manager) {
* If a pause has been requested, don't do any work
* until it's been released.
*/
while ((empty_readyq(manager) || manager->pause_requested ||
manager->exclusive_requested) && !FINISHED(manager))
while ((empty_readyq(manager, threadid) &&
!manager->pause_requested &&
!manager->exclusive_requested) &&
!FINISHED(manager))
{
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_WAIT, "wait"));
WAIT(&manager->work_available, &manager->lock);
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_WAIT,
manager->pause_requested
? "paused" : "notpaused"));
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_WAIT,
manager->exclusive_requested
? "excreq" : "notexcreq"));
WAIT(&manager->queues[threadid].work_available,
&manager->queues[threadid].lock);
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
ISC_MSGSET_TASK,
ISC_MSG_AWAKE, "awake"));
@@ -965,7 +1032,42 @@ dispatch(isc__taskmgr_t *manager) {
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
ISC_MSG_WORKING, "working"));
task = pop_readyq(manager);
if (manager->pause_requested || manager->exclusive_requested) {
UNLOCK(&manager->queues[threadid].lock);
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
ISC_MSG_WORKING, "halting"));
/*
* Switching to exclusive mode is done as a
* 2-phase-lock, checking if we have to switch is
* done without any locks on pause_requested and
* exclusive_requested to save time - the worst
* thing that can happen is that we'll launch one
* task more and exclusive task will be postponed a
* bit.
*
* Broadcasting on halt_cond seems suboptimal, but
* exclusive tasks are rare enought that we don't
* care.
*/
LOCK(&manager->halt_lock);
manager->halted++;
BROADCAST(&manager->halt_cond);
while (manager->pause_requested ||
manager->exclusive_requested)
{
WAIT(&manager->halt_cond, &manager->halt_lock);
}
manager->halted--;
SIGNAL(&manager->halt_cond);
UNLOCK(&manager->halt_lock);
LOCK(&manager->queues[threadid].lock);
/* Restart the loop after */
continue;
}
task = pop_readyq(manager, threadid);
if (task != NULL) {
unsigned int dispatch_count = 0;
bool done = false;
@@ -976,19 +1078,23 @@ dispatch(isc__taskmgr_t *manager) {
INSIST(VALID_TASK(task));
/*
* Note we only unlock the manager lock if we actually
* have a task to do. We must reacquire the manager
* Note we only unlock the queue lock if we actually
* have a task to do. We must reacquire the queue
* lock before exiting the 'if (task != NULL)' block.
*/
manager->tasks_ready--;
manager->tasks_running++;
UNLOCK(&manager->lock);
UNLOCK(&manager->queues[threadid].lock);
RUNTIME_CHECK(
atomic_fetch_sub_explicit(&manager->tasks_ready,
1, memory_order_release) > 0);
atomic_fetch_add_explicit(&manager->tasks_running, 1,
memory_order_acquire);
LOCK(&task->lock);
INSIST(task->state == task_state_ready);
task->state = task_state_running;
XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_RUNNING, "running"));
XTRACE(task->name);
TIME_NOW(&task->tnow);
task->now = isc_time_seconds(&task->tnow);
do {
@@ -1004,6 +1110,7 @@ dispatch(isc__taskmgr_t *manager) {
ISC_MSGSET_TASK,
ISC_MSG_EXECUTE,
"execute action"));
XTRACE(task->name);
if (event->ev_action != NULL) {
UNLOCK(&task->lock);
(event->ev_action)(
@@ -1094,15 +1201,10 @@ dispatch(isc__taskmgr_t *manager) {
if (finished)
task_finished(task);
LOCK(&manager->lock);
manager->tasks_running--;
if (manager->exclusive_requested &&
manager->tasks_running == 1) {
SIGNAL(&manager->exclusive_granted);
} else if (manager->pause_requested &&
manager->tasks_running == 0) {
SIGNAL(&manager->paused);
}
RUNTIME_CHECK(
atomic_fetch_sub_explicit(&manager->tasks_running,
1, memory_order_release) > 0);
LOCK(&manager->queues[threadid].lock);
if (requeue) {
/*
* We know we're awake, so we don't have
@@ -1123,7 +1225,7 @@ dispatch(isc__taskmgr_t *manager) {
* were usually nonempty, the 'optimization'
* might even hurt rather than help.
*/
push_readyq(manager, task);
push_readyq(manager, task, threadid);
}
}
@@ -1133,27 +1235,62 @@ dispatch(isc__taskmgr_t *manager) {
* we're stuck. Automatically drop privileges at that
* point and continue with the regular ready queue.
*/
if (manager->tasks_running == 0 && empty_readyq(manager)) {
manager->mode = isc_taskmgrmode_normal;
if (!empty_readyq(manager))
BROADCAST(&manager->work_available);
if (manager->mode != isc_taskmgrmode_normal &&
atomic_load_explicit(&manager->tasks_running,
memory_order_acquire) == 0)
{
UNLOCK(&manager->queues[threadid].lock);
LOCK(&manager->lock);
/*
* Check once again, under lock. Mode can only
* change from privileged to normal anyway, and
* if we enter this loop twice at the same time
* we'll end up in a deadlock over queue locks.
*
*/
if (manager->mode != isc_taskmgrmode_normal &&
atomic_load_explicit(&manager->tasks_running,
memory_order_acquire) == 0)
{
bool empty = true;
unsigned int i;
for (i = 0; i < manager->workers && empty; i++)
{
LOCK(&manager->queues[i].lock);
empty &= empty_readyq(manager, i);
UNLOCK(&manager->queues[i].lock);
}
if (empty) {
manager->mode = isc_taskmgrmode_normal;
wake_all_queues(manager);
}
}
UNLOCK(&manager->lock);
LOCK(&manager->queues[threadid].lock);
}
}
UNLOCK(&manager->lock);
UNLOCK(&manager->queues[threadid].lock);
/*
* There might be other dispatchers waiting on empty tasks,
* wake them up.
*/
wake_all_queues(manager);
}
static isc_threadresult_t
#ifdef _WIN32
WINAPI
#endif
run(void *uap) {
isc__taskmgr_t *manager = uap;
run(void *queuep) {
isc__taskqueue_t *tq = queuep;
isc__taskmgr_t *manager = tq->manager;
int threadid = tq->threadid;
isc_thread_setaffinity(threadid);
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_STARTING, "starting"));
dispatch(manager);
dispatch(manager, threadid);
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_EXITING, "exiting"));
@@ -1167,27 +1304,23 @@ run(void *uap) {
static void
manager_free(isc__taskmgr_t *manager) {
isc_mem_t *mctx;
(void)isc_condition_destroy(&manager->exclusive_granted);
(void)isc_condition_destroy(&manager->work_available);
(void)isc_condition_destroy(&manager->paused);
isc_mem_free(manager->mctx, manager->threads);
for (unsigned int i = 0; i < manager->workers; i++) {
DESTROYLOCK(&manager->queues[i].lock);
}
DESTROYLOCK(&manager->lock);
DESTROYLOCK(&manager->excl_lock);
DESTROYLOCK(&manager->halt_lock);
isc_mem_put(manager->mctx, manager->queues,
manager->workers * sizeof(isc__taskqueue_t));
manager->common.impmagic = 0;
manager->common.magic = 0;
mctx = manager->mctx;
isc_mem_put(mctx, manager, sizeof(*manager));
isc_mem_detach(&mctx);
isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager));
}
isc_result_t
isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
unsigned int default_quantum, isc_taskmgr_t **managerp)
{
isc_result_t result;
unsigned int i, started = 0;
unsigned int i;
isc__taskmgr_t *manager;
/*
@@ -1198,64 +1331,35 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
REQUIRE(managerp != NULL && *managerp == NULL);
manager = isc_mem_get(mctx, sizeof(*manager));
if (manager == NULL)
return (ISC_R_NOMEMORY);
RUNTIME_CHECK(manager != NULL);
manager->common.impmagic = TASK_MANAGER_MAGIC;
manager->common.magic = ISCAPI_TASKMGR_MAGIC;
manager->mode = isc_taskmgrmode_normal;
manager->mctx = NULL;
result = isc_mutex_init(&manager->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_mgr;
result = isc_mutex_init(&manager->excl_lock);
if (result != ISC_R_SUCCESS) {
DESTROYLOCK(&manager->lock);
goto cleanup_mgr;
}
RUNTIME_CHECK(isc_mutex_init(&manager->lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&manager->excl_lock) == ISC_R_SUCCESS);
manager->workers = 0;
manager->threads = isc_mem_allocate(mctx,
workers * sizeof(isc_thread_t));
if (manager->threads == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup_lock;
}
if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_condition_init() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
result = ISC_R_UNEXPECTED;
goto cleanup_threads;
}
if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_condition_init() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
result = ISC_R_UNEXPECTED;
goto cleanup_workavailable;
}
if (isc_condition_init(&manager->paused) != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_condition_init() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
result = ISC_R_UNEXPECTED;
goto cleanup_exclusivegranted;
}
if (default_quantum == 0)
RUNTIME_CHECK(isc_mutex_init(&manager->halt_lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_init(&manager->halt_cond) == ISC_R_SUCCESS);
manager->workers = workers;
if (default_quantum == 0) {
default_quantum = DEFAULT_DEFAULT_QUANTUM;
}
manager->default_quantum = default_quantum;
INIT_LIST(manager->tasks);
INIT_LIST(manager->ready_tasks);
INIT_LIST(manager->ready_priority_tasks);
manager->queues = isc_mem_get(mctx, workers * sizeof(isc__taskqueue_t));
RUNTIME_CHECK(manager->queues != NULL);
manager->tasks_running = 0;
manager->tasks_ready = 0;
manager->exclusive_requested = false;
manager->pause_requested = false;
manager->curq = 0;
manager->exiting = false;
manager->excl = NULL;
manager->halted = 0;
manager->exclusive_requested = false;
manager->pause_requested = false;
isc_mem_attach(mctx, &manager->mctx);
@@ -1264,40 +1368,29 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
* Start workers.
*/
for (i = 0; i < workers; i++) {
if (isc_thread_create(run, manager,
&manager->threads[manager->workers]) ==
ISC_R_SUCCESS) {
char name[16]; /* thread name limit on Linux */
snprintf(name, sizeof(name), "isc-worker%04u", i);
isc_thread_setname(manager->threads[manager->workers],
name);
manager->workers++;
started++;
}
INIT_LIST(manager->queues[i].ready_tasks);
INIT_LIST(manager->queues[i].ready_priority_tasks);
RUNTIME_CHECK(isc_mutex_init(&manager->queues[i].lock)
== ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_init(
&manager->queues[i].work_available)
== ISC_R_SUCCESS);
manager->queues[i].manager = manager;
manager->queues[i].threadid = i;
RUNTIME_CHECK(isc_thread_create(run, &manager->queues[i],
&manager->queues[i].thread)
== ISC_R_SUCCESS);
char name[16];
snprintf(name, sizeof(name), "isc-worker%04u", i);
isc_thread_setname(manager->queues[i].thread, name);
}
UNLOCK(&manager->lock);
if (started == 0) {
manager_free(manager);
return (ISC_R_NOTHREADS);
}
isc_thread_setconcurrency(workers);
*managerp = (isc_taskmgr_t *)manager;
return (ISC_R_SUCCESS);
cleanup_exclusivegranted:
(void)isc_condition_destroy(&manager->exclusive_granted);
cleanup_workavailable:
(void)isc_condition_destroy(&manager->work_available);
cleanup_threads:
isc_mem_free(mctx, manager->threads);
cleanup_lock:
DESTROYLOCK(&manager->lock);
cleanup_mgr:
isc_mem_put(mctx, manager, sizeof(*manager));
return (result);
}
void
@@ -1355,29 +1448,34 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
/*
* Post shutdown event(s) to every task (if they haven't already been
* posted).
* posted). To make things easier post idle tasks to worker 0.
*/
LOCK(&manager->queues[0].lock);
for (task = HEAD(manager->tasks);
task != NULL;
task = NEXT(task, link)) {
LOCK(&task->lock);
if (task_shutdown(task))
push_readyq(manager, task);
if (task_shutdown(task)) {
task->threadid = 0;
push_readyq(manager, task, 0);
}
UNLOCK(&task->lock);
}
UNLOCK(&manager->queues[0].lock);
/*
* Wake up any sleeping workers. This ensures we get work done if
* there's work left to do, and if there are already no tasks left
* it will cause the workers to see manager->exiting.
*/
BROADCAST(&manager->work_available);
wake_all_queues(manager);
UNLOCK(&manager->lock);
/*
* Wait for all the worker threads to exit.
*/
for (i = 0; i < manager->workers; i++)
(void)isc_thread_join(manager->threads[i], NULL);
(void)isc_thread_join(manager->queues[i].thread, NULL);
manager_free(manager);
@@ -1385,11 +1483,11 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
}
void
isc_taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode) {
isc_taskmgr_setprivilegedmode(isc_taskmgr_t *manager0) {
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
LOCK(&manager->lock);
manager->mode = mode;
manager->mode = isc_taskmgrmode_privileged;
UNLOCK(&manager->lock);
}
@@ -1406,24 +1504,35 @@ isc_taskmgr_mode(isc_taskmgr_t *manager0) {
void
isc__taskmgr_pause(isc_taskmgr_t *manager0) {
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
manager->pause_requested = true;
LOCK(&manager->lock);
while (manager->tasks_running > 0) {
WAIT(&manager->paused, &manager->lock);
LOCK(&manager->halt_lock);
while (manager->exclusive_requested || manager->pause_requested) {
UNLOCK(&manager->halt_lock);
/* This is ugly but pause is used EXCLUSIVELY in tests */
isc_thread_yield();
LOCK(&manager->halt_lock);
}
UNLOCK(&manager->lock);
manager->pause_requested = true;
while (manager->halted < manager->workers) {
wake_all_queues(manager);
WAIT(&manager->halt_cond, &manager->halt_lock);
}
UNLOCK(&manager->halt_lock);
}
void
isc__taskmgr_resume(isc_taskmgr_t *manager0) {
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
LOCK(&manager->lock);
LOCK(&manager->halt_lock);
if (manager->pause_requested) {
manager->pause_requested = false;
BROADCAST(&manager->work_available);
while (manager->halted > 0) {
BROADCAST(&manager->halt_cond);
WAIT(&manager->halt_cond, &manager->halt_lock);
}
}
UNLOCK(&manager->lock);
UNLOCK(&manager->halt_lock);
}
void
@@ -1462,24 +1571,25 @@ isc_result_t
isc_task_beginexclusive(isc_task_t *task0) {
isc__task_t *task = (isc__task_t *)task0;
isc__taskmgr_t *manager = task->manager;
REQUIRE(VALID_TASK(task));
REQUIRE(task->state == task_state_running);
/*
* TODO REQUIRE(task == task->manager->excl);
* it should be here, it fails on shutdown server->task
*/
REQUIRE(task == task->manager->excl ||
(task->manager->exiting && task->manager->excl == NULL));
LOCK(&manager->lock);
if (manager->exclusive_requested) {
UNLOCK(&manager->lock);
if (manager->exclusive_requested || manager->pause_requested) {
return (ISC_R_LOCKBUSY);
}
LOCK(&manager->halt_lock);
INSIST(!manager->exclusive_requested && !manager->pause_requested);
manager->exclusive_requested = true;
while (manager->tasks_running > 1) {
WAIT(&manager->exclusive_granted, &manager->lock);
while (manager->halted + 1 < manager->workers) {
wake_all_queues(manager);
WAIT(&manager->halt_cond, &manager->halt_lock);
}
UNLOCK(&manager->lock);
UNLOCK(&manager->halt_lock);
return (ISC_R_SUCCESS);
}
@@ -1490,11 +1600,14 @@ isc_task_endexclusive(isc_task_t *task0) {
REQUIRE(VALID_TASK(task));
REQUIRE(task->state == task_state_running);
LOCK(&manager->lock);
LOCK(&manager->halt_lock);
REQUIRE(manager->exclusive_requested);
manager->exclusive_requested = false;
BROADCAST(&manager->work_available);
UNLOCK(&manager->lock);
while (manager->halted > 0) {
BROADCAST(&manager->halt_cond);
WAIT(&manager->halt_cond, &manager->halt_lock);
}
UNLOCK(&manager->halt_lock);
}
void
@@ -1515,14 +1628,14 @@ isc_task_setprivilege(isc_task_t *task0, bool priv) {
if (priv == oldpriv)
return;
LOCK(&manager->lock);
LOCK(&manager->queues[task->threadid].lock);
if (priv && ISC_LINK_LINKED(task, ready_link))
ENQUEUE(manager->ready_priority_tasks, task,
ready_priority_link);
ENQUEUE(manager->queues[task->threadid].ready_priority_tasks,
task, ready_priority_link);
else if (!priv && ISC_LINK_LINKED(task, ready_priority_link))
DEQUEUE(manager->ready_priority_tasks, task,
ready_priority_link);
UNLOCK(&manager->lock);
DEQUEUE(manager->queues[task->threadid].ready_priority_tasks,
task, ready_priority_link);
UNLOCK(&manager->queues[task->threadid].lock);
}
bool
@@ -1575,11 +1688,13 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) {
TRY0(xmlTextWriterEndElement(writer)); /* default-quantum */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-running"));
TRY0(xmlTextWriterWriteFormatString(writer, "%d", mgr->tasks_running));
TRY0(xmlTextWriterWriteFormatString(writer, "%d",
(int) mgr->tasks_running));
TRY0(xmlTextWriterEndElement(writer)); /* tasks-running */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-ready"));
TRY0(xmlTextWriterWriteFormatString(writer, "%d", mgr->tasks_ready));
TRY0(xmlTextWriterWriteFormatString(writer, "%d",
(int) mgr->tasks_ready));
TRY0(xmlTextWriterEndElement(writer)); /* tasks-ready */
TRY0(xmlTextWriterEndElement(writer)); /* thread-model */
+6 -9
View File
@@ -67,7 +67,6 @@ set_and_drop(isc_task_t *task, isc_event_t *event) {
*value = (int) isc_taskmgr_mode(taskmgr);
counter++;
UNLOCK(&lock);
isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_normal);
}
/*
@@ -230,7 +229,7 @@ ATF_TC_BODY(privileged_events, tc) {
isc_task_send(task2, &event);
ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
isc_taskmgr_setprivilegedmode(taskmgr);
ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_privileged);
isc__taskmgr_resume(taskmgr);
@@ -351,7 +350,7 @@ ATF_TC_BODY(privilege_drop, tc) {
isc_task_send(task2, &event);
ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
isc_taskmgr_setprivilegedmode(taskmgr);
ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_privileged);
isc__taskmgr_resume(taskmgr);
@@ -363,14 +362,12 @@ ATF_TC_BODY(privilege_drop, tc) {
}
/*
* We can't guarantee what order the events fire, but
* we do know *exactly one* of the privileged tasks will
* have run in privileged mode...
* We need to check that all privilege mode events were fired
* in privileged mode, and non privileged in non-privileged.
*/
ATF_CHECK(a == isc_taskmgrmode_privileged ||
c == isc_taskmgrmode_privileged ||
ATF_CHECK(a == isc_taskmgrmode_privileged &&
c == isc_taskmgrmode_privileged &&
d == isc_taskmgrmode_privileged);
ATF_CHECK(a + c + d == isc_taskmgrmode_privileged);
/* ...and neither of the non-privileged tasks did... */
ATF_CHECK(b == isc_taskmgrmode_normal || e == isc_taskmgrmode_normal);
+820 -1380
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -79,6 +79,9 @@ isc_thread_setconcurrency(unsigned int level);
void
isc_thread_setname(isc_thread_t, const char *);
isc_result_t
isc_thread_setaffinity(int cpu);
int
isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *));
+5 -5
View File
@@ -78,19 +78,16 @@ isc_socket_getpeername
isc_socket_getsockname
isc_socket_gettag
isc_socket_gettype
isc_socket_hasreuseport
isc_socket_ipv6only
isc_socket_listen
isc_socket_open
isc_socket_permunix
isc_socket_recv
isc_socket_recv2
isc_socket_recvv
isc_socket_send
isc_socket_sendto
isc_socket_sendto2
isc_socket_sendtov
isc_socket_sendtov2
isc_socket_sendv
isc_socket_setname
isc_socketmgr_create
isc_socketmgr_create2
@@ -584,6 +581,8 @@ isc_task_purgeevent
isc_task_purgerange
isc_task_send
isc_task_sendanddetach
isc_task_sendto
isc_task_sendtoanddetach
isc_task_setname
isc_task_setprivilege
isc_task_shutdown
@@ -600,7 +599,7 @@ isc_taskmgr_renderjson
isc_taskmgr_renderxml
@END LIBXML2
isc_taskmgr_setexcltask
isc_taskmgr_setmode
isc_taskmgr_setprivilegedmode
isc_taskpool_create
isc_taskpool_destroy
isc_taskpool_expand
@@ -613,6 +612,7 @@ isc_thread_key_create
isc_thread_key_delete
isc_thread_key_getspecific
isc_thread_key_setspecific
isc_thread_setaffinity
isc_thread_setconcurrency
isc_thread_setname
isc_time_add
+40 -288
View File
@@ -47,7 +47,6 @@
#include <isc/app.h>
#include <isc/buffer.h>
#include <isc/bufferlist.h>
#include <isc/condition.h>
#include <isc/list.h>
#include <isc/log.h>
@@ -271,16 +270,6 @@ struct isc_socket {
#define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0)
/*
* Buffer structure
*/
typedef struct buflist buflist_t;
struct buflist {
void *buf;
unsigned int buflen;
ISC_LINK(buflist_t) link;
};
/*
* I/O Completion ports Info structures
@@ -296,7 +285,8 @@ typedef struct IoCompletionInfo {
DWORD received_bytes;
int request_type;
struct msghdr messagehdr;
ISC_LIST(buflist_t) bufferlist; /*%< list of buffers */
void *buf;
unsigned int buflen;
} IoCompletionInfo;
/*
@@ -518,8 +508,6 @@ iocompletionport_init(isc_socketmgr_t *manager) {
strbuf);
}
manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS);
/* Now Create the Completion Port */
manager->hIoCompletionPort = CreateIoCompletionPort(
INVALID_HANDLE_VALUE, NULL,
@@ -950,91 +938,33 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
IoCompletionInfo *lpo)
{
unsigned int iovcount;
isc_buffer_t *buffer;
buflist_t *cpbuffer;
isc_region_t used;
size_t write_count;
size_t skip_count;
memset(msg, 0, sizeof(*msg));
memmove(&msg->to_addr, &dev->address.type, dev->address.length);
msg->to_addr_len = dev->address.length;
buffer = ISC_LIST_HEAD(dev->bufferlist);
write_count = 0;
iovcount = 0;
/*
* Single buffer I/O? Skip what we've done so far in this region.
*/
if (buffer == NULL) {
write_count = dev->region.length - dev->n;
cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
RUNTIME_CHECK(cpbuffer != NULL);
cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count);
RUNTIME_CHECK(cpbuffer->buf != NULL);
write_count = dev->region.length - dev->n;
lpo->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count);
RUNTIME_CHECK(lpo->buf != NULL);
socket_log(__LINE__, sock, NULL, TRACE,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
"alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
cpbuffer->buf, write_count);
socket_log(__LINE__, sock, NULL, TRACE,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
"alloc_buffer %p %d", lpo->buf, write_count);
memmove(cpbuffer->buf,(dev->region.base + dev->n), write_count);
cpbuffer->buflen = (unsigned int)write_count;
ISC_LINK_INIT(cpbuffer, link);
ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link);
iov[0].buf = cpbuffer->buf;
iov[0].len = (u_long)write_count;
iovcount = 1;
memmove(lpo->buf,(dev->region.base + dev->n), write_count);
lpo->buflen = (unsigned int)write_count;
iov[0].buf = lpo->buf;
iov[0].len = (u_long)write_count;
iovcount = 1;
goto config;
}
/*
* Multibuffer I/O.
* Skip the data in the buffer list that we have already written.
*/
skip_count = dev->n;
while (buffer != NULL) {
REQUIRE(ISC_BUFFER_VALID(buffer));
if (skip_count < isc_buffer_usedlength(buffer))
break;
skip_count -= isc_buffer_usedlength(buffer);
buffer = ISC_LIST_NEXT(buffer, link);
}
while (buffer != NULL) {
INSIST(iovcount < MAXSCATTERGATHER_SEND);
isc_buffer_usedregion(buffer, &used);
if (used.length > 0) {
int uselen = (int)(used.length - skip_count);
cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
RUNTIME_CHECK(cpbuffer != NULL);
cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, uselen);
RUNTIME_CHECK(cpbuffer->buf != NULL);
socket_log(__LINE__, sock, NULL, TRACE,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
"alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
cpbuffer->buf, write_count);
memmove(cpbuffer->buf,(used.base + skip_count), uselen);
cpbuffer->buflen = uselen;
iov[iovcount].buf = cpbuffer->buf;
iov[iovcount].len = (u_long)(used.length - skip_count);
write_count += uselen;
skip_count = 0;
iovcount++;
}
buffer = ISC_LIST_NEXT(buffer, link);
}
INSIST(skip_count == 0);
config:
msg->msg_iov = iov;
msg->msg_iovlen = iovcount;
msg->msg_totallen = (u_int)write_count;
@@ -1059,8 +989,6 @@ static void
destroy_socketevent(isc_event_t *event) {
isc_socketevent_t *ev = (isc_socketevent_t *)event;
INSIST(ISC_LIST_EMPTY(ev->bufferlist));
(ev->destroy)(event);
}
@@ -1079,7 +1007,6 @@ allocate_socketevent(isc_mem_t *mctx, isc_socket_t *sock,
ev->result = ISC_R_IOERROR; // XXXMLG temporary change to detect failure to set
ISC_LINK_INIT(ev, ev_link);
ISC_LIST_INIT(ev->bufferlist);
ev->region.base = NULL;
ev->n = 0;
ev->offset = 0;
@@ -1215,9 +1142,7 @@ map_socket_error(isc_socket_t *sock, int windows_errno, int *isc_errno,
static void
fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
isc_region_t r;
int copylen;
isc_buffer_t *buffer;
INSIST(dev->n < dev->minimum);
INSIST(sock->recvbuf.remaining > 0);
@@ -1241,36 +1166,12 @@ fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
dev->address = sock->address;
}
/*
* Run through the list of buffers we were given, and find the
* first one with space. Once it is found, loop through, filling
* the buffers as much as possible.
*/
buffer = ISC_LIST_HEAD(dev->bufferlist);
if (buffer != NULL) { // Multi-buffer receive
while (buffer != NULL && sock->recvbuf.remaining > 0) {
REQUIRE(ISC_BUFFER_VALID(buffer));
if (isc_buffer_availablelength(buffer) > 0) {
isc_buffer_availableregion(buffer, &r);
copylen = min(r.length,
sock->recvbuf.remaining);
memmove(r.base, sock->recvbuf.consume_position,
copylen);
sock->recvbuf.consume_position += copylen;
sock->recvbuf.remaining -= copylen;
isc_buffer_add(buffer, copylen);
dev->n += copylen;
}
buffer = ISC_LIST_NEXT(buffer, link);
}
} else { // Single-buffer receive
copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining);
memmove(dev->region.base + dev->n,
sock->recvbuf.consume_position, copylen);
sock->recvbuf.consume_position += copylen;
sock->recvbuf.remaining -= copylen;
dev->n += copylen;
}
copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining);
memmove(dev->region.base + dev->n,
sock->recvbuf.consume_position, copylen);
sock->recvbuf.consume_position += copylen;
sock->recvbuf.remaining -= copylen;
dev->n += copylen;
/*
* UDP receives are all-consuming. That is, if we have 4k worth of
@@ -1377,7 +1278,6 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
lpo->dev = dev;
mh = &lpo->messagehdr;
memset(mh, 0, sizeof(struct msghdr));
ISC_LIST_INIT(lpo->bufferlist);
build_msghdr_send(sock, dev, mh, cmsg, sock->iov, lpo);
@@ -1649,7 +1549,6 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
REQUIRE(VALID_MANAGER(manager));
REQUIRE(socketp != NULL && *socketp == NULL);
REQUIRE(type != isc_sockettype_fdwatch);
#ifndef SOCK_RAW
if (type == isc_sockettype_raw)
@@ -1855,7 +1754,6 @@ isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
isc_result_t
isc_socket_open(isc_socket_t *sock) {
REQUIRE(VALID_SOCKET(sock));
REQUIRE(sock->type != isc_sockettype_fdwatch);
return (ISC_R_NOTIMPLEMENTED);
}
@@ -1887,7 +1785,6 @@ isc_socket_detach(isc_socket_t **socketp) {
REQUIRE(socketp != NULL);
sock = *socketp;
REQUIRE(VALID_SOCKET(sock));
REQUIRE(sock->type != isc_sockettype_fdwatch);
LOCK(&sock->lock);
CONSISTENT(sock);
@@ -1913,7 +1810,6 @@ isc_socket_detach(isc_socket_t **socketp) {
isc_result_t
isc_socket_close(isc_socket_t *sock) {
REQUIRE(VALID_SOCKET(sock));
REQUIRE(sock->type != isc_sockettype_fdwatch);
return (ISC_R_NOTIMPLEMENTED);
}
@@ -2301,8 +2197,6 @@ static void
internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
struct msghdr *messagehdr, int nbytes, int send_errno, IoCompletionInfo *lpo)
{
buflist_t *buffer;
/*
* Find out what socket this is and lock it.
*/
@@ -2315,17 +2209,14 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
"internal_send: task got socket event %p", dev);
buffer = ISC_LIST_HEAD(lpo->bufferlist);
while (buffer != NULL) {
ISC_LIST_DEQUEUE(lpo->bufferlist, buffer, link);
if (lpo->buf != NULL) {
socket_log(__LINE__, sock, NULL, TRACE,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
"free_buffer %p %p", buffer, buffer->buf);
"free_buffer %p", lpo->buf);
HeapFree(hHeapHandle, 0, buffer->buf);
HeapFree(hHeapHandle, 0, buffer);
buffer = ISC_LIST_HEAD(lpo->bufferlist);
HeapFree(hHeapHandle, 0, lpo->buf);
lpo->buf = NULL;
lpo->buflen = 0;
}
INSIST(sock->pending_iocp > 0);
@@ -2645,7 +2536,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
isc_result_t
isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
unsigned int maxsocks)
unsigned int maxsocks, int nthreads)
{
isc_socketmgr_t *manager;
isc_result_t result;
@@ -2681,6 +2572,10 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
}
isc_mem_attach(mctx, &manager->mctx);
if (nthreads == 0) {
nthreads = isc_os_ncpus() + 1;
}
manager->maxIOCPThreads = min(nthreads, MAX_IOCPTHREADS);
iocompletionport_init(manager); /* Create the Completion Ports */
@@ -2836,77 +2731,6 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
return (result);
}
isc_result_t
isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
unsigned int minimum, isc_task_t *task,
isc_taskaction_t action, void *arg)
{
isc_socketevent_t *dev;
isc_socketmgr_t *manager;
unsigned int iocount;
isc_buffer_t *buffer;
isc_result_t ret;
REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock);
CONSISTENT(sock);
/*
* Make sure that the socket is not closed. XXXMLG change error here?
*/
if (sock->fd == INVALID_SOCKET) {
UNLOCK(&sock->lock);
return (ISC_R_CONNREFUSED);
}
REQUIRE(buflist != NULL);
REQUIRE(!ISC_LIST_EMPTY(*buflist));
REQUIRE(task != NULL);
REQUIRE(action != NULL);
manager = sock->manager;
REQUIRE(VALID_MANAGER(manager));
iocount = isc_bufferlist_availablecount(buflist);
REQUIRE(iocount > 0);
INSIST(sock->bound);
dev = allocate_socketevent(manager->mctx, sock,
ISC_SOCKEVENT_RECVDONE, action, arg);
if (dev == NULL) {
UNLOCK(&sock->lock);
return (ISC_R_NOMEMORY);
}
/*
* UDP sockets are always partial read
*/
if (sock->type == isc_sockettype_udp)
dev->minimum = 1;
else {
if (minimum == 0)
dev->minimum = iocount;
else
dev->minimum = minimum;
}
/*
* Move each buffer from the passed in list to our internal one.
*/
buffer = ISC_LIST_HEAD(*buflist);
while (buffer != NULL) {
ISC_LIST_DEQUEUE(*buflist, buffer, link);
ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
buffer = ISC_LIST_HEAD(*buflist);
}
ret = socket_recv(sock, dev, task, 0);
UNLOCK(&sock->lock);
return (ret);
}
isc_result_t
isc_socket_recv(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
@@ -2967,7 +2791,6 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
return (ISC_R_CONNREFUSED);
}
ISC_LIST_INIT(event->bufferlist);
event->region = *region;
event->n = 0;
event->offset = 0;
@@ -3078,7 +2901,6 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
isc_result_t ret;
REQUIRE(VALID_SOCKET(sock));
REQUIRE(sock->type != isc_sockettype_fdwatch);
LOCK(&sock->lock);
CONSISTENT(sock);
@@ -3112,80 +2934,6 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
return (ret);
}
isc_result_t
isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, void *arg)
{
return (isc_socket_sendtov2(sock, buflist, task, action, arg, NULL,
NULL, 0));
}
isc_result_t
isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, void *arg,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
{
return (isc_socket_sendtov2(sock, buflist, task, action, arg, address,
pktinfo, 0));
}
isc_result_t
isc_socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, void *arg,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
unsigned int flags)
{
isc_socketevent_t *dev;
isc_socketmgr_t *manager;
unsigned int iocount;
isc_buffer_t *buffer;
isc_result_t ret;
REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock);
CONSISTENT(sock);
/*
* make sure that the socket's not closed
*/
if (sock->fd == INVALID_SOCKET) {
UNLOCK(&sock->lock);
return (ISC_R_CONNREFUSED);
}
REQUIRE(buflist != NULL);
REQUIRE(!ISC_LIST_EMPTY(*buflist));
REQUIRE(task != NULL);
REQUIRE(action != NULL);
manager = sock->manager;
REQUIRE(VALID_MANAGER(manager));
iocount = isc_bufferlist_usedcount(buflist);
REQUIRE(iocount > 0);
dev = allocate_socketevent(manager->mctx, sock,
ISC_SOCKEVENT_SENDDONE, action, arg);
if (dev == NULL) {
UNLOCK(&sock->lock);
return (ISC_R_NOMEMORY);
}
/*
* Move each buffer from the passed in list to our internal one.
*/
buffer = ISC_LIST_HEAD(*buflist);
while (buffer != NULL) {
ISC_LIST_DEQUEUE(*buflist, buffer, link);
ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
buffer = ISC_LIST_HEAD(*buflist);
}
ret = socket_send(sock, dev, task, address, pktinfo, flags);
UNLOCK(&sock->lock);
return (ret);
}
isc_result_t
isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
@@ -3209,7 +2957,6 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
UNLOCK(&sock->lock);
return (ISC_R_CONNREFUSED);
}
ISC_LIST_INIT(event->bufferlist);
event->region = *region;
event->n = 0;
event->offset = 0;
@@ -3946,20 +3693,25 @@ isc_socket_socketevent(isc_mem_t *mctx, void *sender,
return (allocate_socketevent(mctx, sender, eventtype, action, arg));
}
bool
isc_socket_hasreuseport() {
return (false);
}
#ifdef HAVE_LIBXML2
static const char *
_socktype(isc_sockettype_t type) {
if (type == isc_sockettype_udp)
switch (type) {
case isc_sockettype_udp:
return ("udp");
else if (type == isc_sockettype_tcp)
case isc_sockettype_tcp:
return ("tcp");
else if (type == isc_sockettype_unix)
case isc_sockettype_unix:
return ("unix");
else if (type == isc_sockettype_fdwatch)
return ("fdwatch");
else
default:
return ("not-initialized");
}
}
#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
+6
View File
@@ -66,6 +66,12 @@ isc_thread_setname(isc_thread_t thread, const char *name) {
UNUSED(name);
}
isc_result_t
isc_thread_setaffinity(int cpu) {
/* no-op on Windows for now */
return (ISC_R_SUCCESS);
}
void *
isc_thread_key_getspecific(isc_thread_key_t key) {
return(TlsGetValue(key));
+1 -1
View File
@@ -2960,7 +2960,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
ns_server_attach(manager->sctx, &client->sctx);
client->task = NULL;
result = isc_task_create(manager->taskmgr, 0, &client->task);
result = isc_task_create(manager->taskmgr, 50, &client->task);
if (result != ISC_R_SUCCESS)
goto cleanup_client;
isc_task_setname(client->task, "client", client);
+1
View File
@@ -470,6 +470,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_NOLISTEN;
attrs |= DNS_DISPATCHATTR_CANREUSE;
attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
+13 -8
View File
@@ -5237,6 +5237,19 @@ ns__query_start(query_ctx_t *qctx) {
qctx->need_wildcardproof = false;
qctx->rpz = false;
/*
* If we require a server cookie then send back BADCOOKIE
* before we have done too much work.
*/
if (!TCP(qctx->client) && qctx->client->view->requireservercookie &&
WANTCOOKIE(qctx->client) && !HAVECOOKIE(qctx->client))
{
qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
qctx->client->message->rcode = dns_rcode_badcookie;
return (query_done(qctx));
}
if (qctx->client->view->checknames &&
!dns_rdata_checkowner(qctx->client->query.qname,
qctx->client->message->rdclass,
@@ -6276,14 +6289,6 @@ query_checkrrl(query_ctx_t *qctx, isc_result_t result) {
return (DNS_R_DROP);
}
}
} else if (!TCP(qctx->client) &&
qctx->client->view->requireservercookie &&
WANTCOOKIE(qctx->client) && !HAVECOOKIE(qctx->client))
{
qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
qctx->client->message->rcode = dns_rcode_badcookie;
return (DNS_R_DROP);
}
return (ISC_R_SUCCESS);
+2
View File
@@ -824,6 +824,8 @@
./bin/tests/system/cookie/ns6/root.hint ZONE 2017,2018
./bin/tests/system/cookie/ns7/named.conf.in CONF-C 2018
./bin/tests/system/cookie/ns7/root.db ZONE 2018
./bin/tests/system/cookie/ns8/example.db ZONE 2018
./bin/tests/system/cookie/ns8/named.conf.in CONF-C 2018
./bin/tests/system/cookie/setup.sh SH 2018
./bin/tests/system/cookie/tests.sh SH 2014,2015,2016,2017,2018
./bin/tests/system/coverage/01-ksk-inactive/README X 2013,2018