mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
Merge branch '1641-doh-dig' into 'main'
Resolve "RFC8484, DoH support in DIG (and any other relevant utilities)" Closes #2464 and #1641 See merge request isc-projects/bind9!4672
This commit is contained in:
commit
d6f33fcd6c
4
CHANGES
4
CHANGES
@ -1,3 +1,7 @@
|
||||
5596. [func] Client-side support for DNS-over-HTTPS (DoH) has
|
||||
been added to dig. "dig +https" can now query
|
||||
a server via HTTP/2. [GL #1641]
|
||||
|
||||
5595. [cleanup] Public header files for BIND 9 libraries no longer
|
||||
directly include third-party library headers. This
|
||||
prevents the need to include paths to third-party header
|
||||
|
@ -228,6 +228,10 @@ help(void) {
|
||||
"SERVFAIL)\n"
|
||||
" +[no]header-only (Send query without a "
|
||||
"question section)\n"
|
||||
" +[no]https[=###] (DNS over HTTPS mode) "
|
||||
"[/]\n"
|
||||
" +[no]https-get (Use GET instead of "
|
||||
"default POST method\n"
|
||||
" +[no]identify (ID responders in short "
|
||||
"answers)\n"
|
||||
#ifdef HAVE_LIBIDN2
|
||||
@ -348,12 +352,18 @@ received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
|
||||
}
|
||||
if (query->lookup->tls_mode) {
|
||||
proto = "TLS";
|
||||
} else if (query->lookup->https_mode) {
|
||||
if (query->lookup->http_plain) {
|
||||
proto = "HTTP";
|
||||
} else {
|
||||
proto = "HTTPS";
|
||||
}
|
||||
} else if (query->lookup->tcp_mode) {
|
||||
proto = "TCP";
|
||||
} else {
|
||||
proto = "UDP";
|
||||
}
|
||||
printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->servname,
|
||||
printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->userarg,
|
||||
proto);
|
||||
time(&tnow);
|
||||
(void)localtime_r(&tnow, &tmnow);
|
||||
@ -1066,6 +1076,17 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
|
||||
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
#define FULLCHECK6(A, B, C, D, E, F) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
|
||||
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0) && \
|
||||
(_l >= sizeof(C) || strncasecmp(cmd, C, _l) != 0) && \
|
||||
(_l >= sizeof(D) || strncasecmp(cmd, D, _l) != 0) && \
|
||||
(_l >= sizeof(E) || strncasecmp(cmd, E, _l) != 0) && \
|
||||
(_l >= sizeof(F) || strncasecmp(cmd, F, _l) != 0)) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
|
||||
switch (cmd[0]) {
|
||||
case 'a':
|
||||
@ -1412,8 +1433,78 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
|
||||
lookup->servfail_stops = state;
|
||||
break;
|
||||
case 'h':
|
||||
FULLCHECK("header-only");
|
||||
lookup->header_only = state;
|
||||
switch (cmd[1]) {
|
||||
case 'e': /* header-only */
|
||||
FULLCHECK("header-only");
|
||||
lookup->header_only = state;
|
||||
break;
|
||||
case 't':
|
||||
FULLCHECK6("https", "https-get", "https-post",
|
||||
"http-plain", "http-plain-get",
|
||||
"http-plain-post");
|
||||
if (lookup->https_path != NULL) {
|
||||
isc_mem_free(mctx, lookup->https_path);
|
||||
lookup->https_path = NULL;
|
||||
}
|
||||
if (!state) {
|
||||
lookup->https_mode = false;
|
||||
break;
|
||||
}
|
||||
lookup->https_mode = true;
|
||||
if (cmd[4] == '-') {
|
||||
lookup->http_plain = true;
|
||||
switch (cmd[10]) {
|
||||
case '\0':
|
||||
FULLCHECK("http-plain");
|
||||
break;
|
||||
case '-':
|
||||
switch (cmd[6]) {
|
||||
case 'p':
|
||||
FULLCHECK("https-plain-post");
|
||||
break;
|
||||
case 'g':
|
||||
FULLCHECK("https-plain-get");
|
||||
lookup->https_get = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
} else {
|
||||
switch (cmd[5]) {
|
||||
case '\0':
|
||||
FULLCHECK("https");
|
||||
break;
|
||||
case '-':
|
||||
switch (cmd[6]) {
|
||||
case 'p':
|
||||
FULLCHECK("https-post");
|
||||
break;
|
||||
case 'g':
|
||||
FULLCHECK("https-get");
|
||||
lookup->https_get = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
}
|
||||
if (!lookup->tcp_mode_set) {
|
||||
lookup->tcp_mode = state;
|
||||
}
|
||||
if (value == NULL) {
|
||||
lookup->https_path = isc_mem_strdup(
|
||||
mctx, DEFAULT_HTTPS_PATH);
|
||||
} else {
|
||||
lookup->https_path = isc_mem_strdup(mctx,
|
||||
value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
switch (cmd[1]) {
|
||||
|
@ -349,11 +349,38 @@ abbreviation is unambiguous; for example, ``+cd`` is equivalent to
|
||||
default is to add a question section. The query type and query name
|
||||
are ignored when this is set.
|
||||
|
||||
``+[no]https[=value]``
|
||||
This option indicates whether to use DNS-over-HTTPS (DoH) when querying
|
||||
name servers. When this option is in use, the port number defaults to 443.
|
||||
The HTTP POST request mode is used when sending the query.
|
||||
|
||||
If ``value`` is specified, it will be used as the HTTP endpoint in the
|
||||
query URI; the default is ``/dns-query``. So, for example, ``dig
|
||||
@example.com +https`` will use the URI ``https://example.com/dns-query``.
|
||||
|
||||
``+[no]https-get[=value]``
|
||||
Similar to ``+https``, except that the HTTP GET request mode is used
|
||||
when sending the query.
|
||||
|
||||
``+[no]https-post[=value]``
|
||||
Same as ``+https``.
|
||||
|
||||
``+[no]http-plain[=value]``
|
||||
Similar to ``+https``, except that HTTP queries will be sent over a
|
||||
non-encrypted channel. When this option is in use, the port number
|
||||
defaults to 80 and the HTTP request mode is POST.
|
||||
|
||||
``+[no]http-plain-get[=value]``
|
||||
Similar to ``+http-plain``, except that the HTTP request mode is GET.
|
||||
|
||||
``+[no]http-plain-post[=value]``
|
||||
Same as ``+http-plain``.
|
||||
|
||||
``+[no]identify``
|
||||
This option shows [or does not show] the IP address and port number that supplied
|
||||
the answer, when the ``+short`` option is enabled. If short form
|
||||
answers are requested, the default is not to show the source address
|
||||
and port number of the server that provided the answer.
|
||||
This option shows [or does not show] the IP address and port number that
|
||||
supplied the answer, when the ``+short`` option is enabled. If short
|
||||
form answers are requested, the default is not to show the source
|
||||
address and port number of the server that provided the answer.
|
||||
|
||||
``+[no]idnin``
|
||||
This option processes [or does not process] IDN domain names on input. This requires
|
||||
@ -519,8 +546,9 @@ abbreviation is unambiguous; for example, ``+cd`` is equivalent to
|
||||
5 seconds. An attempt to set ``T`` to less than 1 is silently set to 1.
|
||||
|
||||
``+[no]tls``
|
||||
This option indicates whether to use DNS over TLS (DoT) when querying
|
||||
name servers.
|
||||
This option indicates whether to use DNS-over-TLS (DoT) when querying
|
||||
name servers. When this option is in use, the port number defaults
|
||||
to 853.
|
||||
|
||||
``+[no]topdown``
|
||||
This feature is related to ``dig +sigchase``, which is obsolete and
|
||||
|
@ -603,102 +603,43 @@ clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
|
||||
dig_lookup_t *
|
||||
make_empty_lookup(void) {
|
||||
dig_lookup_t *looknew;
|
||||
#ifdef HAVE_LIBIDN2
|
||||
bool idn_allowed = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
|
||||
#endif /* HAVE_LIBIDN2 */
|
||||
|
||||
debug("make_empty_lookup()");
|
||||
|
||||
INSIST(!free_now);
|
||||
|
||||
looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
|
||||
looknew->pending = true;
|
||||
looknew->textname[0] = 0;
|
||||
looknew->cmdline[0] = 0;
|
||||
looknew->rdtype = dns_rdatatype_a;
|
||||
looknew->qrdtype = dns_rdatatype_a;
|
||||
looknew->rdclass = dns_rdataclass_in;
|
||||
looknew->rdtypeset = false;
|
||||
looknew->rdclassset = false;
|
||||
looknew->sendspace = NULL;
|
||||
looknew->sendmsg = NULL;
|
||||
looknew->name = NULL;
|
||||
looknew->oname = NULL;
|
||||
looknew->xfr_q = NULL;
|
||||
looknew->current_query = NULL;
|
||||
looknew->doing_xfr = false;
|
||||
looknew->ixfr_serial = 0;
|
||||
looknew->trace = false;
|
||||
looknew->trace_root = false;
|
||||
looknew->identify = false;
|
||||
looknew->identify_previous_line = false;
|
||||
looknew->ignore = false;
|
||||
looknew->servfail_stops = true;
|
||||
looknew->besteffort = true;
|
||||
looknew->dns64prefix = false;
|
||||
looknew->dnssec = false;
|
||||
looknew->ednsflags = 0;
|
||||
looknew->opcode = dns_opcode_query;
|
||||
looknew->expire = false;
|
||||
looknew->nsid = false;
|
||||
looknew->tcp_keepalive = false;
|
||||
looknew->padding = 0;
|
||||
looknew->header_only = false;
|
||||
looknew->sendcookie = false;
|
||||
looknew->seenbadcookie = false;
|
||||
looknew->badcookie = true;
|
||||
looknew->multiline = false;
|
||||
looknew->nottl = false;
|
||||
looknew->noclass = false;
|
||||
looknew->onesoa = false;
|
||||
looknew->use_usec = false;
|
||||
looknew->nocrypto = false;
|
||||
looknew->ttlunits = false;
|
||||
looknew->expandaaaa = false;
|
||||
looknew->qr = false;
|
||||
looknew = isc_mem_allocate(mctx, sizeof(*looknew));
|
||||
*looknew = (dig_lookup_t){
|
||||
.pending = true,
|
||||
.rdtype = dns_rdatatype_a,
|
||||
.qrdtype = dns_rdatatype_a,
|
||||
.rdclass = dns_rdataclass_in,
|
||||
.servfail_stops = true,
|
||||
.besteffort = true,
|
||||
.opcode = dns_opcode_query,
|
||||
.badcookie = true,
|
||||
#ifdef HAVE_LIBIDN2
|
||||
looknew->idnin = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
|
||||
looknew->idnout = looknew->idnin;
|
||||
#else /* ifdef HAVE_LIBIDN2 */
|
||||
looknew->idnin = false;
|
||||
looknew->idnout = false;
|
||||
.idnin = idn_allowed,
|
||||
.idnout = idn_allowed,
|
||||
#endif /* HAVE_LIBIDN2 */
|
||||
looknew->udpsize = -1;
|
||||
looknew->edns = -1;
|
||||
looknew->recurse = true;
|
||||
looknew->aaonly = false;
|
||||
looknew->adflag = false;
|
||||
looknew->cdflag = false;
|
||||
looknew->raflag = false;
|
||||
looknew->tcflag = false;
|
||||
looknew->print_unknown_format = false;
|
||||
looknew->zflag = false;
|
||||
looknew->setqid = false;
|
||||
looknew->qid = 0;
|
||||
looknew->ns_search_only = false;
|
||||
looknew->origin = NULL;
|
||||
looknew->tsigctx = NULL;
|
||||
looknew->querysig = NULL;
|
||||
looknew->retries = tries;
|
||||
looknew->nsfound = 0;
|
||||
looknew->tcp_mode = false;
|
||||
looknew->tcp_mode_set = false;
|
||||
looknew->tls_mode = false;
|
||||
looknew->comments = true;
|
||||
looknew->stats = true;
|
||||
looknew->section_question = true;
|
||||
looknew->section_answer = true;
|
||||
looknew->section_authority = true;
|
||||
looknew->section_additional = true;
|
||||
looknew->new_search = false;
|
||||
looknew->done_as_is = false;
|
||||
looknew->need_search = false;
|
||||
looknew->ecs_addr = NULL;
|
||||
looknew->cookie = NULL;
|
||||
looknew->ednsopts = NULL;
|
||||
looknew->ednsoptscnt = 0;
|
||||
looknew->ednsneg = true;
|
||||
looknew->mapped = true;
|
||||
looknew->dscp = -1;
|
||||
looknew->rrcomments = 0;
|
||||
looknew->eoferr = 0;
|
||||
.udpsize = -1,
|
||||
.edns = -1,
|
||||
.recurse = true,
|
||||
.retries = tries,
|
||||
.comments = true,
|
||||
.stats = true,
|
||||
.section_question = true,
|
||||
.section_answer = true,
|
||||
.section_authority = true,
|
||||
.section_additional = true,
|
||||
.ednsneg = true,
|
||||
.mapped = true,
|
||||
.dscp = -1,
|
||||
};
|
||||
|
||||
dns_fixedname_init(&looknew->fdomain);
|
||||
ISC_LINK_INIT(looknew, link);
|
||||
ISC_LIST_INIT(looknew->q);
|
||||
@ -787,6 +728,12 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
|
||||
looknew->nsid = lookold->nsid;
|
||||
looknew->tcp_keepalive = lookold->tcp_keepalive;
|
||||
looknew->header_only = lookold->header_only;
|
||||
looknew->https_mode = lookold->https_mode;
|
||||
if (lookold->https_path != NULL) {
|
||||
looknew->https_path = isc_mem_strdup(mctx, lookold->https_path);
|
||||
}
|
||||
looknew->https_get = lookold->https_get;
|
||||
looknew->http_plain = lookold->http_plain;
|
||||
looknew->sendcookie = lookold->sendcookie;
|
||||
looknew->seenbadcookie = lookold->seenbadcookie;
|
||||
looknew->badcookie = lookold->badcookie;
|
||||
@ -1638,6 +1585,10 @@ _destroy_lookup(dig_lookup_t *lookup) {
|
||||
isc_mem_free(mctx, lookup->ednsopts);
|
||||
}
|
||||
|
||||
if (lookup->https_path) {
|
||||
isc_mem_free(mctx, lookup->https_path);
|
||||
}
|
||||
|
||||
isc_mem_free(mctx, lookup);
|
||||
}
|
||||
|
||||
@ -2760,7 +2711,20 @@ start_tcp(dig_query_t *query) {
|
||||
* For TLS connections, we want to override the default
|
||||
* port number.
|
||||
*/
|
||||
port = port_set ? port : (query->lookup->tls_mode ? 853 : 53);
|
||||
if (!port_set) {
|
||||
if (query->lookup->tls_mode) {
|
||||
port = 853;
|
||||
} else if (query->lookup->https_mode &&
|
||||
!query->lookup->http_plain) {
|
||||
port = 443;
|
||||
} else if (query->lookup->https_mode) {
|
||||
port = 80;
|
||||
} else {
|
||||
port = 53;
|
||||
}
|
||||
}
|
||||
|
||||
debug("query->servname = %s\n", query->servname);
|
||||
|
||||
result = get_address(query->servname, port, &query->sockaddr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@ -2835,7 +2799,27 @@ start_tcp(dig_query_t *query) {
|
||||
(isc_nmiface_t *)&query->sockaddr,
|
||||
tcp_connected, query, local_timeout, 0,
|
||||
query->tlsctx);
|
||||
check_result(result, "isc_nm_tcpdnsconnect");
|
||||
check_result(result, "isc_nm_tlsdnsconnect");
|
||||
} else if (query->lookup->https_mode) {
|
||||
char uri[4096] = { 0 };
|
||||
snprintf(uri, sizeof(uri), "https://%s:%u%s",
|
||||
query->userarg, (uint16_t)port,
|
||||
query->lookup->https_path);
|
||||
|
||||
if (!query->lookup->http_plain) {
|
||||
result =
|
||||
isc_tlsctx_createclient(&query->tlsctx);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
isc_tlsctx_enable_http2client_alpn(
|
||||
query->tlsctx);
|
||||
}
|
||||
|
||||
result = isc_nm_httpconnect(
|
||||
netmgr, (isc_nmiface_t *)&localaddr,
|
||||
(isc_nmiface_t *)&query->sockaddr, uri,
|
||||
!query->lookup->https_get, tcp_connected, query,
|
||||
query->tlsctx, local_timeout, 0);
|
||||
check_result(result, "isc_nm_httpconnect");
|
||||
} else {
|
||||
result = isc_nm_tcpdnsconnect(
|
||||
netmgr, (isc_nmiface_t *)&localaddr,
|
||||
@ -3211,6 +3195,7 @@ launch_next_query(dig_query_t *query) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lookup_detach(&l);
|
||||
return;
|
||||
}
|
||||
@ -3582,8 +3567,7 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||
isc_sockaddr_t peer;
|
||||
|
||||
REQUIRE(DIG_VALID_QUERY(query));
|
||||
INSIST(query->readhandle != NULL);
|
||||
INSIST(handle == query->readhandle);
|
||||
REQUIRE(query->readhandle != NULL);
|
||||
INSIST(!free_now);
|
||||
|
||||
debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult),
|
||||
|
@ -76,6 +76,9 @@
|
||||
#define DEFAULT_EDNS_VERSION 0
|
||||
#define DEFAULT_EDNS_BUFSIZE 1232
|
||||
|
||||
#define DEFAULT_HTTPS_PATH "/dns-query"
|
||||
#define DEFAULT_HTTPS_QUERY "?dns="
|
||||
|
||||
/*%
|
||||
* Lookup_limit is just a limiter, keeping too many lookups from being
|
||||
* created. It's job is mainly to prevent the program from running away
|
||||
@ -168,6 +171,12 @@ struct dig_lookup {
|
||||
int rrcomments;
|
||||
unsigned int eoferr;
|
||||
uint16_t qid;
|
||||
struct {
|
||||
bool http_plain;
|
||||
bool https_mode;
|
||||
bool https_get;
|
||||
char *https_path;
|
||||
};
|
||||
};
|
||||
|
||||
/*% The dig_query structure */
|
||||
|
@ -64,7 +64,7 @@ add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
|
||||
|
||||
create_name(dohid, &dohname);
|
||||
|
||||
transport = dns_transport_new(&dohname, DNS_TRANSPORT_DOH,
|
||||
transport = dns_transport_new(&dohname, DNS_TRANSPORT_HTTP,
|
||||
list);
|
||||
|
||||
parse_transport_option(doh, transport, "key-file",
|
||||
|
@ -95,6 +95,7 @@ TESTS += \
|
||||
dlz \
|
||||
dlzexternal \
|
||||
dns64 \
|
||||
doth \
|
||||
dscp \
|
||||
dsdigest \
|
||||
dyndb \
|
||||
@ -153,7 +154,6 @@ TESTS += \
|
||||
views \
|
||||
wildcard \
|
||||
xferquota \
|
||||
xot \
|
||||
zonechecks
|
||||
|
||||
# The "stress" test is not run by default since it creates enough
|
||||
@ -176,7 +176,6 @@ TESTS += \
|
||||
nsupdate \
|
||||
resolver \
|
||||
statistics \
|
||||
dot \
|
||||
upforwd \
|
||||
zero
|
||||
|
||||
|
@ -668,7 +668,7 @@ copy_setports() {
|
||||
atsign="@"
|
||||
sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \
|
||||
-e "s/${atsign}TLSPORT${atsign}/${TLSPORT}/g" \
|
||||
-e "s/${atsign}HTTPPORT${atsign}/${HTTPSPORT}/g" \
|
||||
-e "s/${atsign}HTTPPORT${atsign}/${HTTPPORT}/g" \
|
||||
-e "s/${atsign}HTTPSPORT${atsign}/${HTTPSPORT}/g" \
|
||||
-e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
|
||||
-e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/g" \
|
||||
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
rm -f */named.memstats
|
||||
rm -f */named.run
|
||||
rm -f */named.conf
|
||||
rm -f */named.stats*
|
||||
rm -f dig.out*
|
||||
rm -f rndc.out*
|
||||
rm -f ns*/named.lock
|
||||
rm -f ns*/managed-keys.bind*
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
options {
|
||||
port @PORT@;
|
||||
tls-port @TLSPORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
listen-on tls ephemeral { 10.53.0.1; };
|
||||
recursion no;
|
||||
notify no;
|
||||
statistics-file "named.stats";
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db";
|
||||
allow-transfer { any; };
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
$SHELL clean.sh
|
||||
|
||||
copy_setports ns1/named.conf.in ns1/named.conf
|
@ -1,41 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
set -e
|
||||
|
||||
# shellcheck source=../conf.sh
|
||||
. ../conf.sh
|
||||
|
||||
dig_dot_with_opts() {
|
||||
"${DIG}" -p "${TLSPORT}" +tls "$@"
|
||||
}
|
||||
|
||||
status=0
|
||||
n=0
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoT query response ($n)"
|
||||
ret=0
|
||||
dig_dot_with_opts @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoT XFR ($n)"
|
||||
ret=0
|
||||
dig_dot_with_opts +comment @10.53.0.1 . AXFR > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
@ -18,4 +18,4 @@ rm -f ./*/named.memstats
|
||||
rm -f ./*/named.run
|
||||
rm -f ./*/named.run.prev
|
||||
rm -f ./dig.out.*
|
||||
rm -f ./*/*.db
|
||||
rm -f ./*/example.db
|
@ -15,13 +15,21 @@ controls {
|
||||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
http local {
|
||||
endpoints { "/dns-query"; "/alter"; };
|
||||
};
|
||||
|
||||
options {
|
||||
port @PORT@;
|
||||
tls-port @TLSPORT@;
|
||||
https-port @HTTPSPORT@;
|
||||
http-port @HTTPPORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on tls ephemeral { 10.53.0.1; }; // DoT
|
||||
listen-on tls ephemeral http local { 10.53.0.1; }; // DoH
|
||||
listen-on tls none http local { 10.53.0.1; }; // unencrypted DoH
|
||||
listen-on-v6 { none; };
|
||||
listen-on tls ephemeral { 10.53.0.1; };
|
||||
recursion no;
|
||||
notify explicit;
|
||||
also-notify { 10.53.0.2 port @PORT@; };
|
||||
@ -30,8 +38,9 @@ options {
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
type primary;
|
||||
file "root.db";
|
||||
allow-transfer { any; };
|
||||
};
|
||||
|
||||
zone "example" {
|
14
bin/tests/system/doth/ns2/cert.pem
Normal file
14
bin/tests/system/doth/ns2/cert.pem
Normal file
@ -0,0 +1,14 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICHTCCAcOgAwIBAgIUATq1E48Hj7vAQBwn8H/1oQvqvJ0wCgYIKoZIzj0EAwIw
|
||||
YzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENp
|
||||
dHkxDDAKBgNVBAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2Fs
|
||||
aG9zdDAgFw0yMTAyMTIwMzIxMzFaGA8yMTIxMDExOTAzMjEzMVowYzELMAkGA1UE
|
||||
BhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDDAKBgNV
|
||||
BAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMG
|
||||
ByqGSM49AgEGCCqGSM49AwEHA0IABC1uCviud7QFTJ8DfdrLwjkBolYHJJR9c9HP
|
||||
bshvKDXahhRU9+HCbWBNLlqFR6aMs8wyE32cXHLZ70XaILkH88SjUzBRMB0GA1Ud
|
||||
DgQWBBRPpE9aC2MO0TAlCp18vR9vqe4R2TAfBgNVHSMEGDAWgBRPpE9aC2MO0TAl
|
||||
Cp18vR9vqe4R2TAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIE3L
|
||||
zx4iRVqjnOACc+/G0Shru+AIk/MEglfrvP5wxZaVAiEArcmut+hYb+cG0UW5ct/U
|
||||
Q183Kk25XYJkTj39GSBiiiA=
|
||||
-----END CERTIFICATE-----
|
8
bin/tests/system/doth/ns2/key.pem
Normal file
8
bin/tests/system/doth/ns2/key.pem
Normal file
@ -0,0 +1,8 @@
|
||||
-----BEGIN EC PARAMETERS-----
|
||||
BggqhkjOPQMBBw==
|
||||
-----END EC PARAMETERS-----
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIFBLYPWvhrGBMyfi04oC53LOl00LZRZbVOVnC0K30XOCoAoGCCqGSM49
|
||||
AwEHoUQDQgAELW4K+K53tAVMnwN92svCOQGiVgcklH1z0c9uyG8oNdqGFFT34cJt
|
||||
YE0uWoVHpoyzzDITfZxcctnvRdoguQfzxA==
|
||||
-----END EC PRIVATE KEY-----
|
@ -15,17 +15,29 @@ controls {
|
||||
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
tls local {
|
||||
key-file "key.pem";
|
||||
cert-file "cert.pem";
|
||||
};
|
||||
|
||||
http local {
|
||||
endpoints { "/dns-query"; };
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port @PORT@;
|
||||
tls-port @TLSPORT@;
|
||||
https-port @HTTPSPORT@;
|
||||
http-port @HTTPPORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on tls ephemeral { 10.53.0.2; };
|
||||
listen-on tls local { 10.53.0.2; }; // DoT
|
||||
listen-on tls local http local { 10.53.0.2; }; // DoH
|
||||
listen-on tls none http local { 10.53.0.2; }; // unencrypted DoH
|
||||
listen-on-v6 { none; };
|
||||
listen-on tls ephemeral { 10.53.0.2; };
|
||||
recursion no;
|
||||
notify no;
|
||||
ixfr-from-differences yes;
|
186
bin/tests/system/doth/tests.sh
Normal file
186
bin/tests/system/doth/tests.sh
Normal file
@ -0,0 +1,186 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
dig_with_tls_opts() {
|
||||
"$DIG" +tls +noadd +nosea +nostat +noquest +nocmd -p "${TLSPORT}" "$@"
|
||||
}
|
||||
|
||||
dig_with_https_opts() {
|
||||
"$DIG" +https +noadd +nosea +nostat +noquest +nocmd -p "${HTTPSPORT}" "$@"
|
||||
}
|
||||
|
||||
dig_with_http_opts() {
|
||||
"$DIG" +http-plain +noadd +nosea +nostat +noquest +nocmd -p "${HTTPPORT}" "$@"
|
||||
}
|
||||
|
||||
wait_for_tls_xfer() (
|
||||
dig_with_tls_opts -b 10.53.0.3 @10.53.0.2 example. AXFR > "dig.out.ns2.test$n" || return 1
|
||||
grep "^;" "dig.out.ns2.test$n" > /dev/null && return 1
|
||||
return 0
|
||||
)
|
||||
|
||||
status=0
|
||||
n=0
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing XoT server functionality (using dig) ($n)"
|
||||
ret=0
|
||||
dig_with_tls_opts example. -b 10.53.0.3 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
|
||||
grep "^;" dig.out.ns1.test$n | cat_i
|
||||
digcomp dig1.good dig.out.ns1.test$n || ret=1
|
||||
if test $ret != 0 ; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing incoming XoT functionality (from secondary) ($n)"
|
||||
ret=0
|
||||
if retry_quiet 10 wait_for_tls_xfer; then
|
||||
grep "^;" "dig.out.ns2.test$n" | cat_i
|
||||
digcomp dig1.good "dig.out.ns2.test$n" || ret=1
|
||||
else
|
||||
echo_i "timed out waiting for zone transfer"
|
||||
ret=1
|
||||
fi
|
||||
if test $ret != 0 ; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoT query (ephemeral key) ($n)"
|
||||
ret=0
|
||||
dig_with_tls_opts @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoT query (static key) ($n)"
|
||||
ret=0
|
||||
dig_with_tls_opts @10.53.0.2 example SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoT XFR ($n)"
|
||||
ret=0
|
||||
dig_with_tls_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (POST) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (POST, static key) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts @10.53.0.2 example SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (POST, nonstandard endpoint) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +https=/alter @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (POST, undefined endpoint, failure expected) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +tries=1 +time=1 +https=/fake @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "communications error" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH XFR (POST) (failure expected) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
|
||||
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (GET) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +https-get @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (GET, static key) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +https-get @10.53.0.2 example SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (GET, nonstandard endpoint) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +https-get=/alter @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH query (GET, undefined endpoint, failure expected) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +tries=1 +time=1 +https-get=/fake @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "communications error" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking DoH XFR (GET) (failure expected) ($n)"
|
||||
ret=0
|
||||
dig_with_https_opts +https-get +comm @10.53.0.1 . AXFR > dig.out.test$n
|
||||
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking unencrypted DoH query (POST) ($n)"
|
||||
ret=0
|
||||
dig_with_http_opts @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking unencrypted DoH query (GET) ($n)"
|
||||
ret=0
|
||||
dig_with_http_opts +http-plain-get @10.53.0.1 . SOA > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking unencrypted DoH XFR (failure expected) ($n)"
|
||||
ret=0
|
||||
dig_with_http_opts +comm @10.53.0.1 . AXFR > dig.out.test$n
|
||||
grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
@ -1,50 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 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 https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
. ../conf.sh
|
||||
|
||||
dig_with_opts() {
|
||||
"$DIG" +tls +noadd +nosea +nostat +noquest +nocomm +nocmd -p "${TLSPORT}" "$@"
|
||||
}
|
||||
|
||||
wait_for_xfer() (
|
||||
dig_with_opts -b 10.53.0.3 @10.53.0.2 example. AXFR > "dig.out.ns2.test$n" || return 1
|
||||
grep "^;" "dig.out.ns2.test$n" > /dev/null && return 1
|
||||
return 0
|
||||
)
|
||||
|
||||
status=0
|
||||
n=0
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing XoT server functionality (using dig) ($n)"
|
||||
ret=0
|
||||
dig_with_opts example. -b 10.53.0.3 @10.53.0.1 axfr > dig.out.ns1.test$n || ret=1
|
||||
grep "^;" dig.out.ns1.test$n | cat_i
|
||||
digcomp dig1.good dig.out.ns1.test$n || ret=1
|
||||
if test $ret != 0 ; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing basic incoming XoT functionality (from secondary) ($n)"
|
||||
ret=0
|
||||
if retry_quiet 10 wait_for_xfer; then
|
||||
grep "^;" "dig.out.ns2.test$n" | cat_i
|
||||
digcomp dig1.good "dig.out.ns2.test$n" || ret=1
|
||||
else
|
||||
echo_i "timed out waiting for zone transfer"
|
||||
ret=1
|
||||
fi
|
||||
if test $ret != 0 ; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
@ -27,13 +27,27 @@
|
||||
#include <isc/netaddr.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
typedef enum { UDP, TCP, DOT, DOH } protocol_t;
|
||||
#define DEFAULT_DOH_PATH "/dns-query"
|
||||
|
||||
static const char *protocols[] = { "udp", "tcp", "dot", "doh" };
|
||||
typedef enum {
|
||||
UDP,
|
||||
TCP,
|
||||
DOT,
|
||||
HTTPS_POST,
|
||||
HTTPS_GET,
|
||||
HTTP_POST,
|
||||
HTTP_GET
|
||||
} protocol_t;
|
||||
|
||||
static const char *protocols[] = { "udp", "tcp",
|
||||
"dot", "https-post",
|
||||
"https-get", "http-plain-post",
|
||||
"http-plain-get" };
|
||||
|
||||
static isc_mem_t *mctx = NULL;
|
||||
static isc_nm_t *netmgr = NULL;
|
||||
@ -50,6 +64,8 @@ static uint8_t messagebuf[2 * 65536];
|
||||
static isc_region_t message = { .length = 0, .base = messagebuf };
|
||||
static int out = -1;
|
||||
|
||||
static isc_tlsctx_t *tls_ctx = NULL;
|
||||
|
||||
static isc_result_t
|
||||
parse_port(const char *input) {
|
||||
char *endptr = NULL;
|
||||
@ -304,6 +320,9 @@ teardown(void) {
|
||||
|
||||
isc_nm_destroy(&netmgr);
|
||||
isc_mem_destroy(&mctx);
|
||||
if (tls_ctx) {
|
||||
isc_tlsctx_free(&tls_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -374,6 +393,33 @@ connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
|
||||
isc_nm_send(handle, &message, send_cb, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf,
|
||||
size_t outbuf_len, const char *append) {
|
||||
uint16_t sa_port;
|
||||
char saddr[INET6_ADDRSTRLEN] = { 0 };
|
||||
int sa_family;
|
||||
|
||||
if (sa == NULL || outbuf == NULL || outbuf_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sa_family = ((struct sockaddr *)&sa->type.sa)->sa_family;
|
||||
|
||||
sa_port = ntohs(sa_family == AF_INET ? sa->type.sin.sin_port
|
||||
: sa->type.sin6.sin6_port);
|
||||
inet_ntop(sa_family,
|
||||
sa_family == AF_INET
|
||||
? (struct sockaddr *)&sa->type.sin.sin_addr
|
||||
: (struct sockaddr *)&sa->type.sin6.sin6_addr,
|
||||
saddr, sizeof(saddr));
|
||||
|
||||
snprintf(outbuf, outbuf_len, "%s://%s%s%s:%u%s",
|
||||
https ? "https" : "http", sa_family == AF_INET ? "" : "[",
|
||||
saddr, sa_family == AF_INET ? "" : "]", sa_port,
|
||||
append ? append : "");
|
||||
}
|
||||
|
||||
static void
|
||||
run(void) {
|
||||
isc_result_t result;
|
||||
@ -392,19 +438,33 @@ run(void) {
|
||||
connect_cb, NULL, timeout, 0);
|
||||
break;
|
||||
case DOT: {
|
||||
isc_tlsctx_t *tlsdns_ctx = NULL;
|
||||
isc_tlsctx_createclient(&tlsdns_ctx);
|
||||
isc_tlsctx_createclient(&tls_ctx);
|
||||
|
||||
result = isc_nm_tlsdnsconnect(
|
||||
netmgr, (isc_nmiface_t *)&sockaddr_local,
|
||||
(isc_nmiface_t *)&sockaddr_remote, connect_cb, NULL,
|
||||
timeout, 0, tlsdns_ctx);
|
||||
timeout, 0, tls_ctx);
|
||||
break;
|
||||
}
|
||||
case DOH:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
break;
|
||||
case HTTP_GET:
|
||||
case HTTPS_GET:
|
||||
case HTTPS_POST:
|
||||
case HTTP_POST: {
|
||||
bool is_https = (protocol == HTTPS_POST ||
|
||||
protocol == HTTPS_GET);
|
||||
bool is_post = (protocol == HTTPS_POST ||
|
||||
protocol == HTTP_POST);
|
||||
char req_url[256];
|
||||
sockaddr_to_url(&sockaddr_remote, is_https, req_url,
|
||||
sizeof(req_url), DEFAULT_DOH_PATH);
|
||||
if (is_https) {
|
||||
isc_tlsctx_createclient(&tls_ctx);
|
||||
}
|
||||
result = isc_nm_httpconnect(
|
||||
netmgr, (isc_nmiface_t *)&sockaddr_local,
|
||||
(isc_nmiface_t *)&sockaddr_remote, req_url, is_post,
|
||||
connect_cb, NULL, tls_ctx, timeout, 0);
|
||||
} break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
@ -25,9 +25,11 @@
|
||||
#include <isc/string.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
typedef enum { UDP, TCP, DOT, DOH } protocol_t;
|
||||
#define DEFAULT_DOH_PATH "/dns-query"
|
||||
|
||||
static const char *protocols[] = { "udp", "tcp", "dot", "doh" };
|
||||
typedef enum { UDP, TCP, DOT, HTTPS, HTTP } protocol_t;
|
||||
|
||||
static const char *protocols[] = { "udp", "tcp", "dot", "https", "http-plain" };
|
||||
|
||||
static isc_mem_t *mctx = NULL;
|
||||
static isc_nm_t *netmgr = NULL;
|
||||
@ -38,6 +40,8 @@ static isc_netaddr_t netaddr;
|
||||
static isc_sockaddr_t sockaddr __attribute__((unused));
|
||||
static int workers;
|
||||
|
||||
static isc_tlsctx_t *tls_ctx = NULL;
|
||||
|
||||
static void
|
||||
read_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||
void *cbarg);
|
||||
@ -191,6 +195,9 @@ static void
|
||||
teardown(void) {
|
||||
isc_nm_destroy(&netmgr);
|
||||
isc_mem_destroy(&mctx);
|
||||
if (tls_ctx) {
|
||||
isc_tlsctx_free(&tls_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -267,18 +274,26 @@ run(void) {
|
||||
0, NULL, &sock);
|
||||
break;
|
||||
case DOT: {
|
||||
isc_tlsctx_t *tlsdns_ctx = NULL;
|
||||
isc_tlsctx_createserver(NULL, NULL, &tlsdns_ctx);
|
||||
isc_tlsctx_createserver(NULL, NULL, &tls_ctx);
|
||||
|
||||
result = isc_nm_listentlsdns(netmgr, (isc_nmiface_t *)&sockaddr,
|
||||
read_cb, NULL, accept_cb, NULL, 0,
|
||||
0, NULL, tlsdns_ctx, &sock);
|
||||
0, NULL, tls_ctx, &sock);
|
||||
break;
|
||||
}
|
||||
case DOH:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
break;
|
||||
case HTTPS:
|
||||
case HTTP: {
|
||||
bool is_https = protocol == HTTPS;
|
||||
if (is_https) {
|
||||
isc_tlsctx_createserver(NULL, NULL, &tls_ctx);
|
||||
}
|
||||
result = isc_nm_listenhttp(netmgr, (isc_nmiface_t *)&sockaddr,
|
||||
0, NULL, tls_ctx, &sock);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = isc_nm_http_endpoint(sock, DEFAULT_DOH_PATH,
|
||||
read_cb, NULL, 0);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
@ -361,11 +361,38 @@ This option sends a query with a DNS header without a question section. The
|
||||
default is to add a question section. The query type and query name
|
||||
are ignored when this is set.
|
||||
.TP
|
||||
.B \fB+[no]https[=value]\fP
|
||||
This option indicates whether to use DNS\-over\-HTTPS (DoH) when querying
|
||||
name servers. When this option is in use, the port number defaults to 443.
|
||||
The HTTP POST request mode is used when sending the query.
|
||||
.sp
|
||||
If \fBvalue\fP is specified, it will be used as the HTTP endpoint in the
|
||||
query URI; the default is \fB/dns\-query\fP\&. So, for example, \fBdig
|
||||
@example.com +https\fP will use the URI \fBhttps://example.com/dns\-query\fP\&.
|
||||
.TP
|
||||
.B \fB+[no]https\-get[=value]\fP
|
||||
Similar to \fB+https\fP, except that the HTTP GET request mode is used
|
||||
when sending the query.
|
||||
.TP
|
||||
.B \fB+[no]https\-post[=value]\fP
|
||||
Same as \fB+https\fP\&.
|
||||
.TP
|
||||
.B \fB+[no]http\-plain[=value]\fP
|
||||
Similar to \fB+https\fP, except that HTTP queries will be sent over a
|
||||
non\-encrypted channel. When this option is in use, the port number
|
||||
defaults to 80 and the HTTP request mode is POST.
|
||||
.TP
|
||||
.B \fB+[no]http\-plain\-get[=value]\fP
|
||||
Similar to \fB+http\-plain\fP, except that the HTTP request mode is GET.
|
||||
.TP
|
||||
.B \fB+[no]http\-plain\-post[=value]\fP
|
||||
Same as \fB+http\-plain\fP\&.
|
||||
.TP
|
||||
.B \fB+[no]identify\fP
|
||||
This option shows [or does not show] the IP address and port number that supplied
|
||||
the answer, when the \fB+short\fP option is enabled. If short form
|
||||
answers are requested, the default is not to show the source address
|
||||
and port number of the server that provided the answer.
|
||||
This option shows [or does not show] the IP address and port number that
|
||||
supplied the answer, when the \fB+short\fP option is enabled. If short
|
||||
form answers are requested, the default is not to show the source
|
||||
address and port number of the server that provided the answer.
|
||||
.TP
|
||||
.B \fB+[no]idnin\fP
|
||||
This option processes [or does not process] IDN domain names on input. This requires
|
||||
@ -531,8 +558,9 @@ This option sets the timeout for a query to \fBT\fP seconds. The default timeout
|
||||
5 seconds. An attempt to set \fBT\fP to less than 1 is silently set to 1.
|
||||
.TP
|
||||
.B \fB+[no]tls\fP
|
||||
This option indicates whether to use DNS over TLS (DoT) when querying
|
||||
name servers.
|
||||
This option indicates whether to use DNS\-over\-TLS (DoT) when querying
|
||||
name servers. When this option is in use, the port number defaults
|
||||
to 853.
|
||||
.TP
|
||||
.B \fB+[no]topdown\fP
|
||||
This feature is related to \fBdig +sigchase\fP, which is obsolete and
|
||||
|
@ -24,7 +24,8 @@ Known Issues
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
- ``dig`` has been extended to support DNS-over-HTTPS (DoH) queries,
|
||||
using ``dig +https`` and related options. [GL #1641]
|
||||
|
||||
- A new option, ``purge-keys``, has been added to ``dnssec-policy``. It sets
|
||||
the time how long key files should be retained after they have become
|
||||
|
@ -18,14 +18,14 @@ typedef enum {
|
||||
DNS_TRANSPORT_UDP = 1,
|
||||
DNS_TRANSPORT_TCP = 2,
|
||||
DNS_TRANSPORT_TLS = 3,
|
||||
DNS_TRANSPORT_DOH = 4,
|
||||
DNS_TRANSPORT_HTTP = 4,
|
||||
DNS_TRANSPORT_COUNT = 5,
|
||||
} dns_transport_type_t;
|
||||
|
||||
typedef enum {
|
||||
DNS_DOH_GET = 0,
|
||||
DNS_DOH_POST = 1,
|
||||
} dns_doh_mode_t;
|
||||
DNS_HTTP_GET = 0,
|
||||
DNS_HTTP_POST = 1,
|
||||
} dns_http_mode_t;
|
||||
|
||||
typedef struct dns_transport dns_transport_t;
|
||||
typedef struct dns_transport_list dns_transport_list_t;
|
||||
@ -50,11 +50,11 @@ char *
|
||||
dns_transport_get_hostname(dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_endpoint(dns_transport_t *transport);
|
||||
dns_doh_mode_t
|
||||
dns_http_mode_t
|
||||
dns_transport_get_mode(dns_transport_t *transport);
|
||||
/*%<
|
||||
* Getter functions: return the type, cert file, key file, CA file,
|
||||
* hostname, DoH endpoint, or DoH mode (GET or POST) for 'transport'.
|
||||
* hostname, HTTP endpoint, or HTTP mode (GET or POST) for 'transport'.
|
||||
*/
|
||||
|
||||
void
|
||||
@ -68,16 +68,16 @@ dns_transport_set_hostname(dns_transport_t *transport, const char *hostname);
|
||||
void
|
||||
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint);
|
||||
void
|
||||
dns_transport_set_mode(dns_transport_t *transport, dns_doh_mode_t mode);
|
||||
dns_transport_set_mode(dns_transport_t *transport, dns_http_mode_t mode);
|
||||
/*%<
|
||||
* Setter functions: set the type, cert file, key file, CA file,
|
||||
* hostname, DoH endpoint, or DoH mode (GET or POST) for 'transport'.
|
||||
* hostname, HTTP endpoint, or HTTP mode (GET or POST) for 'transport'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'transport' is valid.
|
||||
*\li 'transport' is of type DNS_TRANSPORT_TLS or DNS_TRANSPORT_DOH
|
||||
*\li 'transport' is of type DNS_TRANSPORT_TLS or DNS_TRANSPORT_HTTP
|
||||
* (for certfile, keyfile, cafile, or hostname).
|
||||
*\li 'transport' is of type DNS_TRANSPORT_DOH (for endpoint or mode).
|
||||
*\li 'transport' is of type DNS_TRANSPORT_HTTP (for endpoint or mode).
|
||||
*/
|
||||
|
||||
void
|
||||
|
@ -50,7 +50,7 @@ struct dns_transport {
|
||||
} tls;
|
||||
struct {
|
||||
char *endpoint;
|
||||
dns_doh_mode_t mode;
|
||||
dns_http_mode_t mode;
|
||||
} doh;
|
||||
};
|
||||
|
||||
@ -124,7 +124,7 @@ dns_transport_get_endpoint(dns_transport_t *transport) {
|
||||
return (transport->doh.endpoint);
|
||||
}
|
||||
|
||||
dns_doh_mode_t
|
||||
dns_http_mode_t
|
||||
dns_transport_get_mode(dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
@ -150,7 +150,7 @@ void
|
||||
dns_transport_set_certfile(dns_transport_t *transport, const char *certfile) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_DOH);
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (certfile != NULL) {
|
||||
transport->tls.certfile = isc_mem_strdup(transport->mctx,
|
||||
@ -162,7 +162,7 @@ void
|
||||
dns_transport_set_keyfile(dns_transport_t *transport, const char *keyfile) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_DOH);
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (keyfile != NULL) {
|
||||
transport->tls.keyfile = isc_mem_strdup(transport->mctx,
|
||||
@ -174,7 +174,7 @@ void
|
||||
dns_transport_set_cafile(dns_transport_t *transport, const char *cafile) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_DOH);
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (cafile != NULL) {
|
||||
transport->tls.cafile = isc_mem_strdup(transport->mctx, cafile);
|
||||
@ -185,7 +185,7 @@ void
|
||||
dns_transport_set_hostname(dns_transport_t *transport, const char *hostname) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_DOH);
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (hostname != NULL) {
|
||||
transport->tls.hostname = isc_mem_strdup(transport->mctx,
|
||||
@ -196,7 +196,7 @@ dns_transport_set_hostname(dns_transport_t *transport, const char *hostname) {
|
||||
void
|
||||
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_DOH);
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (endpoint != NULL) {
|
||||
transport->doh.endpoint = isc_mem_strdup(transport->mctx,
|
||||
@ -205,9 +205,9 @@ dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
||||
}
|
||||
|
||||
void
|
||||
dns_transport_set_mode(dns_transport_t *transport, dns_doh_mode_t mode) {
|
||||
dns_transport_set_mode(dns_transport_t *transport, dns_http_mode_t mode) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_DOH);
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
transport->doh.mode = mode;
|
||||
}
|
||||
|
@ -506,45 +506,17 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
* 'cb'.
|
||||
*/
|
||||
|
||||
typedef void (*isc_nm_http_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *data, void *cbarg);
|
||||
/*%<
|
||||
* Callback function to be used when receiving an HTTP request.
|
||||
*
|
||||
* 'handle' the handle that can be used to send back the answer.
|
||||
* 'eresult' the result of the event.
|
||||
* 'data' contains the received data, if any. It will be freed
|
||||
* after return by caller.
|
||||
* 'cbarg' the callback argument passed to listen function.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_nm_http_connect_send_request(isc_nm_t *mgr, const char *uri, bool POST,
|
||||
isc_region_t *message, isc_nm_recv_cb_t cb,
|
||||
void *cbarg, isc_tlsctx_t *ctx,
|
||||
unsigned int timeout);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg,
|
||||
isc_tlsctx_t *ctx, unsigned int timeout,
|
||||
size_t extrahandlesize);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_httprequest(isc_nmhandle_t *handle, isc_region_t *region,
|
||||
isc_nm_recv_cb_t reply_cb, void *cbarg);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog,
|
||||
isc_quota_t *quota, isc_tlsctx_t *ctx,
|
||||
isc_nmsocket_t **sockp);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_http_add_endpoint(isc_nmsocket_t *sock, const char *uri,
|
||||
isc_nm_http_cb_t cb, void *cbarg,
|
||||
size_t extrahandlesize);
|
||||
|
||||
isc_result_t
|
||||
isc_nm_http_add_doh_endpoint(isc_nmsocket_t *sock, const char *uri,
|
||||
isc_nm_recv_cb_t cb, void *cbarg,
|
||||
size_t extrahandlesize);
|
||||
isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
|
||||
void *cbarg, size_t extrahandlesize);
|
||||
|
@ -89,9 +89,10 @@
|
||||
#define ISC_R_DEFAULT 68 /*%< default */
|
||||
#define ISC_R_IPV4PREFIX 69 /*%< IPv4 prefix */
|
||||
#define ISC_R_TLSERROR 70 /*%< TLS error */
|
||||
#define ISC_R_HTTP2ALPNERROR 71 /*%< ALPN for HTTP/2 failed */
|
||||
|
||||
/*% Not a result code: the number of results. */
|
||||
#define ISC_R_NRESULTS 71
|
||||
#define ISC_R_NRESULTS 72
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
|
@ -14,35 +14,72 @@
|
||||
#include <isc/mem.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/tls.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
typedef struct ssl_ctx_st isc_tlsctx_t;
|
||||
typedef struct ssl_st isc_tls_t;
|
||||
|
||||
void
|
||||
isc_tlsctx_free(isc_tlsctx_t **ctpx);
|
||||
/*%
|
||||
* Free the TLS client/server context.
|
||||
/*%<
|
||||
* Free a TLS client or server context.
|
||||
*
|
||||
* Require:
|
||||
* Requires:
|
||||
*\li 'ctxp' != NULL and '*ctxp' != NULL.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_tlsctx_createserver(const char *keyfile, const char *certfile,
|
||||
isc_tlsctx_t **ctxp);
|
||||
/*%
|
||||
* Set up TLS server context.
|
||||
/*%<
|
||||
* Set up a TLS server context, using the key and certificate specified in
|
||||
* 'keyfile' and 'certfile', or a self-generated ephemeral key and
|
||||
* certificdate if both 'keyfile' and 'certfile' are NULL.
|
||||
*
|
||||
* Require:
|
||||
* Requires:
|
||||
*\li 'ctxp' != NULL and '*ctxp' == NULL.
|
||||
*\li 'keyfile' and 'certfile' are either both NULL or both non-NULL.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_tlsctx_createclient(isc_tlsctx_t **ctxp);
|
||||
/*%
|
||||
* Set up TLS client context.
|
||||
/*%<
|
||||
* Set up a TLS client context.
|
||||
*
|
||||
* Require:
|
||||
* Requires:
|
||||
*\li 'ctxp' != NULL and '*ctxp' == NULL.
|
||||
*/
|
||||
|
||||
isc_tls_t *
|
||||
isc_tls_create(isc_tlsctx_t *ctx);
|
||||
/*%<
|
||||
* Set up the structure to hold data for a new TLS connection.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'ctx' != NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_tls_free(isc_tls_t **tlsp);
|
||||
/*%<
|
||||
* Free a TLS structure.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'tlsp' != NULL and '*tlsp' != NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_tlsctx_enable_http2client_alpn(isc_tlsctx_t *ctx);
|
||||
void
|
||||
isc_tlsctx_enable_http2server_alpn(isc_tlsctx_t *ctx);
|
||||
/*%<
|
||||
*
|
||||
* Enable HTTP/2 Application Layer Protocol Negotation for 'ctx'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'ctx' is not NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_tls_get_http2_alpn(isc_tls_t *tls, const unsigned char **alpn,
|
||||
unsigned int *alpnlen);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/thread.h>
|
||||
#include <isc/tls.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "uv-compat.h"
|
||||
@ -156,8 +157,6 @@ isc__nm_dump_active(isc_nm_t *nm);
|
||||
#define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock)
|
||||
#endif
|
||||
|
||||
typedef struct isc_nm_http2_session isc_nm_http2_session_t;
|
||||
|
||||
/*
|
||||
* Single network event loop worker.
|
||||
*/
|
||||
@ -195,6 +194,7 @@ typedef struct isc__networker {
|
||||
atomic_load(&(t)->references) > 0)
|
||||
|
||||
typedef void (*isc__nm_closecb)(isc_nmhandle_t *);
|
||||
typedef struct isc_nm_http_session isc_nm_http_session_t;
|
||||
|
||||
struct isc_nmhandle {
|
||||
int magic;
|
||||
@ -210,7 +210,7 @@ struct isc_nmhandle {
|
||||
isc_nmsocket_t *sock;
|
||||
size_t ah_pos; /* Position in the socket's 'active handles' array */
|
||||
|
||||
isc_nm_http2_session_t *httpsession;
|
||||
isc_nm_http_session_t *httpsession;
|
||||
|
||||
isc_sockaddr_t peer;
|
||||
isc_sockaddr_t local;
|
||||
@ -302,20 +302,18 @@ typedef enum isc__netievent_type {
|
||||
|
||||
typedef union {
|
||||
isc_nm_recv_cb_t recv;
|
||||
isc_nm_http_cb_t http;
|
||||
isc_nm_cb_t send;
|
||||
isc_nm_cb_t connect;
|
||||
isc_nm_accept_cb_t accept;
|
||||
} isc__nm_cb_t;
|
||||
|
||||
typedef struct isc_nm_http2_server_handler isc_nm_http2_server_handler_t;
|
||||
|
||||
struct isc_nm_http2_server_handler {
|
||||
typedef struct isc_nm_httphandler isc_nm_httphandler_t;
|
||||
struct isc_nm_httphandler {
|
||||
char *path;
|
||||
isc_nm_http_cb_t cb;
|
||||
isc_nm_recv_cb_t cb;
|
||||
void *cbarg;
|
||||
size_t extrahandlesize;
|
||||
LINK(isc_nm_http2_server_handler_t) link;
|
||||
LINK(isc_nm_httphandler_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -674,7 +672,7 @@ typedef enum isc_nmsocket_type {
|
||||
isc_nm_tlsdnslistener,
|
||||
isc_nm_tlsdnssocket,
|
||||
isc_nm_httplistener,
|
||||
isc_nm_httpstream
|
||||
isc_nm_httpsocket
|
||||
} isc_nmsocket_type;
|
||||
|
||||
/*%
|
||||
@ -704,25 +702,29 @@ enum {
|
||||
typedef struct isc_nmsocket_tls_send_req {
|
||||
isc_nmsocket_t *tlssock;
|
||||
isc_region_t data;
|
||||
isc_nm_cb_t cb;
|
||||
void *cbarg;
|
||||
isc_nmhandle_t *handle;
|
||||
bool finish;
|
||||
} isc_nmsocket_tls_send_req_t;
|
||||
|
||||
typedef enum isc_doh_request_type {
|
||||
typedef enum isc_http_request_type {
|
||||
ISC_HTTP_REQ_GET,
|
||||
ISC_HTTP_REQ_POST,
|
||||
ISC_HTTP_REQ_UNSUPPORTED
|
||||
} isc_http2_request_type_t;
|
||||
} isc_http_request_type_t;
|
||||
|
||||
typedef enum isc_http2_scheme_type {
|
||||
typedef enum isc_http_scheme_type {
|
||||
ISC_HTTP_SCHEME_HTTP,
|
||||
ISC_HTTP_SCHEME_HTTP_SECURE,
|
||||
ISC_HTTP_SCHEME_UNSUPPORTED
|
||||
} isc_http2_scheme_type_t;
|
||||
} isc_http_scheme_type_t;
|
||||
|
||||
typedef struct isc_nm_http_doh_cbarg {
|
||||
typedef struct isc_nm_httpcbarg {
|
||||
isc_nm_recv_cb_t cb;
|
||||
void *cbarg;
|
||||
LINK(struct isc_nm_http_doh_cbarg) link;
|
||||
} isc_nm_http_doh_cbarg_t;
|
||||
LINK(struct isc_nm_httpcbarg) link;
|
||||
} isc_nm_httpcbarg_t;
|
||||
|
||||
typedef struct isc_nmsocket_h2 {
|
||||
isc_nmsocket_t *psock; /* owner of the structure */
|
||||
@ -730,38 +732,43 @@ typedef struct isc_nmsocket_h2 {
|
||||
char *query_data;
|
||||
size_t query_data_len;
|
||||
bool query_too_large;
|
||||
isc_nm_http2_server_handler_t *handler;
|
||||
isc_nm_httphandler_t *handler;
|
||||
|
||||
uint8_t *buf;
|
||||
size_t bufsize;
|
||||
size_t bufpos;
|
||||
|
||||
int32_t stream_id;
|
||||
isc_nm_http2_session_t *session;
|
||||
isc_nm_http_session_t *session;
|
||||
|
||||
isc_nmsocket_t *httpserver;
|
||||
|
||||
isc_http2_request_type_t request_type;
|
||||
isc_http2_scheme_type_t request_scheme;
|
||||
size_t content_length;
|
||||
bool content_type_verified;
|
||||
bool accept_type_verified;
|
||||
isc_http_request_type_t request_type;
|
||||
isc_http_scheme_type_t request_scheme;
|
||||
|
||||
isc_nm_http_cb_t handler_cb;
|
||||
void *handler_cbarg;
|
||||
size_t content_length;
|
||||
char clenbuf[128];
|
||||
|
||||
int headers_error_code;
|
||||
size_t headers_data_processed;
|
||||
|
||||
isc_nm_recv_cb_t cb;
|
||||
void *cbarg;
|
||||
LINK(struct isc_nmsocket_h2) link;
|
||||
|
||||
ISC_LIST(isc_nm_http2_server_handler_t) handlers;
|
||||
ISC_LIST(isc_nm_http_doh_cbarg_t) handlers_cbargs;
|
||||
isc_rwlock_t handlers_lock;
|
||||
ISC_LIST(isc_nm_httphandler_t) handlers;
|
||||
ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs;
|
||||
isc_rwlock_t lock;
|
||||
|
||||
char response_content_length_str[128];
|
||||
|
||||
struct isc_nmsocket_h2_connect_data {
|
||||
struct {
|
||||
char *uri;
|
||||
bool post;
|
||||
isc_tlsctx_t *tlsctx;
|
||||
isc_nmiface_t local_interface;
|
||||
void *cstream;
|
||||
} connect;
|
||||
} isc_nmsocket_h2_t;
|
||||
|
||||
struct isc_nmsocket {
|
||||
/*% Unlocked, RO */
|
||||
int magic;
|
||||
@ -778,8 +785,8 @@ struct isc_nmsocket {
|
||||
|
||||
/*% TLS stuff */
|
||||
struct tls {
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
isc_tls_t *tls;
|
||||
isc_tlsctx_t *ctx;
|
||||
BIO *app_rbio;
|
||||
BIO *app_wbio;
|
||||
BIO *ssl_rbio;
|
||||
@ -802,21 +809,22 @@ struct isc_nmsocket {
|
||||
struct tlsstream {
|
||||
bool server;
|
||||
BIO *app_bio;
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
isc_tls_t *tls;
|
||||
isc_tlsctx_t *ctx;
|
||||
BIO *ssl_bio;
|
||||
isc_nmsocket_t *tlslistener;
|
||||
isc_nmiface_t server_iface;
|
||||
isc_nmiface_t local_iface;
|
||||
bool connect_from_networker;
|
||||
atomic_bool result_updated;
|
||||
enum {
|
||||
TLS_INIT,
|
||||
TLS_HANDSHAKE,
|
||||
TLS_IO,
|
||||
TLS_ERROR,
|
||||
TLS_CLOSING,
|
||||
TLS_CLOSED
|
||||
} state;
|
||||
} state; /*%< The order of these is significant */
|
||||
size_t nsending;
|
||||
/* List of active send requests. */
|
||||
ISC_LIST(isc__nm_uvreq_t) sends;
|
||||
} tlsstream;
|
||||
|
||||
isc_nmsocket_h2_t h2;
|
||||
@ -1149,11 +1157,15 @@ isc__nmsocket_clearcb(isc_nmsocket_t *sock);
|
||||
void
|
||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult);
|
||||
|
||||
void
|
||||
isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult);
|
||||
|
||||
void
|
||||
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
/*%<
|
||||
* Issue a connect callback on the socket, used to call the callback
|
||||
|
||||
*/
|
||||
|
||||
void
|
||||
@ -1518,19 +1530,42 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock);
|
||||
void
|
||||
isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
|
||||
/*%<
|
||||
* Set the read timeout and reset the timer for the socket
|
||||
* associated with 'handle', and the TCP socket it wraps
|
||||
* around.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_clear_handlers(isc_nmsocket_t *sock);
|
||||
isc__nm_http_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
|
||||
/*%<
|
||||
* Set the read timeout and reset the timer for the socket
|
||||
* associated with 'handle', and the TLS/TCP socket it wraps
|
||||
* around.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_http_clear_session(isc_nmsocket_t *sock);
|
||||
isc__nm_http_initsocket(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_cleanup_data(isc_nmsocket_t *sock);
|
||||
|
||||
isc_result_t
|
||||
isc__nm_http_request(isc_nmhandle_t *handle, isc_region_t *region,
|
||||
isc_nm_recv_cb_t reply_cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_http_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
|
||||
|
||||
void
|
||||
isc__nm_http_close(isc_nmsocket_t *sock);
|
||||
|
||||
@ -1544,8 +1579,8 @@ void
|
||||
isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
bool
|
||||
isc__nm_parse_doh_query_string(const char *query_string, const char **start,
|
||||
size_t *len);
|
||||
isc__nm_parse_httpquery(const char *query_string, const char **start,
|
||||
size_t *len);
|
||||
|
||||
char *
|
||||
isc__nm_base64url_to_base64(isc_mem_t *mem, const char *base64url,
|
||||
@ -1555,6 +1590,12 @@ char *
|
||||
isc__nm_base64_to_base64url(isc_mem_t *mem, const char *base64,
|
||||
const size_t base64_len, size_t *res_len);
|
||||
|
||||
void
|
||||
isc__nm_httpsession_attach(isc_nm_http_session_t *source,
|
||||
isc_nm_http_session_t **targetp);
|
||||
void
|
||||
isc__nm_httpsession_detach(isc_nm_http_session_t **sessionp);
|
||||
|
||||
#define isc__nm_uverr2result(x) \
|
||||
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
||||
isc_result_t
|
||||
@ -1646,6 +1687,12 @@ isc__nm_socket_connectiontimeout(uv_os_sock_t fd, int timeout_ms);
|
||||
* the minimum value must be at least 1000 (1 second).
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc__nm_socket_tcp_nodelay(uv_os_sock_t fd);
|
||||
/*%<
|
||||
* Disables Nagle's algorithm on a TCP socket (sets TCP_NODELAY).
|
||||
*/
|
||||
|
||||
/*
|
||||
* typedef all the netievent types
|
||||
*/
|
||||
|
@ -1004,33 +1004,7 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
|
||||
isc_condition_destroy(&sock->cond);
|
||||
isc_condition_destroy(&sock->scond);
|
||||
isc__nm_tls_cleanup_data(sock);
|
||||
|
||||
if (sock->type == isc_nm_httplistener) {
|
||||
isc__nm_http_clear_handlers(sock);
|
||||
isc_rwlock_destroy(&sock->h2.handlers_lock);
|
||||
}
|
||||
|
||||
if (sock->h2.request_path != NULL) {
|
||||
isc_mem_free(sock->mgr->mctx, sock->h2.request_path);
|
||||
sock->h2.request_path = NULL;
|
||||
}
|
||||
|
||||
if (sock->h2.query_data != NULL) {
|
||||
isc_mem_free(sock->mgr->mctx, sock->h2.query_data);
|
||||
sock->h2.query_data = NULL;
|
||||
}
|
||||
|
||||
if (sock->h2.connect.uri != NULL) {
|
||||
isc_mem_free(sock->mgr->mctx, sock->h2.connect.uri);
|
||||
sock->h2.query_data = NULL;
|
||||
}
|
||||
|
||||
if (sock->h2.buf != NULL) {
|
||||
isc_mem_free(sock->mgr->mctx, sock->h2.buf);
|
||||
sock->h2.buf = NULL;
|
||||
}
|
||||
|
||||
isc__nm_http_clear_session(sock);
|
||||
isc__nm_http_cleanup_data(sock);
|
||||
#ifdef NETMGR_TRACE
|
||||
LOCK(&sock->mgr->lock);
|
||||
ISC_LIST_UNLINK(sock->mgr->active_sockets, sock, active_link);
|
||||
@ -1145,7 +1119,7 @@ isc___nmsocket_prep_destroy(isc_nmsocket_t *sock FLARG) {
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_close(sock);
|
||||
return;
|
||||
case isc_nm_httpstream:
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_close(sock);
|
||||
return;
|
||||
default:
|
||||
@ -1255,7 +1229,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
||||
case isc_nm_tcpdnslistener:
|
||||
case isc_nm_tlsdnssocket:
|
||||
case isc_nm_tlsdnslistener:
|
||||
case isc_nm_httpstream:
|
||||
case isc_nm_httpsocket:
|
||||
case isc_nm_httplistener:
|
||||
if (family == AF_INET) {
|
||||
sock->statsindex = tcp4statsindex;
|
||||
@ -1274,7 +1248,6 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
||||
isc_refcount_init(&sock->references, 1);
|
||||
|
||||
memset(&sock->tlsstream, 0, sizeof(sock->tlsstream));
|
||||
ISC_LIST_INIT(sock->tlsstream.sends);
|
||||
|
||||
NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %lu\n", sock,
|
||||
isc_refcount_current(&sock->references));
|
||||
@ -1286,27 +1259,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
||||
|
||||
atomic_store(&sock->active_child_connections, 0);
|
||||
|
||||
if (type == isc_nm_httplistener) {
|
||||
ISC_LIST_INIT(sock->h2.handlers);
|
||||
ISC_LIST_INIT(sock->h2.handlers_cbargs);
|
||||
isc_rwlock_init(&sock->h2.handlers_lock, 0, 1);
|
||||
}
|
||||
|
||||
sock->h2.session = NULL;
|
||||
sock->h2.httpserver = NULL;
|
||||
sock->h2.query_data = NULL;
|
||||
sock->h2.query_data_len = 0;
|
||||
sock->h2.query_too_large = false;
|
||||
sock->h2.request_path = NULL;
|
||||
sock->h2.request_type = ISC_HTTP_REQ_UNSUPPORTED;
|
||||
sock->h2.request_scheme = ISC_HTTP_SCHEME_UNSUPPORTED;
|
||||
sock->h2.content_length = 0;
|
||||
sock->h2.content_type_verified = false;
|
||||
sock->h2.accept_type_verified = false;
|
||||
sock->h2.handler_cb = NULL;
|
||||
sock->h2.handler_cbarg = NULL;
|
||||
sock->h2.connect.uri = NULL;
|
||||
sock->h2.buf = NULL;
|
||||
isc__nm_http_initsocket(sock);
|
||||
|
||||
sock->magic = NMSOCK_MAGIC;
|
||||
}
|
||||
@ -1449,8 +1402,9 @@ isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
|
||||
sock->statichandle = handle;
|
||||
}
|
||||
|
||||
if (sock->type == isc_nm_httpstream) {
|
||||
handle->httpsession = sock->h2.session;
|
||||
if (sock->type == isc_nm_httpsocket && sock->h2.session) {
|
||||
isc__nm_httpsession_attach(sock->h2.session,
|
||||
&handle->httpsession);
|
||||
}
|
||||
|
||||
return (handle);
|
||||
@ -1582,6 +1536,10 @@ nmhandle_detach_cb(isc_nmhandle_t **handlep FLARG) {
|
||||
handle->doreset(handle->opaque);
|
||||
}
|
||||
|
||||
if (sock->type == isc_nm_httpsocket && handle->httpsession != NULL) {
|
||||
isc__nm_httpsession_detach(&handle->httpsession);
|
||||
}
|
||||
|
||||
nmhandle_deactivate(sock, handle);
|
||||
|
||||
/*
|
||||
@ -1642,6 +1600,12 @@ isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_settimeout(handle, timeout);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_settimeout(handle, timeout);
|
||||
break;
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_settimeout(handle, timeout);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@ -1758,7 +1722,7 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_httpstream:
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_send(handle, region, cb, cbarg);
|
||||
break;
|
||||
default:
|
||||
@ -1794,6 +1758,9 @@ isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_read(handle, cb, cbarg);
|
||||
break;
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_read(handle, cb, cbarg);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
@ -1893,27 +1860,38 @@ isc_nm_stoplistening(isc_nmsocket_t *sock) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult) {
|
||||
static void
|
||||
nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq, isc_result_t eresult,
|
||||
bool force_async) {
|
||||
isc__netievent_connectcb_t *ievent = NULL;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(VALID_UVREQ(uvreq));
|
||||
REQUIRE(VALID_NMHANDLE(uvreq->handle));
|
||||
|
||||
if (eresult == ISC_R_SUCCESS) {
|
||||
isc__netievent_connectcb_t ievent = { .sock = sock,
|
||||
.req = uvreq,
|
||||
.result = eresult };
|
||||
isc__nm_async_connectcb(NULL, (isc__netievent_t *)&ievent);
|
||||
} else {
|
||||
isc__netievent_connectcb_t *ievent =
|
||||
isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
|
||||
eresult);
|
||||
ievent = isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
|
||||
eresult);
|
||||
if (force_async) {
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
} else {
|
||||
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult) {
|
||||
nm_connectcb(sock, uvreq, eresult, false);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult) {
|
||||
nm_connectcb(sock, uvreq, eresult, true);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent_connectcb_t *ievent = (isc__netievent_connectcb_t *)ev0;
|
||||
@ -2429,6 +2407,20 @@ isc__nm_socket_connectiontimeout(uv_os_sock_t fd, int timeout_ms) {
|
||||
#endif
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc__nm_socket_tcp_nodelay(uv_os_sock_t fd) {
|
||||
#ifdef TCP_NODELAY
|
||||
if (setsockopt_on(fd, IPPROTO_TCP, TCP_NODELAY) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
} else {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#else
|
||||
UNUSED(fd);
|
||||
return (ISC_R_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef NETMGR_TRACE
|
||||
/*
|
||||
* Dump all active sockets in netmgr. We output to stderr
|
||||
@ -2460,8 +2452,8 @@ nmsocket_type_totext(isc_nmsocket_type type) {
|
||||
return ("isc_nm_tlsdnssocket");
|
||||
case isc_nm_httplistener:
|
||||
return ("isc_nm_httplistener");
|
||||
case isc_nm_httpstream:
|
||||
return ("isc_nm_httpstream");
|
||||
case isc_nm_httpsocket:
|
||||
return ("isc_nm_httpsocket");
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
@ -167,23 +167,6 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
REQUIRE(isc__nm_in_netthread());
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
result = isc__nm_socket(req->peer.type.sa.sa_family, SOCK_STREAM, 0,
|
||||
&sock->fd);
|
||||
/*
|
||||
* The socket() call can fail spuriously on FreeBSD 12, so we need to
|
||||
* handle the failure early and gracefully.
|
||||
*/
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
atomic_store(&sock->closed, true);
|
||||
isc__nm_uvreq_t *cbreq = NULL;
|
||||
cbreq = isc__nm_uvreq_get(sock->mgr, sock);
|
||||
cbreq->cb.connect = req->cb.connect;
|
||||
cbreq->cbarg = req->cbarg;
|
||||
isc_nmhandle_attach(req->handle, &cbreq->handle);
|
||||
isc__nmsocket_clearcb(sock);
|
||||
isc__nm_connectcb(sock, cbreq, result);
|
||||
goto error;
|
||||
}
|
||||
result = isc__nm_socket_connectiontimeout(sock->fd,
|
||||
sock->connect_timeout);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
@ -231,7 +214,7 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
|
||||
done:
|
||||
result = isc__nm_uverr2result(r);
|
||||
error:
|
||||
|
||||
LOCK(&sock->lock);
|
||||
sock->result = result;
|
||||
SIGNAL(&sock->cond);
|
||||
@ -260,7 +243,6 @@ isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
REQUIRE(sock->parent == NULL);
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
sock->fd = (uv_os_sock_t)(-1);
|
||||
result = tcp_connect_direct(sock, req);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
atomic_store(&sock->active, false);
|
||||
@ -333,17 +315,31 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
isc__netievent_tcpconnect_t *ievent = NULL;
|
||||
isc__nm_uvreq_t *req = NULL;
|
||||
sa_family_t sa_family;
|
||||
uv_os_sock_t fd;
|
||||
|
||||
REQUIRE(VALID_NM(mgr));
|
||||
REQUIRE(local != NULL);
|
||||
REQUIRE(peer != NULL);
|
||||
|
||||
sa_family = peer->addr.type.sa.sa_family;
|
||||
|
||||
/*
|
||||
* The socket() call can fail spuriously on FreeBSD 12, so we need to
|
||||
* handle the failure early and gracefully.
|
||||
*/
|
||||
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &fd);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
|
||||
isc__nmsocket_init(sock, mgr, isc_nm_tcpsocket, local);
|
||||
|
||||
sock->extrahandlesize = extrahandlesize;
|
||||
sock->connect_timeout = timeout;
|
||||
sock->result = ISC_R_DEFAULT;
|
||||
sock->fd = fd;
|
||||
atomic_init(&sock->client, true);
|
||||
|
||||
req = isc__nm_uvreq_get(mgr, sock);
|
||||
|
@ -338,8 +338,8 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
|
||||
}
|
||||
|
||||
sock->tls.state = TLS_STATE_NONE;
|
||||
sock->tls.ssl = SSL_new(sock->tls.ctx);
|
||||
RUNTIME_CHECK(sock->tls.ssl != NULL);
|
||||
sock->tls.tls = isc_tls_create(sock->tls.ctx);
|
||||
RUNTIME_CHECK(sock->tls.tls != NULL);
|
||||
|
||||
/*
|
||||
*
|
||||
@ -359,13 +359,13 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
|
||||
* may be necessary to increment the number of references available
|
||||
* using BIO_up_ref(3) before calling the set0 functions.
|
||||
*/
|
||||
SSL_set0_rbio(sock->tls.ssl, sock->tls.ssl_rbio);
|
||||
SSL_set0_wbio(sock->tls.ssl, sock->tls.ssl_wbio);
|
||||
SSL_set0_rbio(sock->tls.tls, sock->tls.ssl_rbio);
|
||||
SSL_set0_wbio(sock->tls.tls, sock->tls.ssl_wbio);
|
||||
#else
|
||||
SSL_set_bio(sock->tls.ssl, sock->tls.ssl_rbio, sock->tls.ssl_wbio);
|
||||
SSL_set_bio(sock->tls.tls, sock->tls.ssl_rbio, sock->tls.ssl_wbio);
|
||||
#endif
|
||||
|
||||
SSL_set_connect_state(sock->tls.ssl);
|
||||
SSL_set_connect_state(sock->tls.tls);
|
||||
|
||||
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
@ -782,7 +782,7 @@ isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = SSL_shutdown(sock->tls.ssl);
|
||||
rv = SSL_shutdown(sock->tls.tls);
|
||||
|
||||
if (rv == 1) {
|
||||
sock->tls.state = TLS_STATE_NONE;
|
||||
@ -802,7 +802,7 @@ isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = SSL_get_error(sock->tls.ssl, rv);
|
||||
err = SSL_get_error(sock->tls.tls, rv);
|
||||
|
||||
switch (err) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
@ -1167,9 +1167,9 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
||||
size_t len;
|
||||
|
||||
for (;;) {
|
||||
(void)SSL_peek(sock->tls.ssl, &(char){ '\0' }, 0);
|
||||
(void)SSL_peek(sock->tls.tls, &(char){ '\0' }, 0);
|
||||
|
||||
int pending = SSL_pending(sock->tls.ssl);
|
||||
int pending = SSL_pending(sock->tls.tls);
|
||||
if (pending > TLS_BUF_SIZE) {
|
||||
pending = TLS_BUF_SIZE;
|
||||
}
|
||||
@ -1179,7 +1179,7 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
||||
}
|
||||
|
||||
len = 0;
|
||||
rv = SSL_read_ex(sock->tls.ssl,
|
||||
rv = SSL_read_ex(sock->tls.tls,
|
||||
sock->buf + sock->buf_len,
|
||||
sock->buf_size - sock->buf_len, &len);
|
||||
if (rv != 1) {
|
||||
@ -1196,11 +1196,11 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
||||
|
||||
process_sock_buffer(sock);
|
||||
}
|
||||
} else if (!SSL_is_init_finished(sock->tls.ssl)) {
|
||||
if (SSL_is_server(sock->tls.ssl)) {
|
||||
rv = SSL_accept(sock->tls.ssl);
|
||||
} else if (!SSL_is_init_finished(sock->tls.tls)) {
|
||||
if (SSL_is_server(sock->tls.tls)) {
|
||||
rv = SSL_accept(sock->tls.tls);
|
||||
} else {
|
||||
rv = SSL_connect(sock->tls.ssl);
|
||||
rv = SSL_connect(sock->tls.tls);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1208,13 +1208,13 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
||||
}
|
||||
|
||||
if (rv <= 0) {
|
||||
err = SSL_get_error(sock->tls.ssl, rv);
|
||||
err = SSL_get_error(sock->tls.tls, rv);
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
if (sock->tls.state == TLS_STATE_NONE &&
|
||||
!SSL_is_init_finished(sock->tls.ssl)) {
|
||||
!SSL_is_init_finished(sock->tls.tls)) {
|
||||
sock->tls.state = TLS_STATE_HANDSHAKE;
|
||||
start_reading(sock);
|
||||
}
|
||||
@ -1237,11 +1237,11 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
||||
|
||||
/* Stop state after handshake */
|
||||
if (sock->tls.state == TLS_STATE_HANDSHAKE &&
|
||||
SSL_is_init_finished(sock->tls.ssl))
|
||||
SSL_is_init_finished(sock->tls.tls))
|
||||
{
|
||||
sock->tls.state = TLS_STATE_IO;
|
||||
|
||||
if (SSL_is_server(sock->tls.ssl)) {
|
||||
if (SSL_is_server(sock->tls.tls)) {
|
||||
REQUIRE(sock->recv_handle != NULL);
|
||||
result = sock->accept_cb(sock->recv_handle,
|
||||
ISC_R_SUCCESS,
|
||||
@ -1656,18 +1656,8 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
|
||||
|
||||
csock->tls.state = TLS_STATE_NONE;
|
||||
|
||||
csock->tls.ssl = SSL_new(ssock->tls.ctx);
|
||||
|
||||
if (csock->tls.ssl == NULL) {
|
||||
char errbuf[256];
|
||||
unsigned long err = ERR_get_error();
|
||||
|
||||
ERR_error_string_n(err, errbuf, sizeof(errbuf));
|
||||
fprintf(stderr, "%s:SSL_new(%p) -> %s\n", __func__,
|
||||
ssock->tls.ctx, errbuf);
|
||||
}
|
||||
|
||||
RUNTIME_CHECK(csock->tls.ssl != NULL);
|
||||
csock->tls.tls = isc_tls_create(ssock->tls.ctx);
|
||||
RUNTIME_CHECK(csock->tls.tls != NULL);
|
||||
|
||||
r = BIO_new_bio_pair(&csock->tls.ssl_wbio, TLS_BUF_SIZE,
|
||||
&csock->tls.app_rbio, TLS_BUF_SIZE);
|
||||
@ -1684,13 +1674,13 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
|
||||
* may be necessary to increment the number of references available
|
||||
* using BIO_up_ref(3) before calling the set0 functions.
|
||||
*/
|
||||
SSL_set0_rbio(csock->tls.ssl, csock->tls.ssl_rbio);
|
||||
SSL_set0_wbio(csock->tls.ssl, csock->tls.ssl_wbio);
|
||||
SSL_set0_rbio(csock->tls.tls, csock->tls.ssl_rbio);
|
||||
SSL_set0_wbio(csock->tls.tls, csock->tls.ssl_wbio);
|
||||
#else
|
||||
SSL_set_bio(csock->tls.ssl, csock->tls.ssl_rbio, csock->tls.ssl_wbio);
|
||||
SSL_set_bio(csock->tls.tls, csock->tls.ssl_rbio, csock->tls.ssl_wbio);
|
||||
#endif
|
||||
|
||||
SSL_set_accept_state(csock->tls.ssl);
|
||||
SSL_set_accept_state(csock->tls.tls);
|
||||
|
||||
/* FIXME: Set SSL_MODE_RELEASE_BUFFERS */
|
||||
|
||||
@ -1823,7 +1813,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
}
|
||||
|
||||
/* Writes won't succeed until handshake end */
|
||||
if (!SSL_is_init_finished(sock->tls.ssl)) {
|
||||
if (!SSL_is_init_finished(sock->tls.tls)) {
|
||||
goto requeue;
|
||||
}
|
||||
|
||||
@ -1837,7 +1827,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
memmove(worker->sendbuf + sizeof(uint16_t), req->uvbuf.base,
|
||||
req->uvbuf.len);
|
||||
|
||||
rv = SSL_write_ex(sock->tls.ssl, worker->sendbuf, sendlen, &bytes);
|
||||
rv = SSL_write_ex(sock->tls.tls, worker->sendbuf, sendlen, &bytes);
|
||||
if (rv > 0) {
|
||||
/* SSL_write_ex() doesn't do partial writes */
|
||||
INSIST(sendlen == bytes);
|
||||
@ -1848,7 +1838,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
}
|
||||
|
||||
/* Nothing was written, maybe enqueue? */
|
||||
err = SSL_get_error(sock->tls.ssl, rv);
|
||||
err = SSL_get_error(sock->tls.tls, rv);
|
||||
|
||||
switch (err) {
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
@ -1921,9 +1911,8 @@ tlsdns_close_cb(uv_handle_t *handle) {
|
||||
|
||||
atomic_store(&sock->connected, false);
|
||||
|
||||
if (sock->tls.ssl) {
|
||||
SSL_free(sock->tls.ssl);
|
||||
sock->tls.ssl = NULL;
|
||||
if (sock->tls.tls != NULL) {
|
||||
isc_tls_free(&sock->tls.tls);
|
||||
}
|
||||
|
||||
BIO_free_all(sock->tls.app_rbio);
|
||||
|
File diff suppressed because it is too large
Load Diff
146
lib/isc/result.c
146
lib/isc/result.c
@ -102,81 +102,81 @@ static const char *description[ISC_R_NRESULTS] = {
|
||||
"default", /*%< 68 */
|
||||
"IPv4 prefix", /*%< 69 */
|
||||
"TLS error", /*%< 70 */
|
||||
"ALPN for HTTP/2 failed" /*%< 71 */
|
||||
};
|
||||
|
||||
static const char *identifier[ISC_R_NRESULTS] = {
|
||||
"ISC_R_SUCCESS",
|
||||
"ISC_R_NOMEMORY",
|
||||
"ISC_R_TIMEDOUT",
|
||||
"ISC_R_NOTHREADS",
|
||||
"ISC_R_ADDRNOTAVAIL",
|
||||
"ISC_R_ADDRINUSE",
|
||||
"ISC_R_NOPERM",
|
||||
"ISC_R_NOCONN",
|
||||
"ISC_R_NETUNREACH",
|
||||
"ISC_R_HOSTUNREACH",
|
||||
"ISC_R_NETDOWN",
|
||||
"ISC_R_HOSTDOWN",
|
||||
"ISC_R_CONNREFUSED",
|
||||
"ISC_R_NORESOURCES",
|
||||
"ISC_R_EOF",
|
||||
"ISC_R_BOUND",
|
||||
"ISC_R_RELOAD",
|
||||
"ISC_R_LOCKBUSY",
|
||||
"ISC_R_EXISTS",
|
||||
"ISC_R_NOSPACE",
|
||||
"ISC_R_CANCELED",
|
||||
"ISC_R_NOTBOUND",
|
||||
"ISC_R_SHUTTINGDOWN",
|
||||
"ISC_R_NOTFOUND",
|
||||
"ISC_R_UNEXPECTEDEND",
|
||||
"ISC_R_FAILURE",
|
||||
"ISC_R_IOERROR",
|
||||
"ISC_R_NOTIMPLEMENTED",
|
||||
"ISC_R_UNBALANCED",
|
||||
"ISC_R_NOMORE",
|
||||
"ISC_R_INVALIDFILE",
|
||||
"ISC_R_BADBASE64",
|
||||
"ISC_R_UNEXPECTEDTOKEN",
|
||||
"ISC_R_QUOTA",
|
||||
"ISC_R_UNEXPECTED",
|
||||
"ISC_R_ALREADYRUNNING",
|
||||
"ISC_R_IGNORE",
|
||||
"ISC_R_MASKNONCONTIG",
|
||||
"ISC_R_FILENOTFOUND",
|
||||
"ISC_R_FILEEXISTS",
|
||||
"ISC_R_NOTCONNECTED",
|
||||
"ISC_R_RANGE",
|
||||
"ISC_R_NOENTROPY",
|
||||
"ISC_R_MULTICAST",
|
||||
"ISC_R_NOTFILE",
|
||||
"ISC_R_NOTDIRECTORY",
|
||||
"ISC_R_QUEUEFULL",
|
||||
"ISC_R_FAMILYMISMATCH",
|
||||
"ISC_R_FAMILYNOSUPPORT",
|
||||
"ISC_R_BADHEX",
|
||||
"ISC_R_TOOMANYOPENFILES",
|
||||
"ISC_R_NOTBLOCKING",
|
||||
"ISC_R_UNBALANCEDQUOTES",
|
||||
"ISC_R_INPROGRESS",
|
||||
"ISC_R_CONNECTIONRESET",
|
||||
"ISC_R_SOFTQUOTA",
|
||||
"ISC_R_BADNUMBER",
|
||||
"ISC_R_DISABLED",
|
||||
"ISC_R_MAXSIZE",
|
||||
"ISC_R_BADADDRESSFORM",
|
||||
"ISC_R_BADBASE32",
|
||||
"ISC_R_UNSET",
|
||||
"ISC_R_MULTIPLE",
|
||||
"ISC_R_WOULDBLOCK",
|
||||
"ISC_R_COMPLETE",
|
||||
"ISC_R_CRYPTOFAILURE",
|
||||
"ISC_R_DISCQUOTA",
|
||||
"ISC_R_DISCFULL",
|
||||
"ISC_R_DEFAULT",
|
||||
"ISC_R_IPV4PREFIX",
|
||||
"ISC_R_TLSERROR",
|
||||
};
|
||||
static const char *identifier[ISC_R_NRESULTS] = { "ISC_R_SUCCESS",
|
||||
"ISC_R_NOMEMORY",
|
||||
"ISC_R_TIMEDOUT",
|
||||
"ISC_R_NOTHREADS",
|
||||
"ISC_R_ADDRNOTAVAIL",
|
||||
"ISC_R_ADDRINUSE",
|
||||
"ISC_R_NOPERM",
|
||||
"ISC_R_NOCONN",
|
||||
"ISC_R_NETUNREACH",
|
||||
"ISC_R_HOSTUNREACH",
|
||||
"ISC_R_NETDOWN",
|
||||
"ISC_R_HOSTDOWN",
|
||||
"ISC_R_CONNREFUSED",
|
||||
"ISC_R_NORESOURCES",
|
||||
"ISC_R_EOF",
|
||||
"ISC_R_BOUND",
|
||||
"ISC_R_RELOAD",
|
||||
"ISC_R_LOCKBUSY",
|
||||
"ISC_R_EXISTS",
|
||||
"ISC_R_NOSPACE",
|
||||
"ISC_R_CANCELED",
|
||||
"ISC_R_NOTBOUND",
|
||||
"ISC_R_SHUTTINGDOWN",
|
||||
"ISC_R_NOTFOUND",
|
||||
"ISC_R_UNEXPECTEDEND",
|
||||
"ISC_R_FAILURE",
|
||||
"ISC_R_IOERROR",
|
||||
"ISC_R_NOTIMPLEMENTED",
|
||||
"ISC_R_UNBALANCED",
|
||||
"ISC_R_NOMORE",
|
||||
"ISC_R_INVALIDFILE",
|
||||
"ISC_R_BADBASE64",
|
||||
"ISC_R_UNEXPECTEDTOKEN",
|
||||
"ISC_R_QUOTA",
|
||||
"ISC_R_UNEXPECTED",
|
||||
"ISC_R_ALREADYRUNNING",
|
||||
"ISC_R_IGNORE",
|
||||
"ISC_R_MASKNONCONTIG",
|
||||
"ISC_R_FILENOTFOUND",
|
||||
"ISC_R_FILEEXISTS",
|
||||
"ISC_R_NOTCONNECTED",
|
||||
"ISC_R_RANGE",
|
||||
"ISC_R_NOENTROPY",
|
||||
"ISC_R_MULTICAST",
|
||||
"ISC_R_NOTFILE",
|
||||
"ISC_R_NOTDIRECTORY",
|
||||
"ISC_R_QUEUEFULL",
|
||||
"ISC_R_FAMILYMISMATCH",
|
||||
"ISC_R_FAMILYNOSUPPORT",
|
||||
"ISC_R_BADHEX",
|
||||
"ISC_R_TOOMANYOPENFILES",
|
||||
"ISC_R_NOTBLOCKING",
|
||||
"ISC_R_UNBALANCEDQUOTES",
|
||||
"ISC_R_INPROGRESS",
|
||||
"ISC_R_CONNECTIONRESET",
|
||||
"ISC_R_SOFTQUOTA",
|
||||
"ISC_R_BADNUMBER",
|
||||
"ISC_R_DISABLED",
|
||||
"ISC_R_MAXSIZE",
|
||||
"ISC_R_BADADDRESSFORM",
|
||||
"ISC_R_BADBASE32",
|
||||
"ISC_R_UNSET",
|
||||
"ISC_R_MULTIPLE",
|
||||
"ISC_R_WOULDBLOCK",
|
||||
"ISC_R_COMPLETE",
|
||||
"ISC_R_CRYPTOFAILURE",
|
||||
"ISC_R_DISCQUOTA",
|
||||
"ISC_R_DISCFULL",
|
||||
"ISC_R_DEFAULT",
|
||||
"ISC_R_IPV4PREFIX",
|
||||
"ISC_R_TLSERROR",
|
||||
"ISC_R_HTTP2ALPNERROR" };
|
||||
|
||||
#define ISC_RESULT_RESULTSET 2
|
||||
#define ISC_RESULT_UNAVAILABLESET 3
|
||||
|
@ -72,7 +72,8 @@ static bool reuse_supported = true;
|
||||
static atomic_bool POST = ATOMIC_VAR_INIT(true);
|
||||
|
||||
static atomic_bool use_TLS = ATOMIC_VAR_INIT(false);
|
||||
static SSL_CTX *server_ssl_ctx = NULL;
|
||||
static isc_tlsctx_t *server_tlsctx = NULL;
|
||||
static isc_tlsctx_t *client_tlsctx = NULL;
|
||||
|
||||
#define NSENDS 100
|
||||
#define NWRITES 10
|
||||
@ -101,6 +102,63 @@ static SSL_CTX *server_ssl_ctx = NULL;
|
||||
#define X(v)
|
||||
#endif
|
||||
|
||||
typedef struct csdata {
|
||||
isc_nm_recv_cb_t reply_cb;
|
||||
void *cb_arg;
|
||||
isc_region_t region;
|
||||
} csdata_t;
|
||||
|
||||
static void
|
||||
connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
csdata_t data;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
|
||||
memmove(&data, arg, sizeof(data));
|
||||
isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = isc__nm_http_request(handle, &data.region, data.reply_cb,
|
||||
data.cb_arg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
isc_mem_put(handle->sock->mgr->mctx, data.region.base,
|
||||
data.region.length);
|
||||
return;
|
||||
error:
|
||||
data.reply_cb(handle, result, NULL, data.cb_arg);
|
||||
isc_mem_put(handle->sock->mgr->mctx, data.region.base,
|
||||
data.region.length);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
connect_send_request(isc_nm_t *mgr, const char *uri, bool post,
|
||||
isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg,
|
||||
bool tls, unsigned int timeout) {
|
||||
isc_result_t result;
|
||||
isc_region_t copy;
|
||||
csdata_t *data = NULL;
|
||||
isc_tlsctx_t *ctx = NULL;
|
||||
|
||||
copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length),
|
||||
.length = region->length };
|
||||
memmove(copy.base, region->base, region->length);
|
||||
data = isc_mem_get(mgr->mctx, sizeof(*data));
|
||||
*data = (csdata_t){ .reply_cb = cb, .cb_arg = cbarg, .region = copy };
|
||||
if (tls) {
|
||||
ctx = client_tlsctx;
|
||||
}
|
||||
|
||||
result = isc_nm_httpconnect(
|
||||
mgr, NULL, (isc_nmiface_t *)&tcp_listen_addr, uri, post,
|
||||
connect_send_cb, data, ctx, timeout, 0);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
|
||||
isc_result_t result;
|
||||
@ -171,7 +229,7 @@ static int
|
||||
_setup(void **state) {
|
||||
UNUSED(state);
|
||||
|
||||
/*workers = isc_os_ncpus();*/
|
||||
workers = isc_os_ncpus();
|
||||
|
||||
if (isc_test_begin(NULL, false, workers) != ISC_R_SUCCESS) {
|
||||
return (-1);
|
||||
@ -243,8 +301,11 @@ nm_setup(void **state) {
|
||||
assert_non_null(nm[i]);
|
||||
}
|
||||
|
||||
server_ssl_ctx = NULL;
|
||||
isc_tlsctx_createserver(NULL, NULL, &server_ssl_ctx);
|
||||
server_tlsctx = NULL;
|
||||
isc_tlsctx_createserver(NULL, NULL, &server_tlsctx);
|
||||
client_tlsctx = NULL;
|
||||
isc_tlsctx_createclient(&client_tlsctx);
|
||||
isc_tlsctx_enable_http2client_alpn(client_tlsctx);
|
||||
|
||||
*state = nm;
|
||||
|
||||
@ -261,8 +322,11 @@ nm_teardown(void **state) {
|
||||
}
|
||||
isc_mem_put(test_mctx, nm, MAX_NM * sizeof(nm[0]));
|
||||
|
||||
if (server_ssl_ctx) {
|
||||
isc_tlsctx_free(&server_ssl_ctx);
|
||||
if (server_tlsctx != NULL) {
|
||||
isc_tlsctx_free(&server_tlsctx);
|
||||
}
|
||||
if (client_tlsctx != NULL) {
|
||||
isc_tlsctx_free(&client_tlsctx);
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -276,6 +340,7 @@ sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf,
|
||||
uint16_t port;
|
||||
char saddr[INET6_ADDRSTRLEN] = { 0 };
|
||||
int family;
|
||||
|
||||
if (sa == NULL || outbuf == NULL || outbuf_len == 0) {
|
||||
return;
|
||||
}
|
||||
@ -321,8 +386,6 @@ doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
}
|
||||
}
|
||||
atomic_store(&was_error, true);
|
||||
/* Send failed, we need to stop reading too */
|
||||
isc_nm_cancelread(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,10 +445,6 @@ mock_doh_uv_tcp_bind(void **state) {
|
||||
isc_nm_t *listen_nm = nm[0];
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE);
|
||||
|
||||
@ -404,17 +463,13 @@ doh_noop(void **state) {
|
||||
isc_nm_t *connect_nm = nm[1];
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
char req_url[256];
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr,
|
||||
0, NULL, NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
noop_read_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
|
||||
0);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
@ -422,11 +477,11 @@ doh_noop(void **state) {
|
||||
|
||||
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
|
||||
DOH_PATH);
|
||||
(void)isc_nm_http_connect_send_request(
|
||||
(void)connect_send_request(
|
||||
connect_nm, req_url, atomic_load(&POST),
|
||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||
.length = send_msg.len },
|
||||
noop_read_cb, NULL, NULL, 30000);
|
||||
noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
|
||||
|
||||
isc_nm_closedown(connect_nm);
|
||||
|
||||
@ -455,27 +510,23 @@ doh_noresponse(void **state) {
|
||||
isc_nm_t *connect_nm = nm[1];
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
char req_url[256];
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr,
|
||||
0, NULL, NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
noop_read_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
|
||||
0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
|
||||
DOH_PATH);
|
||||
(void)isc_nm_http_connect_send_request(
|
||||
(void)connect_send_request(
|
||||
connect_nm, req_url, atomic_load(&POST),
|
||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||
.length = send_msg.len },
|
||||
noop_read_cb, NULL, NULL, 30000);
|
||||
noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
@ -509,7 +560,7 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
size_t i;
|
||||
atomic_fetch_sub(&nsends, 1);
|
||||
for (i = 0; i < NWRITES / 2; i++) {
|
||||
eresult = isc_nm_httprequest(
|
||||
eresult = isc__nm_http_request(
|
||||
handle,
|
||||
&(isc_region_t){
|
||||
.base = (uint8_t *)send_msg.base,
|
||||
@ -535,20 +586,18 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
static isc_threadresult_t
|
||||
doh_connect_thread(isc_threadarg_t arg) {
|
||||
isc_nm_t *connect_nm = (isc_nm_t *)arg;
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
char req_url[256];
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
||||
sizeof(req_url), DOH_PATH);
|
||||
|
||||
while (atomic_load(&nsends) > 0) {
|
||||
(void)isc_nm_http_connect_send_request(
|
||||
(void)connect_send_request(
|
||||
connect_nm, req_url, atomic_load(&POST),
|
||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||
.length = send_msg.len },
|
||||
doh_receive_send_reply_cb, NULL, NULL, 5000);
|
||||
doh_receive_send_reply_cb, NULL, atomic_load(&use_TLS),
|
||||
30000);
|
||||
}
|
||||
|
||||
return ((isc_threadresult_t)0);
|
||||
@ -561,33 +610,26 @@ doh_recv_one(void **state) {
|
||||
isc_nm_t *connect_nm = nm[1];
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
char req_url[256];
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
atomic_store(&nsends, 1);
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(
|
||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
||||
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
|
||||
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
||||
sizeof(req_url), DOH_PATH);
|
||||
result = isc_nm_http_connect_send_request(
|
||||
result = connect_send_request(
|
||||
connect_nm, req_url, atomic_load(&POST),
|
||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||
.length = send_msg.len },
|
||||
doh_receive_reply_cb, NULL, NULL, 5000);
|
||||
doh_receive_reply_cb, NULL, atomic_load(&use_TLS), 30000);
|
||||
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
@ -657,7 +699,7 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = isc_nm_httprequest(
|
||||
result = isc__nm_http_request(
|
||||
handle,
|
||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||
.length = send_msg.len },
|
||||
@ -666,7 +708,7 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = isc_nm_httprequest(
|
||||
result = isc__nm_http_request(
|
||||
handle,
|
||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||
.length = send_msg.len },
|
||||
@ -674,8 +716,6 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
isc_nm_resumeread(handle);
|
||||
return;
|
||||
error:
|
||||
atomic_store(&was_error, true);
|
||||
@ -688,31 +728,31 @@ doh_recv_two(void **state) {
|
||||
isc_nm_t *connect_nm = nm[1];
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
char req_url[256];
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
isc_tlsctx_t *ctx = NULL;
|
||||
|
||||
atomic_store(&nsends, 2);
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(
|
||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
||||
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
|
||||
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
||||
sizeof(req_url), DOH_PATH);
|
||||
|
||||
if (atomic_load(&use_TLS)) {
|
||||
ctx = client_tlsctx;
|
||||
}
|
||||
|
||||
result = isc_nm_httpconnect(
|
||||
connect_nm, NULL, NULL, req_url, atomic_load(&POST),
|
||||
doh_connect_send_two_requests_cb, NULL, NULL, 5000, 0);
|
||||
connect_nm, NULL, (isc_nmiface_t *)&tcp_listen_addr, req_url,
|
||||
atomic_load(&POST), doh_connect_send_two_requests_cb, NULL, ctx,
|
||||
5000, 0);
|
||||
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
@ -783,21 +823,14 @@ doh_recv_send(void **state) {
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||
isc_thread_t threads[32] = { 0 };
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(
|
||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
||||
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
|
||||
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
for (size_t i = 0; i < nthreads; i++) {
|
||||
@ -859,21 +892,14 @@ doh_recv_half_send(void **state) {
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||
isc_thread_t threads[32] = { 0 };
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(
|
||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
||||
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
|
||||
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
for (size_t i = 0; i < nthreads; i++) {
|
||||
@ -940,21 +966,14 @@ doh_half_recv_send(void **state) {
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||
isc_thread_t threads[32] = { 0 };
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(
|
||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
||||
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
|
||||
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
for (size_t i = 0; i < nthreads; i++) {
|
||||
@ -1021,21 +1040,14 @@ doh_half_recv_half_send(void **state) {
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||
isc_thread_t threads[32] = { 0 };
|
||||
isc_sockaddr_t tcp_connect_addr;
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
result = isc_nm_listenhttp(
|
||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
||||
atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock);
|
||||
atomic_load(&use_TLS) ? server_tlsctx : NULL, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||
doh_receive_request_cb, NULL, 0);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
for (size_t i = 0; i < nthreads; i++) {
|
||||
@ -1105,7 +1117,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
|
||||
"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1122,7 +1134,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
|
||||
"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1136,7 +1148,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123&dns=567";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1150,7 +1162,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?name1=123&dns=567&name2=123&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1167,7 +1179,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
"BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%"
|
||||
"D0%BD%D0%BD%D1%8F&dns=123&veaction=edit§ion=0";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1184,7 +1196,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
"BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%"
|
||||
"D0%BD%D0%BD%D1%8F&veaction=edit§ion=0";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1196,7 +1208,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1208,7 +1220,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1220,7 +1232,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1232,7 +1244,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1244,7 +1256,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123&&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1256,7 +1268,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123%12&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1270,7 +1282,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123%ZZ&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1282,7 +1294,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123%%&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1294,7 +1306,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123%AZ&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_false(ret);
|
||||
assert_null(queryp);
|
||||
assert_true(len == 0);
|
||||
@ -1306,7 +1318,7 @@ doh_parse_GET_query_string(void **state) {
|
||||
size_t len = 0;
|
||||
char str[] = "?dns=123%0AZ&";
|
||||
|
||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
||||
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||
assert_true(ret);
|
||||
assert_non_null(queryp);
|
||||
assert_true(len > 0);
|
||||
@ -1593,66 +1605,6 @@ doh_base64_to_base64url(void **state) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static char wikipedia_org_A[] = { 0xae, 0x35, 0x01, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x77,
|
||||
0x69, 0x6b, 0x69, 0x70, 0x65, 0x64, 0x69,
|
||||
0x61, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00,
|
||||
0x01, 0x00, 0x01 };
|
||||
|
||||
static void
|
||||
doh_print_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *cbarg) {
|
||||
assert_non_null(handle);
|
||||
UNUSED(cbarg);
|
||||
UNUSED(region);
|
||||
|
||||
puts("Cloudflare DNS query result:");
|
||||
if (eresult == ISC_R_SUCCESS) {
|
||||
puts("success!");
|
||||
printf("Response size: %lu\n", region->length);
|
||||
atomic_fetch_add(&creads, 1);
|
||||
isc_nm_resumeread(handle);
|
||||
} else {
|
||||
puts("failure!");
|
||||
atomic_store(&was_error, true);
|
||||
isc_nm_cancelread(handle);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
doh_cloudflare(void **state) {
|
||||
isc_nm_t **nm = (isc_nm_t **)*state;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
result = isc_nm_http_connect_send_request(
|
||||
nm[0], "https://cloudflare-dns.com/dns-query",
|
||||
atomic_load(&POST),
|
||||
&(isc_region_t){ .base = (uint8_t *)wikipedia_org_A,
|
||||
.length = sizeof(wikipedia_org_A) },
|
||||
doh_print_reply_cb, NULL, NULL, 5000);
|
||||
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
while (atomic_load(&creads) != 1 && atomic_load(&was_error) == false) {
|
||||
isc_thread_yield();
|
||||
}
|
||||
|
||||
isc_nm_closedown(nm[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
doh_cloudflare_POST(void **state) {
|
||||
atomic_store(&POST, true);
|
||||
doh_cloudflare(state);
|
||||
}
|
||||
|
||||
static void
|
||||
doh_cloudflare_GET(void **state) {
|
||||
atomic_store(&POST, false);
|
||||
doh_cloudflare(state);
|
||||
}
|
||||
*/
|
||||
int
|
||||
main(void) {
|
||||
const struct CMUnitTest tests_short[] = {
|
||||
@ -1745,17 +1697,21 @@ main(void) {
|
||||
cmocka_unit_test_setup_teardown(doh_cloudflare_POST, nm_setup,
|
||||
nm_teardown)*/
|
||||
};
|
||||
int result = 0;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
UNUSED(tests_long);
|
||||
return (cmocka_run_group_tests(tests_short, _setup, _teardown));
|
||||
result = (cmocka_run_group_tests(tests_short, _setup, _teardown));
|
||||
#else
|
||||
if (getenv("CI") != NULL || !reuse_supported) {
|
||||
return (cmocka_run_group_tests(tests_short, _setup, _teardown));
|
||||
result = (cmocka_run_group_tests(tests_short, _setup,
|
||||
_teardown));
|
||||
} else {
|
||||
return (cmocka_run_group_tests(tests_long, _setup, _teardown));
|
||||
result =
|
||||
(cmocka_run_group_tests(tests_long, _setup, _teardown));
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* HAVE_CMOCKA */
|
||||
|
132
lib/isc/tls.c
132
lib/isc/tls.c
@ -9,6 +9,9 @@
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/opensslv.h>
|
||||
@ -220,14 +223,7 @@ isc_tlsctx_createserver(const char *keyfile, const char *certfile,
|
||||
const SSL_METHOD *method = NULL;
|
||||
|
||||
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
||||
|
||||
if (ephemeral) {
|
||||
INSIST(keyfile == NULL);
|
||||
INSIST(certfile == NULL);
|
||||
} else {
|
||||
INSIST(keyfile != NULL);
|
||||
INSIST(certfile != NULL);
|
||||
}
|
||||
REQUIRE((keyfile == NULL) == (certfile == NULL));
|
||||
|
||||
method = TLS_server_method();
|
||||
if (method == NULL) {
|
||||
@ -355,3 +351,123 @@ ssl_error:
|
||||
|
||||
return (ISC_R_TLSERROR);
|
||||
}
|
||||
|
||||
isc_tls_t *
|
||||
isc_tls_create(isc_tlsctx_t *ctx) {
|
||||
isc_tls_t *newctx = NULL;
|
||||
|
||||
REQUIRE(ctx != NULL);
|
||||
|
||||
newctx = SSL_new(ctx);
|
||||
if (newctx == NULL) {
|
||||
char errbuf[256];
|
||||
unsigned long err = ERR_get_error();
|
||||
|
||||
ERR_error_string_n(err, errbuf, sizeof(errbuf));
|
||||
fprintf(stderr, "%s:SSL_new(%p) -> %s\n", __func__, ctx,
|
||||
errbuf);
|
||||
}
|
||||
|
||||
return (newctx);
|
||||
}
|
||||
|
||||
void
|
||||
isc_tls_free(isc_tls_t **tlsp) {
|
||||
REQUIRE(tlsp != NULL && *tlsp != NULL);
|
||||
|
||||
SSL_free(*tlsp);
|
||||
*tlsp = NULL;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/*
|
||||
* NPN TLS extension client callback.
|
||||
*/
|
||||
static int
|
||||
select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg) {
|
||||
UNUSED(ssl);
|
||||
UNUSED(arg);
|
||||
|
||||
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
|
||||
return (SSL_TLSEXT_ERR_NOACK);
|
||||
}
|
||||
return (SSL_TLSEXT_ERR_OK);
|
||||
}
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
void
|
||||
isc_tlsctx_enable_http2client_alpn(isc_tlsctx_t *ctx) {
|
||||
REQUIRE(ctx != NULL);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_CTX_set_next_proto_select_cb(ctx, select_next_proto_cb, NULL);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)NGHTTP2_PROTO_ALPN,
|
||||
NGHTTP2_PROTO_ALPN_LEN);
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
static int
|
||||
next_proto_cb(isc_tls_t *ssl, const unsigned char **data, unsigned int *len,
|
||||
void *arg) {
|
||||
UNUSED(ssl);
|
||||
UNUSED(arg);
|
||||
|
||||
*data = (const unsigned char *)NGHTTP2_PROTO_ALPN;
|
||||
*len = (unsigned int)NGHTTP2_PROTO_ALPN_LEN;
|
||||
return (SSL_TLSEXT_ERR_OK);
|
||||
}
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
static int
|
||||
alpn_select_proto_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg) {
|
||||
int ret;
|
||||
|
||||
UNUSED(ssl);
|
||||
UNUSED(arg);
|
||||
|
||||
ret = nghttp2_select_next_protocol((unsigned char **)(uintptr_t)out,
|
||||
outlen, in, inlen);
|
||||
|
||||
if (ret != 1) {
|
||||
return (SSL_TLSEXT_ERR_NOACK);
|
||||
}
|
||||
|
||||
return (SSL_TLSEXT_ERR_OK);
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
|
||||
void
|
||||
isc_tlsctx_enable_http2server_alpn(isc_tlsctx_t *tls) {
|
||||
REQUIRE(tls != NULL);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_CTX_set_next_protos_advertised_cb(tls, next_proto_cb, NULL);
|
||||
#endif // OPENSSL_NO_NEXTPROTONEG
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
SSL_CTX_set_alpn_select_cb(tls, alpn_select_proto_cb, NULL);
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
}
|
||||
|
||||
void
|
||||
isc_tls_get_http2_alpn(isc_tls_t *tls, const unsigned char **alpn,
|
||||
unsigned int *alpnlen) {
|
||||
REQUIRE(tls != NULL);
|
||||
REQUIRE(alpn != NULL);
|
||||
REQUIRE(alpnlen != NULL);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_get0_next_proto_negotiated(tls, alpn, alpnlen);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (*alpn == NULL) {
|
||||
SSL_get0_alpn_selected(tls, alpn, alpnlen);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -452,11 +452,8 @@ isc_nm_cancelread
|
||||
isc_nm_closedown
|
||||
isc_nm_destroy
|
||||
isc_nm_detach
|
||||
isc_nm_http_add_doh_endpoint
|
||||
isc_nm_http_add_endpoint
|
||||
isc_nm_http_connect_send_request
|
||||
isc_nm_http_endpoint
|
||||
isc_nm_httpconnect
|
||||
isc_nm_httprequest
|
||||
isc_nm_listenhttp
|
||||
isc_nm_listentcpdns
|
||||
isc_nm_listentls
|
||||
@ -710,17 +707,20 @@ isc_timermgr_create
|
||||
isc_timermgr_createinctx
|
||||
isc_timermgr_destroy
|
||||
isc_timermgr_poke
|
||||
isc__tls_initialize
|
||||
isc__tls_shutdown
|
||||
isc_tls_get_http2_alpn
|
||||
isc_tls_create
|
||||
isc_tls_free
|
||||
isc_tlsctx_createclient
|
||||
isc_tlsctx_createserver
|
||||
isc_tlsctx_free
|
||||
isc_tlsctx_enable_http2client_alpn
|
||||
isc_tlsctx_enable_http2server_alpn
|
||||
isc_tm_timegm
|
||||
isc_tm_strptime
|
||||
isc__trampoline_initialize
|
||||
isc__trampoline_shutdown
|
||||
isc__trampoline_get
|
||||
isc__trampoline_run
|
||||
isc_tm_timegm
|
||||
isc_tm_strptime
|
||||
isc_url_parse
|
||||
isc_utf8_bom
|
||||
isc_utf8_valid
|
||||
|
@ -556,9 +556,9 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
for (i = 0; i < neps; i++) {
|
||||
result = isc_nm_http_add_doh_endpoint(
|
||||
sock, eps[i], ns__client_request, ifp,
|
||||
sizeof(ns_client_t));
|
||||
result = isc_nm_http_endpoint(sock, eps[i],
|
||||
ns__client_request, ifp,
|
||||
sizeof(ns_client_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,9 +368,12 @@
|
||||
./bin/tests/system/dnstap/setup.sh SH 2018,2019,2020,2021
|
||||
./bin/tests/system/dnstap/tests.sh SH 2015,2016,2017,2018,2019,2020,2021
|
||||
./bin/tests/system/dnstap/ydump.py PYTHON 2016,2017,2018,2019,2020,2021
|
||||
./bin/tests/system/dot/clean.sh SH 2020,2021
|
||||
./bin/tests/system/dot/setup.sh SH 2020,2021
|
||||
./bin/tests/system/dot/tests.sh SH 2020,2021
|
||||
./bin/tests/system/doth/clean.sh SH 2020,2021
|
||||
./bin/tests/system/doth/dig1.good X 2021
|
||||
./bin/tests/system/doth/ns2/cert.pem X 2021
|
||||
./bin/tests/system/doth/ns2/key.pem X 2021
|
||||
./bin/tests/system/doth/setup.sh SH 2021
|
||||
./bin/tests/system/doth/tests.sh SH 2021
|
||||
./bin/tests/system/dscp/clean.sh SH 2013,2014,2015,2016,2018,2019,2020,2021
|
||||
./bin/tests/system/dscp/ns1/named.args X 2013,2014,2018,2019,2020,2021
|
||||
./bin/tests/system/dscp/ns2/named.args X 2013,2014,2018,2019,2020,2021
|
||||
@ -987,10 +990,6 @@
|
||||
./bin/tests/system/xferquota/setup.pl PERL 2000,2001,2004,2007,2011,2012,2016,2018,2019,2020,2021
|
||||
./bin/tests/system/xferquota/setup.sh SH 2000,2001,2004,2007,2012,2016,2018,2019,2020,2021
|
||||
./bin/tests/system/xferquota/tests.sh SH 2000,2001,2004,2007,2012,2016,2018,2019,2020,2021
|
||||
./bin/tests/system/xot/clean.sh SH 2021
|
||||
./bin/tests/system/xot/dig1.good X 2021
|
||||
./bin/tests/system/xot/setup.sh SH 2021
|
||||
./bin/tests/system/xot/tests.sh SH 2021
|
||||
./bin/tests/system/zero/ans5/ans.pl PERL 2016,2018,2019,2020,2021
|
||||
./bin/tests/system/zero/clean.sh SH 2013,2014,2015,2016,2018,2019,2020,2021
|
||||
./bin/tests/system/zero/setup.sh SH 2013,2014,2016,2018,2019,2020,2021
|
||||
|
Loading…
x
Reference in New Issue
Block a user