mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-22 18:33:11 -04:00
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:
commit
44235cd2cf
16 changed files with 260 additions and 551 deletions
6
CHANGES
6
CHANGES
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
14
bin/tests/system/cookie/ns7/from-no-cookie-server.example.db
Normal file
14
bin/tests/system/cookie/ns7/from-no-cookie-server.example.db
Normal 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
|
||||
|
|
@ -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";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ options {
|
|||
require-server-cookie yes;
|
||||
};
|
||||
|
||||
server 10.53.0.7 { require-cookie yes; };
|
||||
|
||||
zone "example" {
|
||||
type primary;
|
||||
file "example.db";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
672
lib/dns/peer.c
672
lib/dns/peer.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
Loading…
Reference in a new issue