Merge branch '2295-add-the-ability-to-specify-that-a-server-supports-cookies' into 'main'

Resolve "Add the ability to specify that a server supports COOKIES."

Closes #2295

See merge request isc-projects/bind9!4410
This commit is contained in:
Mark Andrews 2022-09-14 01:36:42 +00:00
commit 44235cd2cf
16 changed files with 260 additions and 551 deletions

View file

@ -1,3 +1,9 @@
5966. [func] You can now specify if a server must return a DNS
COOKIE before accepting the response over UDP.
[GL #2295]
server <prefix> { require-cookie <yes_or_no>; };
5965. [cleanup] Move the duplicated ASCII case conversion tables to
isc_ascii where they can be shared, and replace the
various hot-path tolower() loops with calls to new

View file

@ -1470,6 +1470,12 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj)));
}
obj = NULL;
(void)cfg_map_get(cpeer, "require-cookie", &obj);
if (obj != NULL) {
CHECK(dns_peer_setrequirecookie(peer, cfg_obj_asboolean(obj)));
}
obj = NULL;
(void)cfg_map_get(cpeer, "edns", &obj);
if (obj != NULL) {

View file

@ -30,6 +30,7 @@ server 0.0.0.0 {
request-expire no;
request-ixfr no;
request-nsid no;
require-cookie no;
send-cookie no;
tcp-keepalive no;
tcp-only no;
@ -52,6 +53,7 @@ server :: {
request-expire no;
request-ixfr no;
request-nsid no;
require-cookie no;
send-cookie no;
tcp-keepalive no;
tcp-only no;

View file

@ -0,0 +1,14 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ SOA ns7 hostmaster.isc.org. 1 600 600 1200 600
@ NS ns7
ns7 A 10.53.0.7

View file

@ -29,3 +29,8 @@ zone "." {
type primary;
file "root.db";
};
zone "from-no-cookie-server.example" {
type primary;
file "from-no-cookie-server.example.db";
};

View file

@ -9,5 +9,7 @@
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 3600 SOA . . 0 0 0 0 0
@ 3600 NS .
@ 3600 SOA . . 0 0 0 0 0
@ 3600 NS .
from-no-cookie-server 3600 NS ns7.from-no-cookie-server
ns7.from-no-cookie-server 3600 A 10.53.0.7

View file

@ -33,6 +33,8 @@ options {
require-server-cookie yes;
};
server 10.53.0.7 { require-cookie yes; };
zone "example" {
type primary;
file "example.db";

View file

@ -214,6 +214,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 'server <prefix> { require-cookie yes; };' triggers TCP when cookie not returned ($n)"
ret=0
nextpart ns8/named.run > /dev/null
$DIG $DIGOPTS +cookie soa from-no-cookie-server.example @10.53.0.8 > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
wait_for_log_peek 3 "missing required cookie from 10.53.0.7#" ns8/named.run || ret=1
wait_for_log_peek 3 "from-no-cookie-server.example/SOA): connecting via TCP" ns8/named.run || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "send undersized cookie ($n)"
ret=0

View file

@ -2320,6 +2320,34 @@ Boolean Options
option in its response, then its contents are logged in the ``nsid``
category at level ``info``. The default is ``no``.
.. namedconf:statement:: require-cookie
:tags: query
:short: Controls whether responses without a server cookie are accepted
The ``require-cookie`` clause can be used to indicate that the
remote server is known to support DNS COOKIE. Setting this option
to ``yes`` causes ``named`` to always retry a request over TCP when
it receives a UDP response without a DNS COOKIE from the remote
server, even if UDP responses with DNS COOKIE have not been sent
by this server before. This prevents spoofed answers from being
accepted without a retry over TCP when ``named`` has not yet
determined whether the remote server supports DNS COOKIE. Setting
this option to ``no`` (the default) causes ``named`` to rely on
autodetection of DNS COOKIE support to determine when to retry a
request over TCP.
.. note::
If a UDP response is signed using TSIG, ``named`` accepts it even if
``require-cookie`` is set to ``yes`` and the response does not
contain a DNS COOKIE.
The ``send-cookie`` clause determines whether the local server adds
a COOKIE EDNS option to requests sent to the server. This overrides
``send-cookie`` set at the view or option level. The :iscman:`named` server
may determine that COOKIE is not supported by the remote server and not
add a COOKIE EDNS option to requests.
.. namedconf:statement:: require-server-cookie
:tags: query
:short: Controls whether a valid server cookie is required before sending a full response to a UDP request.
@ -5829,6 +5857,7 @@ and :namedconf:ref:`options` blocks:
- :namedconf:ref:`request-expire`
- :namedconf:ref:`request-ixfr`
- :namedconf:ref:`request-nsid`
- :namedconf:ref:`require-cookie`
- :namedconf:ref:`send-cookie`
- :namedconf:ref:`transfer-format`
- :namedconf:ref:`transfer-source-v6`

View file

@ -399,6 +399,7 @@ server <netprefix> {
request\-expire <boolean>;
request\-ixfr <boolean>;
request\-nsid <boolean>;
require\-cookie <boolean>;
send\-cookie <boolean>;
tcp\-keepalive <boolean>;
tcp\-only <boolean>;
@ -612,6 +613,7 @@ view <string> [ <class> ] {
request\-expire <boolean>;
request\-ixfr <boolean>;
request\-nsid <boolean>;
require\-cookie <boolean>;
send\-cookie <boolean>;
tcp\-keepalive <boolean>;
tcp\-only <boolean>;

View file

@ -342,6 +342,7 @@ server <netprefix> {
request-expire <boolean>;
request-ixfr <boolean>;
request-nsid <boolean>;
require-cookie <boolean>;
send-cookie <boolean>;
tcp-keepalive <boolean>;
tcp-only <boolean>;
@ -555,6 +556,7 @@ view <string> [ <class> ] {
request-expire <boolean>;
request-ixfr <boolean>;
request-nsid <boolean>;
require-cookie <boolean>;
send-cookie <boolean>;
tcp-keepalive <boolean>;
tcp-only <boolean>;

View file

@ -27,6 +27,12 @@ New Features
- None.
- A new configuration option ``require-cookie`` has been introduced, it
specifies if there should be a DNS COOKIE in the response for a given
prefix and if not named falls back to TCP. This is useful if you know
a given server support DNS COOKIE. It can also be used to force all
non DNS COOKIE responses to fall back to TCP. :gl:`#2295`
Removed Features
~~~~~~~~~~~~~~~~

View file

@ -118,6 +118,12 @@ dns_peer_setsendcookie(dns_peer_t *peer, bool newval);
isc_result_t
dns_peer_getsendcookie(dns_peer_t *peer, bool *retval);
isc_result_t
dns_peer_setrequirecookie(dns_peer_t *peer, bool newval);
isc_result_t
dns_peer_getrequirecookie(dns_peer_t *peer, bool *retval);
isc_result_t
dns_peer_setrequestexpire(dns_peer_t *peer, bool newval);

View file

@ -56,6 +56,7 @@ struct dns_peer {
bool support_edns;
bool request_nsid;
bool send_cookie;
bool require_cookie;
bool request_expire;
bool force_tcp;
bool tcp_keepalive;
@ -98,6 +99,7 @@ struct dns_peer {
#define FORCE_TCP_BIT 15
#define SERVER_PADDING_BIT 16
#define REQUEST_TCP_KEEPALIVE_BIT 17
#define REQUIRE_COOKIE_BIT 18
static void
peerlist_delete(dns_peerlist_t **list);
@ -348,302 +350,141 @@ peer_delete(dns_peer_t **peer) {
isc_mem_put(mem, p, sizeof(*p));
}
isc_result_t
dns_peer_setbogus(dns_peer_t *peer, bool newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(BOGUS_BIT, &peer->bitflags);
peer->bogus = newval;
DNS_BIT_SET(BOGUS_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getbogus(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(BOGUS_BIT, &peer->bitflags)) {
*retval = peer->bogus;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
#define ACCESS_OPTION(name, macro, type, element) \
isc_result_t dns_peer_get##name(dns_peer_t *peer, type *value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
REQUIRE(value != NULL); \
if (DNS_BIT_CHECK(macro, &peer->bitflags)) { \
*value = peer->element; \
return (ISC_R_SUCCESS); \
} else { \
return (ISC_R_NOTFOUND); \
} \
} \
isc_result_t dns_peer_set##name(dns_peer_t *peer, type value) { \
bool existed; \
REQUIRE(DNS_PEER_VALID(peer)); \
existed = DNS_BIT_CHECK(macro, &peer->bitflags); \
peer->element = value; \
DNS_BIT_SET(macro, &peer->bitflags); \
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); \
}
}
isc_result_t
dns_peer_setprovideixfr(dns_peer_t *peer, bool newval) {
bool existed;
ACCESS_OPTION(bogus, BOGUS_BIT, bool, bogus)
ACCESS_OPTION(forcetcp, FORCE_TCP_BIT, bool, force_tcp)
ACCESS_OPTION(maxudp, SERVER_MAXUDP_BIT, uint16_t, maxudp)
ACCESS_OPTION(provideixfr, PROVIDE_IXFR_BIT, bool, provide_ixfr)
ACCESS_OPTION(requestexpire, REQUEST_EXPIRE_BIT, bool, request_expire)
ACCESS_OPTION(requestixfr, REQUEST_IXFR_BIT, bool, request_ixfr)
ACCESS_OPTION(requestnsid, REQUEST_NSID_BIT, bool, request_nsid)
ACCESS_OPTION(requirecookie, REQUIRE_COOKIE_BIT, bool, require_cookie)
ACCESS_OPTION(sendcookie, SEND_COOKIE_BIT, bool, send_cookie)
ACCESS_OPTION(supportedns, SUPPORT_EDNS_BIT, bool, support_edns)
ACCESS_OPTION(tcpkeepalive, REQUEST_TCP_KEEPALIVE_BIT, bool, tcp_keepalive)
ACCESS_OPTION(transferformat, SERVER_TRANSFER_FORMAT_BIT, dns_transfer_format_t,
transfer_format)
ACCESS_OPTION(transfers, TRANSFERS_BIT, uint32_t, transfers)
ACCESS_OPTION(udpsize, SERVER_UDPSIZE_BIT, uint16_t, udpsize)
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(PROVIDE_IXFR_BIT, &peer->bitflags);
peer->provide_ixfr = newval;
DNS_BIT_SET(PROVIDE_IXFR_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getprovideixfr(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(PROVIDE_IXFR_BIT, &peer->bitflags)) {
*retval = peer->provide_ixfr;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
#define ACCESS_OPTIONMAX(name, macro, type, element, max) \
isc_result_t dns_peer_get##name(dns_peer_t *peer, type *value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
REQUIRE(value != NULL); \
if (DNS_BIT_CHECK(macro, &peer->bitflags)) { \
*value = peer->element; \
return (ISC_R_SUCCESS); \
} else { \
return (ISC_R_NOTFOUND); \
} \
} \
isc_result_t dns_peer_set##name(dns_peer_t *peer, type value) { \
bool existed; \
REQUIRE(DNS_PEER_VALID(peer)); \
existed = DNS_BIT_CHECK(macro, &peer->bitflags); \
if (value > max) { \
value = max; \
} \
peer->element = value; \
DNS_BIT_SET(macro, &peer->bitflags); \
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS); \
}
}
isc_result_t
dns_peer_setrequestixfr(dns_peer_t *peer, bool newval) {
bool existed;
ACCESS_OPTIONMAX(padding, SERVER_PADDING_BIT, uint16_t, padding, 512)
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(REQUEST_IXFR_BIT, &peer->bitflags);
peer->request_ixfr = newval;
DNS_BIT_SET(REQUEST_IXFR_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getrequestixfr(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(REQUEST_IXFR_BIT, &peer->bitflags)) {
*retval = peer->request_ixfr;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
#define ACCESS_SOCKADDR(name, element) \
isc_result_t dns_peer_get##name(dns_peer_t *peer, \
isc_sockaddr_t *value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
REQUIRE(value != NULL); \
if (peer->element == NULL) { \
return (ISC_R_NOTFOUND); \
} \
*value = *peer->element; \
return (ISC_R_SUCCESS); \
} \
isc_result_t dns_peer_set##name(dns_peer_t *peer, \
const isc_sockaddr_t *value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
if (peer->element != NULL) { \
isc_mem_put(peer->mem, peer->element, \
sizeof(*peer->element)); \
peer->element = NULL; \
} \
if (value != NULL) { \
peer->element = isc_mem_get(peer->mem, \
sizeof(*peer->element)); \
*peer->element = *value; \
} \
return (ISC_R_SUCCESS); \
}
}
isc_result_t
dns_peer_setsupportedns(dns_peer_t *peer, bool newval) {
bool existed;
ACCESS_SOCKADDR(notifysource, notify_source)
ACCESS_SOCKADDR(querysource, query_source)
ACCESS_SOCKADDR(transfersource, transfer_source)
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(SUPPORT_EDNS_BIT, &peer->bitflags);
peer->support_edns = newval;
DNS_BIT_SET(SUPPORT_EDNS_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getsupportedns(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(SUPPORT_EDNS_BIT, &peer->bitflags)) {
*retval = peer->support_edns;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
#define ACCESS_OPTION_OVERWRITE(name, macro, type, element) \
isc_result_t dns_peer_get##name(dns_peer_t *peer, type *value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
REQUIRE(value != NULL); \
if (DNS_BIT_CHECK(macro, &peer->bitflags)) { \
*value = peer->element; \
return (ISC_R_SUCCESS); \
} else { \
return (ISC_R_NOTFOUND); \
} \
} \
isc_result_t dns_peer_set##name(dns_peer_t *peer, type value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
peer->element = value; \
DNS_BIT_SET(macro, &peer->bitflags); \
return (ISC_R_SUCCESS); \
}
}
isc_result_t
dns_peer_setrequestnsid(dns_peer_t *peer, bool newval) {
bool existed;
ACCESS_OPTION_OVERWRITE(ednsversion, EDNS_VERSION_BIT, uint8_t, ednsversion)
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags);
peer->request_nsid = newval;
DNS_BIT_SET(REQUEST_NSID_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getrequestnsid(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags)) {
*retval = peer->request_nsid;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
#define ACCESS_OPTION_OVERWRITEDSCP(name, macro, type, element) \
isc_result_t dns_peer_get##name(dns_peer_t *peer, type *value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
REQUIRE(value != NULL); \
if (DNS_BIT_CHECK(macro, &peer->bitflags)) { \
*value = peer->element; \
return (ISC_R_SUCCESS); \
} else { \
return (ISC_R_NOTFOUND); \
} \
} \
isc_result_t dns_peer_set##name(dns_peer_t *peer, type value) { \
REQUIRE(DNS_PEER_VALID(peer)); \
REQUIRE(value < 64); \
peer->element = value; \
DNS_BIT_SET(macro, &peer->bitflags); \
return (ISC_R_SUCCESS); \
}
}
isc_result_t
dns_peer_setsendcookie(dns_peer_t *peer, bool newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(SEND_COOKIE_BIT, &peer->bitflags);
peer->send_cookie = newval;
DNS_BIT_SET(SEND_COOKIE_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getsendcookie(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(SEND_COOKIE_BIT, &peer->bitflags)) {
*retval = peer->send_cookie;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_setrequestexpire(dns_peer_t *peer, bool newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(REQUEST_EXPIRE_BIT, &peer->bitflags);
peer->request_expire = newval;
DNS_BIT_SET(REQUEST_EXPIRE_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getrequestexpire(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(REQUEST_EXPIRE_BIT, &peer->bitflags)) {
*retval = peer->request_expire;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_setforcetcp(dns_peer_t *peer, bool newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(FORCE_TCP_BIT, &peer->bitflags);
peer->force_tcp = newval;
DNS_BIT_SET(FORCE_TCP_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getforcetcp(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(FORCE_TCP_BIT, &peer->bitflags)) {
*retval = peer->force_tcp;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_settcpkeepalive(dns_peer_t *peer, bool newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(REQUEST_TCP_KEEPALIVE_BIT, &peer->bitflags);
peer->tcp_keepalive = newval;
DNS_BIT_SET(REQUEST_TCP_KEEPALIVE_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_gettcpkeepalive(dns_peer_t *peer, bool *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(REQUEST_TCP_KEEPALIVE_BIT, &peer->bitflags)) {
*retval = peer->tcp_keepalive;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_settransfers(dns_peer_t *peer, uint32_t newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(TRANSFERS_BIT, &peer->bitflags);
peer->transfers = newval;
DNS_BIT_SET(TRANSFERS_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_gettransfers(dns_peer_t *peer, uint32_t *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(TRANSFERS_BIT, &peer->bitflags)) {
*retval = peer->transfers;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_settransferformat(dns_peer_t *peer, dns_transfer_format_t newval) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags);
peer->transfer_format = newval;
DNS_BIT_SET(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_gettransferformat(dns_peer_t *peer, dns_transfer_format_t *retval) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(retval != NULL);
if (DNS_BIT_CHECK(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags)) {
*retval = peer->transfer_format;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
ACCESS_OPTION_OVERWRITEDSCP(notifydscp, NOTIFY_DSCP_BIT, isc_dscp_t,
notify_dscp)
ACCESS_OPTION_OVERWRITEDSCP(querydscp, QUERY_DSCP_BIT, isc_dscp_t, query_dscp)
ACCESS_OPTION_OVERWRITEDSCP(transferdscp, TRANSFER_DSCP_BIT, isc_dscp_t,
transfer_dscp)
isc_result_t
dns_peer_getkey(dns_peer_t *peer, dns_name_t **retval) {
@ -701,268 +542,3 @@ dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) {
return (result);
}
isc_result_t
dns_peer_settransfersource(dns_peer_t *peer,
const isc_sockaddr_t *transfer_source) {
REQUIRE(DNS_PEER_VALID(peer));
if (peer->transfer_source != NULL) {
isc_mem_put(peer->mem, peer->transfer_source,
sizeof(*peer->transfer_source));
peer->transfer_source = NULL;
}
if (transfer_source != NULL) {
peer->transfer_source =
isc_mem_get(peer->mem, sizeof(*peer->transfer_source));
*peer->transfer_source = *transfer_source;
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(transfer_source != NULL);
if (peer->transfer_source == NULL) {
return (ISC_R_NOTFOUND);
}
*transfer_source = *peer->transfer_source;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_setnotifysource(dns_peer_t *peer,
const isc_sockaddr_t *notify_source) {
REQUIRE(DNS_PEER_VALID(peer));
if (peer->notify_source != NULL) {
isc_mem_put(peer->mem, peer->notify_source,
sizeof(*peer->notify_source));
peer->notify_source = NULL;
}
if (notify_source != NULL) {
peer->notify_source = isc_mem_get(peer->mem,
sizeof(*peer->notify_source));
*peer->notify_source = *notify_source;
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getnotifysource(dns_peer_t *peer, isc_sockaddr_t *notify_source) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(notify_source != NULL);
if (peer->notify_source == NULL) {
return (ISC_R_NOTFOUND);
}
*notify_source = *peer->notify_source;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source) {
REQUIRE(DNS_PEER_VALID(peer));
if (peer->query_source != NULL) {
isc_mem_put(peer->mem, peer->query_source,
sizeof(*peer->query_source));
peer->query_source = NULL;
}
if (query_source != NULL) {
peer->query_source = isc_mem_get(peer->mem,
sizeof(*peer->query_source));
*peer->query_source = *query_source;
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getquerysource(dns_peer_t *peer, isc_sockaddr_t *query_source) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(query_source != NULL);
if (peer->query_source == NULL) {
return (ISC_R_NOTFOUND);
}
*query_source = *peer->query_source;
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_setudpsize(dns_peer_t *peer, uint16_t udpsize) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags);
peer->udpsize = udpsize;
DNS_BIT_SET(SERVER_UDPSIZE_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getudpsize(dns_peer_t *peer, uint16_t *udpsize) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(udpsize != NULL);
if (DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags)) {
*udpsize = peer->udpsize;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_setmaxudp(dns_peer_t *peer, uint16_t maxudp) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags);
peer->maxudp = maxudp;
DNS_BIT_SET(SERVER_MAXUDP_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getmaxudp(dns_peer_t *peer, uint16_t *maxudp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(maxudp != NULL);
if (DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags)) {
*maxudp = peer->maxudp;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_setpadding(dns_peer_t *peer, uint16_t padding) {
bool existed;
REQUIRE(DNS_PEER_VALID(peer));
existed = DNS_BIT_CHECK(SERVER_PADDING_BIT, &peer->bitflags);
if (padding > 512) {
padding = 512;
}
peer->padding = padding;
DNS_BIT_SET(SERVER_PADDING_BIT, &peer->bitflags);
return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getpadding(dns_peer_t *peer, uint16_t *padding) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(padding != NULL);
if (DNS_BIT_CHECK(SERVER_PADDING_BIT, &peer->bitflags)) {
*padding = peer->padding;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}
isc_result_t
dns_peer_setnotifydscp(dns_peer_t *peer, isc_dscp_t dscp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(dscp < 64);
peer->notify_dscp = dscp;
DNS_BIT_SET(NOTIFY_DSCP_BIT, &peer->bitflags);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getnotifydscp(dns_peer_t *peer, isc_dscp_t *dscpp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(dscpp != NULL);
if (DNS_BIT_CHECK(NOTIFY_DSCP_BIT, &peer->bitflags)) {
*dscpp = peer->notify_dscp;
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_peer_settransferdscp(dns_peer_t *peer, isc_dscp_t dscp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(dscp < 64);
peer->transfer_dscp = dscp;
DNS_BIT_SET(TRANSFER_DSCP_BIT, &peer->bitflags);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_gettransferdscp(dns_peer_t *peer, isc_dscp_t *dscpp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(dscpp != NULL);
if (DNS_BIT_CHECK(TRANSFER_DSCP_BIT, &peer->bitflags)) {
*dscpp = peer->transfer_dscp;
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_peer_setquerydscp(dns_peer_t *peer, isc_dscp_t dscp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(dscp < 64);
peer->query_dscp = dscp;
DNS_BIT_SET(QUERY_DSCP_BIT, &peer->bitflags);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getquerydscp(dns_peer_t *peer, isc_dscp_t *dscpp) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(dscpp != NULL);
if (DNS_BIT_CHECK(QUERY_DSCP_BIT, &peer->bitflags)) {
*dscpp = peer->query_dscp;
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_peer_setednsversion(dns_peer_t *peer, uint8_t ednsversion) {
REQUIRE(DNS_PEER_VALID(peer));
peer->ednsversion = ednsversion;
DNS_BIT_SET(EDNS_VERSION_BIT, &peer->bitflags);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_peer_getednsversion(dns_peer_t *peer, uint8_t *ednsversion) {
REQUIRE(DNS_PEER_VALID(peer));
REQUIRE(ednsversion != NULL);
if (DNS_BIT_CHECK(EDNS_VERSION_BIT, &peer->bitflags)) {
*ednsversion = peer->ednsversion;
return (ISC_R_SUCCESS);
} else {
return (ISC_R_NOTFOUND);
}
}

View file

@ -7714,7 +7714,9 @@ resquery_response(isc_result_t eresult, isc_region_t *region, void *arg) {
/*
* If we have had a server cookie and don't get one retry over
* TCP. This may be a misconfigured anycast server or an attempt
* to send a spoofed response. Skip if we have a valid tsig.
* to send a spoofed response. Additionally retry over TCP if
* require-cookie is true and we don't have a got client cookie.
* Skip if we have a valid TSIG.
*/
if (dns_message_gettsig(query->rmessage, NULL) == NULL &&
!query->rmessage->cc_ok && !query->rmessage->cc_bad &&
@ -7739,6 +7741,43 @@ resquery_response(isc_result_t eresult, isc_region_t *region, void *arg) {
rctx.resend = true;
rctx_done(&rctx, result);
return;
} else if (fctx->res->view->peers != NULL) {
dns_peer_t *peer = NULL;
isc_netaddr_t netaddr;
isc_netaddr_fromsockaddr(&netaddr,
&query->addrinfo->sockaddr);
result = dns_peerlist_peerbyaddr(fctx->res->view->peers,
&netaddr, &peer);
if (result == ISC_R_SUCCESS) {
bool required = false;
result = dns_peer_getrequirecookie(peer,
&required);
if (result == ISC_R_SUCCESS && required) {
if (isc_log_wouldlog(dns_lctx,
ISC_LOG_INFO)) {
char addrbuf
[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_format(
&query->addrinfo
->sockaddr,
addrbuf,
sizeof(addrbuf));
isc_log_write(
dns_lctx,
DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER,
ISC_LOG_INFO,
"missing required "
"cookie "
"from %s",
addrbuf);
}
rctx.retryopts |= DNS_FETCHOPT_TCP;
rctx.resend = true;
rctx_done(&rctx, result);
return;
}
}
}
}

View file

@ -2539,6 +2539,7 @@ static cfg_clausedef_t server_clauses[] = {
{ "request-ixfr", &cfg_type_boolean, 0 },
{ "request-nsid", &cfg_type_boolean, 0 },
{ "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "require-cookie", &cfg_type_boolean, 0 },
{ "send-cookie", &cfg_type_boolean, 0 },
{ "support-ixfr", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "tcp-keepalive", &cfg_type_boolean, 0 },