mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 22:15:20 +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:
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
|
5595. [cleanup] Public header files for BIND 9 libraries no longer
|
||||||
directly include third-party library headers. This
|
directly include third-party library headers. This
|
||||||
prevents the need to include paths to third-party header
|
prevents the need to include paths to third-party header
|
||||||
|
@@ -228,6 +228,10 @@ help(void) {
|
|||||||
"SERVFAIL)\n"
|
"SERVFAIL)\n"
|
||||||
" +[no]header-only (Send query without a "
|
" +[no]header-only (Send query without a "
|
||||||
"question section)\n"
|
"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 "
|
" +[no]identify (ID responders in short "
|
||||||
"answers)\n"
|
"answers)\n"
|
||||||
#ifdef HAVE_LIBIDN2
|
#ifdef HAVE_LIBIDN2
|
||||||
@@ -348,12 +352,18 @@ received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
|
|||||||
}
|
}
|
||||||
if (query->lookup->tls_mode) {
|
if (query->lookup->tls_mode) {
|
||||||
proto = "TLS";
|
proto = "TLS";
|
||||||
|
} else if (query->lookup->https_mode) {
|
||||||
|
if (query->lookup->http_plain) {
|
||||||
|
proto = "HTTP";
|
||||||
|
} else {
|
||||||
|
proto = "HTTPS";
|
||||||
|
}
|
||||||
} else if (query->lookup->tcp_mode) {
|
} else if (query->lookup->tcp_mode) {
|
||||||
proto = "TCP";
|
proto = "TCP";
|
||||||
} else {
|
} else {
|
||||||
proto = "UDP";
|
proto = "UDP";
|
||||||
}
|
}
|
||||||
printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->servname,
|
printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->userarg,
|
||||||
proto);
|
proto);
|
||||||
time(&tnow);
|
time(&tnow);
|
||||||
(void)localtime_r(&tnow, &tmnow);
|
(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)) \
|
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
|
||||||
goto invalid_option; \
|
goto invalid_option; \
|
||||||
} while (0)
|
} 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]) {
|
switch (cmd[0]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
@@ -1412,9 +1433,79 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
|
|||||||
lookup->servfail_stops = state;
|
lookup->servfail_stops = state;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
switch (cmd[1]) {
|
||||||
|
case 'e': /* header-only */
|
||||||
FULLCHECK("header-only");
|
FULLCHECK("header-only");
|
||||||
lookup->header_only = state;
|
lookup->header_only = state;
|
||||||
break;
|
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':
|
case 'i':
|
||||||
switch (cmd[1]) {
|
switch (cmd[1]) {
|
||||||
case 'd': /* identify */
|
case 'd': /* identify */
|
||||||
|
@@ -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
|
default is to add a question section. The query type and query name
|
||||||
are ignored when this is set.
|
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``
|
``+[no]identify``
|
||||||
This option shows [or does not show] the IP address and port number that supplied
|
This option shows [or does not show] the IP address and port number that
|
||||||
the answer, when the ``+short`` option is enabled. If short form
|
supplied the answer, when the ``+short`` option is enabled. If short
|
||||||
answers are requested, the default is not to show the source address
|
form answers are requested, the default is not to show the source
|
||||||
and port number of the server that provided the answer.
|
address and port number of the server that provided the answer.
|
||||||
|
|
||||||
``+[no]idnin``
|
``+[no]idnin``
|
||||||
This option processes [or does not process] IDN domain names on input. This requires
|
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.
|
5 seconds. An attempt to set ``T`` to less than 1 is silently set to 1.
|
||||||
|
|
||||||
``+[no]tls``
|
``+[no]tls``
|
||||||
This option indicates whether to use DNS over TLS (DoT) when querying
|
This option indicates whether to use DNS-over-TLS (DoT) when querying
|
||||||
name servers.
|
name servers. When this option is in use, the port number defaults
|
||||||
|
to 853.
|
||||||
|
|
||||||
``+[no]topdown``
|
``+[no]topdown``
|
||||||
This feature is related to ``dig +sigchase``, which is obsolete and
|
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 *
|
dig_lookup_t *
|
||||||
make_empty_lookup(void) {
|
make_empty_lookup(void) {
|
||||||
dig_lookup_t *looknew;
|
dig_lookup_t *looknew;
|
||||||
|
#ifdef HAVE_LIBIDN2
|
||||||
|
bool idn_allowed = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
|
||||||
|
#endif /* HAVE_LIBIDN2 */
|
||||||
|
|
||||||
debug("make_empty_lookup()");
|
debug("make_empty_lookup()");
|
||||||
|
|
||||||
INSIST(!free_now);
|
INSIST(!free_now);
|
||||||
|
|
||||||
looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
|
looknew = isc_mem_allocate(mctx, sizeof(*looknew));
|
||||||
looknew->pending = true;
|
*looknew = (dig_lookup_t){
|
||||||
looknew->textname[0] = 0;
|
.pending = true,
|
||||||
looknew->cmdline[0] = 0;
|
.rdtype = dns_rdatatype_a,
|
||||||
looknew->rdtype = dns_rdatatype_a;
|
.qrdtype = dns_rdatatype_a,
|
||||||
looknew->qrdtype = dns_rdatatype_a;
|
.rdclass = dns_rdataclass_in,
|
||||||
looknew->rdclass = dns_rdataclass_in;
|
.servfail_stops = true,
|
||||||
looknew->rdtypeset = false;
|
.besteffort = true,
|
||||||
looknew->rdclassset = false;
|
.opcode = dns_opcode_query,
|
||||||
looknew->sendspace = NULL;
|
.badcookie = true,
|
||||||
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;
|
|
||||||
#ifdef HAVE_LIBIDN2
|
#ifdef HAVE_LIBIDN2
|
||||||
looknew->idnin = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
|
.idnin = idn_allowed,
|
||||||
looknew->idnout = looknew->idnin;
|
.idnout = idn_allowed,
|
||||||
#else /* ifdef HAVE_LIBIDN2 */
|
|
||||||
looknew->idnin = false;
|
|
||||||
looknew->idnout = false;
|
|
||||||
#endif /* HAVE_LIBIDN2 */
|
#endif /* HAVE_LIBIDN2 */
|
||||||
looknew->udpsize = -1;
|
.udpsize = -1,
|
||||||
looknew->edns = -1;
|
.edns = -1,
|
||||||
looknew->recurse = true;
|
.recurse = true,
|
||||||
looknew->aaonly = false;
|
.retries = tries,
|
||||||
looknew->adflag = false;
|
.comments = true,
|
||||||
looknew->cdflag = false;
|
.stats = true,
|
||||||
looknew->raflag = false;
|
.section_question = true,
|
||||||
looknew->tcflag = false;
|
.section_answer = true,
|
||||||
looknew->print_unknown_format = false;
|
.section_authority = true,
|
||||||
looknew->zflag = false;
|
.section_additional = true,
|
||||||
looknew->setqid = false;
|
.ednsneg = true,
|
||||||
looknew->qid = 0;
|
.mapped = true,
|
||||||
looknew->ns_search_only = false;
|
.dscp = -1,
|
||||||
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;
|
|
||||||
dns_fixedname_init(&looknew->fdomain);
|
dns_fixedname_init(&looknew->fdomain);
|
||||||
ISC_LINK_INIT(looknew, link);
|
ISC_LINK_INIT(looknew, link);
|
||||||
ISC_LIST_INIT(looknew->q);
|
ISC_LIST_INIT(looknew->q);
|
||||||
@@ -787,6 +728,12 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
|
|||||||
looknew->nsid = lookold->nsid;
|
looknew->nsid = lookold->nsid;
|
||||||
looknew->tcp_keepalive = lookold->tcp_keepalive;
|
looknew->tcp_keepalive = lookold->tcp_keepalive;
|
||||||
looknew->header_only = lookold->header_only;
|
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->sendcookie = lookold->sendcookie;
|
||||||
looknew->seenbadcookie = lookold->seenbadcookie;
|
looknew->seenbadcookie = lookold->seenbadcookie;
|
||||||
looknew->badcookie = lookold->badcookie;
|
looknew->badcookie = lookold->badcookie;
|
||||||
@@ -1638,6 +1585,10 @@ _destroy_lookup(dig_lookup_t *lookup) {
|
|||||||
isc_mem_free(mctx, lookup->ednsopts);
|
isc_mem_free(mctx, lookup->ednsopts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lookup->https_path) {
|
||||||
|
isc_mem_free(mctx, lookup->https_path);
|
||||||
|
}
|
||||||
|
|
||||||
isc_mem_free(mctx, lookup);
|
isc_mem_free(mctx, lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2760,7 +2711,20 @@ start_tcp(dig_query_t *query) {
|
|||||||
* For TLS connections, we want to override the default
|
* For TLS connections, we want to override the default
|
||||||
* port number.
|
* 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);
|
result = get_address(query->servname, port, &query->sockaddr);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
@@ -2835,7 +2799,27 @@ start_tcp(dig_query_t *query) {
|
|||||||
(isc_nmiface_t *)&query->sockaddr,
|
(isc_nmiface_t *)&query->sockaddr,
|
||||||
tcp_connected, query, local_timeout, 0,
|
tcp_connected, query, local_timeout, 0,
|
||||||
query->tlsctx);
|
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 {
|
} else {
|
||||||
result = isc_nm_tcpdnsconnect(
|
result = isc_nm_tcpdnsconnect(
|
||||||
netmgr, (isc_nmiface_t *)&localaddr,
|
netmgr, (isc_nmiface_t *)&localaddr,
|
||||||
@@ -3211,6 +3195,7 @@ launch_next_query(dig_query_t *query) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup_detach(&l);
|
lookup_detach(&l);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3582,8 +3567,7 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||||||
isc_sockaddr_t peer;
|
isc_sockaddr_t peer;
|
||||||
|
|
||||||
REQUIRE(DIG_VALID_QUERY(query));
|
REQUIRE(DIG_VALID_QUERY(query));
|
||||||
INSIST(query->readhandle != NULL);
|
REQUIRE(query->readhandle != NULL);
|
||||||
INSIST(handle == query->readhandle);
|
|
||||||
INSIST(!free_now);
|
INSIST(!free_now);
|
||||||
|
|
||||||
debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult),
|
debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult),
|
||||||
|
@@ -76,6 +76,9 @@
|
|||||||
#define DEFAULT_EDNS_VERSION 0
|
#define DEFAULT_EDNS_VERSION 0
|
||||||
#define DEFAULT_EDNS_BUFSIZE 1232
|
#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
|
* 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
|
* created. It's job is mainly to prevent the program from running away
|
||||||
@@ -168,6 +171,12 @@ struct dig_lookup {
|
|||||||
int rrcomments;
|
int rrcomments;
|
||||||
unsigned int eoferr;
|
unsigned int eoferr;
|
||||||
uint16_t qid;
|
uint16_t qid;
|
||||||
|
struct {
|
||||||
|
bool http_plain;
|
||||||
|
bool https_mode;
|
||||||
|
bool https_get;
|
||||||
|
char *https_path;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*% The dig_query structure */
|
/*% 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);
|
create_name(dohid, &dohname);
|
||||||
|
|
||||||
transport = dns_transport_new(&dohname, DNS_TRANSPORT_DOH,
|
transport = dns_transport_new(&dohname, DNS_TRANSPORT_HTTP,
|
||||||
list);
|
list);
|
||||||
|
|
||||||
parse_transport_option(doh, transport, "key-file",
|
parse_transport_option(doh, transport, "key-file",
|
||||||
|
@@ -95,6 +95,7 @@ TESTS += \
|
|||||||
dlz \
|
dlz \
|
||||||
dlzexternal \
|
dlzexternal \
|
||||||
dns64 \
|
dns64 \
|
||||||
|
doth \
|
||||||
dscp \
|
dscp \
|
||||||
dsdigest \
|
dsdigest \
|
||||||
dyndb \
|
dyndb \
|
||||||
@@ -153,7 +154,6 @@ TESTS += \
|
|||||||
views \
|
views \
|
||||||
wildcard \
|
wildcard \
|
||||||
xferquota \
|
xferquota \
|
||||||
xot \
|
|
||||||
zonechecks
|
zonechecks
|
||||||
|
|
||||||
# The "stress" test is not run by default since it creates enough
|
# The "stress" test is not run by default since it creates enough
|
||||||
@@ -176,7 +176,6 @@ TESTS += \
|
|||||||
nsupdate \
|
nsupdate \
|
||||||
resolver \
|
resolver \
|
||||||
statistics \
|
statistics \
|
||||||
dot \
|
|
||||||
upforwd \
|
upforwd \
|
||||||
zero
|
zero
|
||||||
|
|
||||||
|
@@ -668,7 +668,7 @@ copy_setports() {
|
|||||||
atsign="@"
|
atsign="@"
|
||||||
sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \
|
sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \
|
||||||
-e "s/${atsign}TLSPORT${atsign}/${TLSPORT}/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}HTTPSPORT${atsign}/${HTTPSPORT}/g" \
|
||||||
-e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
|
-e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \
|
||||||
-e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/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
|
||||||
rm -f ./*/named.run.prev
|
rm -f ./*/named.run.prev
|
||||||
rm -f ./dig.out.*
|
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; };
|
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
http local {
|
||||||
|
endpoints { "/dns-query"; "/alter"; };
|
||||||
|
};
|
||||||
|
|
||||||
options {
|
options {
|
||||||
port @PORT@;
|
port @PORT@;
|
||||||
tls-port @TLSPORT@;
|
tls-port @TLSPORT@;
|
||||||
|
https-port @HTTPSPORT@;
|
||||||
|
http-port @HTTPPORT@;
|
||||||
pid-file "named.pid";
|
pid-file "named.pid";
|
||||||
listen-on { 10.53.0.1; };
|
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-v6 { none; };
|
||||||
listen-on tls ephemeral { 10.53.0.1; };
|
|
||||||
recursion no;
|
recursion no;
|
||||||
notify explicit;
|
notify explicit;
|
||||||
also-notify { 10.53.0.2 port @PORT@; };
|
also-notify { 10.53.0.2 port @PORT@; };
|
||||||
@@ -30,8 +38,9 @@ options {
|
|||||||
};
|
};
|
||||||
|
|
||||||
zone "." {
|
zone "." {
|
||||||
type hint;
|
type primary;
|
||||||
file "../../common/root.hint";
|
file "root.db";
|
||||||
|
allow-transfer { any; };
|
||||||
};
|
};
|
||||||
|
|
||||||
zone "example" {
|
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; };
|
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 {
|
options {
|
||||||
query-source address 10.53.0.2;
|
query-source address 10.53.0.2;
|
||||||
notify-source 10.53.0.2;
|
notify-source 10.53.0.2;
|
||||||
transfer-source 10.53.0.2;
|
transfer-source 10.53.0.2;
|
||||||
port @PORT@;
|
port @PORT@;
|
||||||
tls-port @TLSPORT@;
|
tls-port @TLSPORT@;
|
||||||
|
https-port @HTTPSPORT@;
|
||||||
|
http-port @HTTPPORT@;
|
||||||
pid-file "named.pid";
|
pid-file "named.pid";
|
||||||
listen-on { 10.53.0.2; };
|
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-v6 { none; };
|
||||||
listen-on tls ephemeral { 10.53.0.2; };
|
|
||||||
recursion no;
|
recursion no;
|
||||||
notify no;
|
notify no;
|
||||||
ixfr-from-differences yes;
|
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/netaddr.h>
|
||||||
#include <isc/netmgr.h>
|
#include <isc/netmgr.h>
|
||||||
#include <isc/os.h>
|
#include <isc/os.h>
|
||||||
|
#include <isc/print.h>
|
||||||
#include <isc/sockaddr.h>
|
#include <isc/sockaddr.h>
|
||||||
#include <isc/string.h>
|
#include <isc/string.h>
|
||||||
#include <isc/util.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_mem_t *mctx = NULL;
|
||||||
static isc_nm_t *netmgr = 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 isc_region_t message = { .length = 0, .base = messagebuf };
|
||||||
static int out = -1;
|
static int out = -1;
|
||||||
|
|
||||||
|
static isc_tlsctx_t *tls_ctx = NULL;
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
parse_port(const char *input) {
|
parse_port(const char *input) {
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
@@ -304,6 +320,9 @@ teardown(void) {
|
|||||||
|
|
||||||
isc_nm_destroy(&netmgr);
|
isc_nm_destroy(&netmgr);
|
||||||
isc_mem_destroy(&mctx);
|
isc_mem_destroy(&mctx);
|
||||||
|
if (tls_ctx) {
|
||||||
|
isc_tlsctx_free(&tls_ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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
|
static void
|
||||||
run(void) {
|
run(void) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
@@ -392,19 +438,33 @@ run(void) {
|
|||||||
connect_cb, NULL, timeout, 0);
|
connect_cb, NULL, timeout, 0);
|
||||||
break;
|
break;
|
||||||
case DOT: {
|
case DOT: {
|
||||||
isc_tlsctx_t *tlsdns_ctx = NULL;
|
isc_tlsctx_createclient(&tls_ctx);
|
||||||
isc_tlsctx_createclient(&tlsdns_ctx);
|
|
||||||
|
|
||||||
result = isc_nm_tlsdnsconnect(
|
result = isc_nm_tlsdnsconnect(
|
||||||
netmgr, (isc_nmiface_t *)&sockaddr_local,
|
netmgr, (isc_nmiface_t *)&sockaddr_local,
|
||||||
(isc_nmiface_t *)&sockaddr_remote, connect_cb, NULL,
|
(isc_nmiface_t *)&sockaddr_remote, connect_cb, NULL,
|
||||||
timeout, 0, tlsdns_ctx);
|
timeout, 0, tls_ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DOH:
|
case HTTP_GET:
|
||||||
INSIST(0);
|
case HTTPS_GET:
|
||||||
ISC_UNREACHABLE();
|
case HTTPS_POST:
|
||||||
break;
|
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:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
ISC_UNREACHABLE();
|
ISC_UNREACHABLE();
|
||||||
|
@@ -25,9 +25,11 @@
|
|||||||
#include <isc/string.h>
|
#include <isc/string.h>
|
||||||
#include <isc/util.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_mem_t *mctx = NULL;
|
||||||
static isc_nm_t *netmgr = NULL;
|
static isc_nm_t *netmgr = NULL;
|
||||||
@@ -38,6 +40,8 @@ static isc_netaddr_t netaddr;
|
|||||||
static isc_sockaddr_t sockaddr __attribute__((unused));
|
static isc_sockaddr_t sockaddr __attribute__((unused));
|
||||||
static int workers;
|
static int workers;
|
||||||
|
|
||||||
|
static isc_tlsctx_t *tls_ctx = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
read_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||||
void *cbarg);
|
void *cbarg);
|
||||||
@@ -191,6 +195,9 @@ static void
|
|||||||
teardown(void) {
|
teardown(void) {
|
||||||
isc_nm_destroy(&netmgr);
|
isc_nm_destroy(&netmgr);
|
||||||
isc_mem_destroy(&mctx);
|
isc_mem_destroy(&mctx);
|
||||||
|
if (tls_ctx) {
|
||||||
|
isc_tlsctx_free(&tls_ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -267,18 +274,26 @@ run(void) {
|
|||||||
0, NULL, &sock);
|
0, NULL, &sock);
|
||||||
break;
|
break;
|
||||||
case DOT: {
|
case DOT: {
|
||||||
isc_tlsctx_t *tlsdns_ctx = NULL;
|
isc_tlsctx_createserver(NULL, NULL, &tls_ctx);
|
||||||
isc_tlsctx_createserver(NULL, NULL, &tlsdns_ctx);
|
|
||||||
|
|
||||||
result = isc_nm_listentlsdns(netmgr, (isc_nmiface_t *)&sockaddr,
|
result = isc_nm_listentlsdns(netmgr, (isc_nmiface_t *)&sockaddr,
|
||||||
read_cb, NULL, accept_cb, NULL, 0,
|
read_cb, NULL, accept_cb, NULL, 0,
|
||||||
0, NULL, tlsdns_ctx, &sock);
|
0, NULL, tls_ctx, &sock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DOH:
|
case HTTPS:
|
||||||
INSIST(0);
|
case HTTP: {
|
||||||
ISC_UNREACHABLE();
|
bool is_https = protocol == HTTPS;
|
||||||
break;
|
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:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
ISC_UNREACHABLE();
|
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
|
default is to add a question section. The query type and query name
|
||||||
are ignored when this is set.
|
are ignored when this is set.
|
||||||
.TP
|
.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
|
.B \fB+[no]identify\fP
|
||||||
This option shows [or does not show] the IP address and port number that supplied
|
This option shows [or does not show] the IP address and port number that
|
||||||
the answer, when the \fB+short\fP option is enabled. If short form
|
supplied the answer, when the \fB+short\fP option is enabled. If short
|
||||||
answers are requested, the default is not to show the source address
|
form answers are requested, the default is not to show the source
|
||||||
and port number of the server that provided the answer.
|
address and port number of the server that provided the answer.
|
||||||
.TP
|
.TP
|
||||||
.B \fB+[no]idnin\fP
|
.B \fB+[no]idnin\fP
|
||||||
This option processes [or does not process] IDN domain names on input. This requires
|
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.
|
5 seconds. An attempt to set \fBT\fP to less than 1 is silently set to 1.
|
||||||
.TP
|
.TP
|
||||||
.B \fB+[no]tls\fP
|
.B \fB+[no]tls\fP
|
||||||
This option indicates whether to use DNS over TLS (DoT) when querying
|
This option indicates whether to use DNS\-over\-TLS (DoT) when querying
|
||||||
name servers.
|
name servers. When this option is in use, the port number defaults
|
||||||
|
to 853.
|
||||||
.TP
|
.TP
|
||||||
.B \fB+[no]topdown\fP
|
.B \fB+[no]topdown\fP
|
||||||
This feature is related to \fBdig +sigchase\fP, which is obsolete and
|
This feature is related to \fBdig +sigchase\fP, which is obsolete and
|
||||||
|
@@ -24,7 +24,8 @@ Known Issues
|
|||||||
New Features
|
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
|
- 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
|
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_UDP = 1,
|
||||||
DNS_TRANSPORT_TCP = 2,
|
DNS_TRANSPORT_TCP = 2,
|
||||||
DNS_TRANSPORT_TLS = 3,
|
DNS_TRANSPORT_TLS = 3,
|
||||||
DNS_TRANSPORT_DOH = 4,
|
DNS_TRANSPORT_HTTP = 4,
|
||||||
DNS_TRANSPORT_COUNT = 5,
|
DNS_TRANSPORT_COUNT = 5,
|
||||||
} dns_transport_type_t;
|
} dns_transport_type_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DNS_DOH_GET = 0,
|
DNS_HTTP_GET = 0,
|
||||||
DNS_DOH_POST = 1,
|
DNS_HTTP_POST = 1,
|
||||||
} dns_doh_mode_t;
|
} dns_http_mode_t;
|
||||||
|
|
||||||
typedef struct dns_transport dns_transport_t;
|
typedef struct dns_transport dns_transport_t;
|
||||||
typedef struct dns_transport_list dns_transport_list_t;
|
typedef struct dns_transport_list dns_transport_list_t;
|
||||||
@@ -50,11 +50,11 @@ char *
|
|||||||
dns_transport_get_hostname(dns_transport_t *transport);
|
dns_transport_get_hostname(dns_transport_t *transport);
|
||||||
char *
|
char *
|
||||||
dns_transport_get_endpoint(dns_transport_t *transport);
|
dns_transport_get_endpoint(dns_transport_t *transport);
|
||||||
dns_doh_mode_t
|
dns_http_mode_t
|
||||||
dns_transport_get_mode(dns_transport_t *transport);
|
dns_transport_get_mode(dns_transport_t *transport);
|
||||||
/*%<
|
/*%<
|
||||||
* Getter functions: return the type, cert file, key file, CA file,
|
* 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
|
void
|
||||||
@@ -68,16 +68,16 @@ dns_transport_set_hostname(dns_transport_t *transport, const char *hostname);
|
|||||||
void
|
void
|
||||||
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint);
|
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint);
|
||||||
void
|
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,
|
* 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:
|
* Requires:
|
||||||
*\li 'transport' is valid.
|
*\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).
|
* (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
|
void
|
||||||
|
@@ -50,7 +50,7 @@ struct dns_transport {
|
|||||||
} tls;
|
} tls;
|
||||||
struct {
|
struct {
|
||||||
char *endpoint;
|
char *endpoint;
|
||||||
dns_doh_mode_t mode;
|
dns_http_mode_t mode;
|
||||||
} doh;
|
} doh;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ dns_transport_get_endpoint(dns_transport_t *transport) {
|
|||||||
return (transport->doh.endpoint);
|
return (transport->doh.endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_doh_mode_t
|
dns_http_mode_t
|
||||||
dns_transport_get_mode(dns_transport_t *transport) {
|
dns_transport_get_mode(dns_transport_t *transport) {
|
||||||
REQUIRE(VALID_TRANSPORT(transport));
|
REQUIRE(VALID_TRANSPORT(transport));
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ void
|
|||||||
dns_transport_set_certfile(dns_transport_t *transport, const char *certfile) {
|
dns_transport_set_certfile(dns_transport_t *transport, const char *certfile) {
|
||||||
REQUIRE(VALID_TRANSPORT(transport));
|
REQUIRE(VALID_TRANSPORT(transport));
|
||||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||||
transport->type == DNS_TRANSPORT_DOH);
|
transport->type == DNS_TRANSPORT_HTTP);
|
||||||
|
|
||||||
if (certfile != NULL) {
|
if (certfile != NULL) {
|
||||||
transport->tls.certfile = isc_mem_strdup(transport->mctx,
|
transport->tls.certfile = isc_mem_strdup(transport->mctx,
|
||||||
@@ -162,7 +162,7 @@ void
|
|||||||
dns_transport_set_keyfile(dns_transport_t *transport, const char *keyfile) {
|
dns_transport_set_keyfile(dns_transport_t *transport, const char *keyfile) {
|
||||||
REQUIRE(VALID_TRANSPORT(transport));
|
REQUIRE(VALID_TRANSPORT(transport));
|
||||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||||
transport->type == DNS_TRANSPORT_DOH);
|
transport->type == DNS_TRANSPORT_HTTP);
|
||||||
|
|
||||||
if (keyfile != NULL) {
|
if (keyfile != NULL) {
|
||||||
transport->tls.keyfile = isc_mem_strdup(transport->mctx,
|
transport->tls.keyfile = isc_mem_strdup(transport->mctx,
|
||||||
@@ -174,7 +174,7 @@ void
|
|||||||
dns_transport_set_cafile(dns_transport_t *transport, const char *cafile) {
|
dns_transport_set_cafile(dns_transport_t *transport, const char *cafile) {
|
||||||
REQUIRE(VALID_TRANSPORT(transport));
|
REQUIRE(VALID_TRANSPORT(transport));
|
||||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||||
transport->type == DNS_TRANSPORT_DOH);
|
transport->type == DNS_TRANSPORT_HTTP);
|
||||||
|
|
||||||
if (cafile != NULL) {
|
if (cafile != NULL) {
|
||||||
transport->tls.cafile = isc_mem_strdup(transport->mctx, cafile);
|
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) {
|
dns_transport_set_hostname(dns_transport_t *transport, const char *hostname) {
|
||||||
REQUIRE(VALID_TRANSPORT(transport));
|
REQUIRE(VALID_TRANSPORT(transport));
|
||||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||||
transport->type == DNS_TRANSPORT_DOH);
|
transport->type == DNS_TRANSPORT_HTTP);
|
||||||
|
|
||||||
if (hostname != NULL) {
|
if (hostname != NULL) {
|
||||||
transport->tls.hostname = isc_mem_strdup(transport->mctx,
|
transport->tls.hostname = isc_mem_strdup(transport->mctx,
|
||||||
@@ -196,7 +196,7 @@ dns_transport_set_hostname(dns_transport_t *transport, const char *hostname) {
|
|||||||
void
|
void
|
||||||
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
||||||
REQUIRE(VALID_TRANSPORT(transport));
|
REQUIRE(VALID_TRANSPORT(transport));
|
||||||
REQUIRE(transport->type == DNS_TRANSPORT_DOH);
|
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
||||||
|
|
||||||
if (endpoint != NULL) {
|
if (endpoint != NULL) {
|
||||||
transport->doh.endpoint = isc_mem_strdup(transport->mctx,
|
transport->doh.endpoint = isc_mem_strdup(transport->mctx,
|
||||||
@@ -205,9 +205,9 @@ dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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(VALID_TRANSPORT(transport));
|
||||||
REQUIRE(transport->type == DNS_TRANSPORT_DOH);
|
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
||||||
|
|
||||||
transport->doh.mode = mode;
|
transport->doh.mode = mode;
|
||||||
}
|
}
|
||||||
|
@@ -506,45 +506,17 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
|||||||
* 'cb'.
|
* '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_result_t
|
||||||
isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
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,
|
const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg,
|
||||||
isc_tlsctx_t *ctx, unsigned int timeout,
|
isc_tlsctx_t *ctx, unsigned int timeout,
|
||||||
size_t extrahandlesize);
|
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_result_t
|
||||||
isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog,
|
isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog,
|
||||||
isc_quota_t *quota, isc_tlsctx_t *ctx,
|
isc_quota_t *quota, isc_tlsctx_t *ctx,
|
||||||
isc_nmsocket_t **sockp);
|
isc_nmsocket_t **sockp);
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_nm_http_add_endpoint(isc_nmsocket_t *sock, const char *uri,
|
isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
|
||||||
isc_nm_http_cb_t cb, void *cbarg,
|
void *cbarg, size_t extrahandlesize);
|
||||||
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);
|
|
||||||
|
@@ -89,9 +89,10 @@
|
|||||||
#define ISC_R_DEFAULT 68 /*%< default */
|
#define ISC_R_DEFAULT 68 /*%< default */
|
||||||
#define ISC_R_IPV4PREFIX 69 /*%< IPv4 prefix */
|
#define ISC_R_IPV4PREFIX 69 /*%< IPv4 prefix */
|
||||||
#define ISC_R_TLSERROR 70 /*%< TLS error */
|
#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. */
|
/*% Not a result code: the number of results. */
|
||||||
#define ISC_R_NRESULTS 71
|
#define ISC_R_NRESULTS 72
|
||||||
|
|
||||||
ISC_LANG_BEGINDECLS
|
ISC_LANG_BEGINDECLS
|
||||||
|
|
||||||
|
@@ -14,35 +14,72 @@
|
|||||||
#include <isc/mem.h>
|
#include <isc/mem.h>
|
||||||
#include <isc/region.h>
|
#include <isc/region.h>
|
||||||
#include <isc/result.h>
|
#include <isc/result.h>
|
||||||
#include <isc/tls.h>
|
|
||||||
#include <isc/types.h>
|
#include <isc/types.h>
|
||||||
|
|
||||||
typedef struct ssl_ctx_st isc_tlsctx_t;
|
typedef struct ssl_ctx_st isc_tlsctx_t;
|
||||||
|
typedef struct ssl_st isc_tls_t;
|
||||||
|
|
||||||
void
|
void
|
||||||
isc_tlsctx_free(isc_tlsctx_t **ctpx);
|
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.
|
*\li 'ctxp' != NULL and '*ctxp' != NULL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_tlsctx_createserver(const char *keyfile, const char *certfile,
|
isc_tlsctx_createserver(const char *keyfile, const char *certfile,
|
||||||
isc_tlsctx_t **ctxp);
|
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 'ctxp' != NULL and '*ctxp' == NULL.
|
||||||
|
*\li 'keyfile' and 'certfile' are either both NULL or both non-NULL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_tlsctx_createclient(isc_tlsctx_t **ctxp);
|
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.
|
*\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/sockaddr.h>
|
||||||
#include <isc/stats.h>
|
#include <isc/stats.h>
|
||||||
#include <isc/thread.h>
|
#include <isc/thread.h>
|
||||||
|
#include <isc/tls.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
#include "uv-compat.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)
|
#define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct isc_nm_http2_session isc_nm_http2_session_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Single network event loop worker.
|
* Single network event loop worker.
|
||||||
*/
|
*/
|
||||||
@@ -195,6 +194,7 @@ typedef struct isc__networker {
|
|||||||
atomic_load(&(t)->references) > 0)
|
atomic_load(&(t)->references) > 0)
|
||||||
|
|
||||||
typedef void (*isc__nm_closecb)(isc_nmhandle_t *);
|
typedef void (*isc__nm_closecb)(isc_nmhandle_t *);
|
||||||
|
typedef struct isc_nm_http_session isc_nm_http_session_t;
|
||||||
|
|
||||||
struct isc_nmhandle {
|
struct isc_nmhandle {
|
||||||
int magic;
|
int magic;
|
||||||
@@ -210,7 +210,7 @@ struct isc_nmhandle {
|
|||||||
isc_nmsocket_t *sock;
|
isc_nmsocket_t *sock;
|
||||||
size_t ah_pos; /* Position in the socket's 'active handles' array */
|
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 peer;
|
||||||
isc_sockaddr_t local;
|
isc_sockaddr_t local;
|
||||||
@@ -302,20 +302,18 @@ typedef enum isc__netievent_type {
|
|||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
isc_nm_recv_cb_t recv;
|
isc_nm_recv_cb_t recv;
|
||||||
isc_nm_http_cb_t http;
|
|
||||||
isc_nm_cb_t send;
|
isc_nm_cb_t send;
|
||||||
isc_nm_cb_t connect;
|
isc_nm_cb_t connect;
|
||||||
isc_nm_accept_cb_t accept;
|
isc_nm_accept_cb_t accept;
|
||||||
} isc__nm_cb_t;
|
} isc__nm_cb_t;
|
||||||
|
|
||||||
typedef struct isc_nm_http2_server_handler isc_nm_http2_server_handler_t;
|
typedef struct isc_nm_httphandler isc_nm_httphandler_t;
|
||||||
|
struct isc_nm_httphandler {
|
||||||
struct isc_nm_http2_server_handler {
|
|
||||||
char *path;
|
char *path;
|
||||||
isc_nm_http_cb_t cb;
|
isc_nm_recv_cb_t cb;
|
||||||
void *cbarg;
|
void *cbarg;
|
||||||
size_t extrahandlesize;
|
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_tlsdnslistener,
|
||||||
isc_nm_tlsdnssocket,
|
isc_nm_tlsdnssocket,
|
||||||
isc_nm_httplistener,
|
isc_nm_httplistener,
|
||||||
isc_nm_httpstream
|
isc_nm_httpsocket
|
||||||
} isc_nmsocket_type;
|
} isc_nmsocket_type;
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
@@ -704,25 +702,29 @@ enum {
|
|||||||
typedef struct isc_nmsocket_tls_send_req {
|
typedef struct isc_nmsocket_tls_send_req {
|
||||||
isc_nmsocket_t *tlssock;
|
isc_nmsocket_t *tlssock;
|
||||||
isc_region_t data;
|
isc_region_t data;
|
||||||
|
isc_nm_cb_t cb;
|
||||||
|
void *cbarg;
|
||||||
|
isc_nmhandle_t *handle;
|
||||||
|
bool finish;
|
||||||
} isc_nmsocket_tls_send_req_t;
|
} 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_GET,
|
||||||
ISC_HTTP_REQ_POST,
|
ISC_HTTP_REQ_POST,
|
||||||
ISC_HTTP_REQ_UNSUPPORTED
|
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,
|
||||||
ISC_HTTP_SCHEME_HTTP_SECURE,
|
ISC_HTTP_SCHEME_HTTP_SECURE,
|
||||||
ISC_HTTP_SCHEME_UNSUPPORTED
|
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;
|
isc_nm_recv_cb_t cb;
|
||||||
void *cbarg;
|
void *cbarg;
|
||||||
LINK(struct isc_nm_http_doh_cbarg) link;
|
LINK(struct isc_nm_httpcbarg) link;
|
||||||
} isc_nm_http_doh_cbarg_t;
|
} isc_nm_httpcbarg_t;
|
||||||
|
|
||||||
typedef struct isc_nmsocket_h2 {
|
typedef struct isc_nmsocket_h2 {
|
||||||
isc_nmsocket_t *psock; /* owner of the structure */
|
isc_nmsocket_t *psock; /* owner of the structure */
|
||||||
@@ -730,38 +732,43 @@ typedef struct isc_nmsocket_h2 {
|
|||||||
char *query_data;
|
char *query_data;
|
||||||
size_t query_data_len;
|
size_t query_data_len;
|
||||||
bool query_too_large;
|
bool query_too_large;
|
||||||
isc_nm_http2_server_handler_t *handler;
|
isc_nm_httphandler_t *handler;
|
||||||
|
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
size_t bufpos;
|
size_t bufpos;
|
||||||
|
|
||||||
int32_t stream_id;
|
int32_t stream_id;
|
||||||
isc_nm_http2_session_t *session;
|
isc_nm_http_session_t *session;
|
||||||
|
|
||||||
isc_nmsocket_t *httpserver;
|
isc_nmsocket_t *httpserver;
|
||||||
|
|
||||||
isc_http2_request_type_t request_type;
|
isc_http_request_type_t request_type;
|
||||||
isc_http2_scheme_type_t request_scheme;
|
isc_http_scheme_type_t request_scheme;
|
||||||
size_t content_length;
|
|
||||||
bool content_type_verified;
|
|
||||||
bool accept_type_verified;
|
|
||||||
|
|
||||||
isc_nm_http_cb_t handler_cb;
|
size_t content_length;
|
||||||
void *handler_cbarg;
|
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;
|
LINK(struct isc_nmsocket_h2) link;
|
||||||
|
|
||||||
ISC_LIST(isc_nm_http2_server_handler_t) handlers;
|
ISC_LIST(isc_nm_httphandler_t) handlers;
|
||||||
ISC_LIST(isc_nm_http_doh_cbarg_t) handlers_cbargs;
|
ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs;
|
||||||
isc_rwlock_t handlers_lock;
|
isc_rwlock_t lock;
|
||||||
|
|
||||||
char response_content_length_str[128];
|
struct {
|
||||||
|
|
||||||
struct isc_nmsocket_h2_connect_data {
|
|
||||||
char *uri;
|
char *uri;
|
||||||
bool post;
|
bool post;
|
||||||
|
isc_tlsctx_t *tlsctx;
|
||||||
|
isc_nmiface_t local_interface;
|
||||||
|
void *cstream;
|
||||||
} connect;
|
} connect;
|
||||||
} isc_nmsocket_h2_t;
|
} isc_nmsocket_h2_t;
|
||||||
|
|
||||||
struct isc_nmsocket {
|
struct isc_nmsocket {
|
||||||
/*% Unlocked, RO */
|
/*% Unlocked, RO */
|
||||||
int magic;
|
int magic;
|
||||||
@@ -778,8 +785,8 @@ struct isc_nmsocket {
|
|||||||
|
|
||||||
/*% TLS stuff */
|
/*% TLS stuff */
|
||||||
struct tls {
|
struct tls {
|
||||||
SSL *ssl;
|
isc_tls_t *tls;
|
||||||
SSL_CTX *ctx;
|
isc_tlsctx_t *ctx;
|
||||||
BIO *app_rbio;
|
BIO *app_rbio;
|
||||||
BIO *app_wbio;
|
BIO *app_wbio;
|
||||||
BIO *ssl_rbio;
|
BIO *ssl_rbio;
|
||||||
@@ -802,21 +809,22 @@ struct isc_nmsocket {
|
|||||||
struct tlsstream {
|
struct tlsstream {
|
||||||
bool server;
|
bool server;
|
||||||
BIO *app_bio;
|
BIO *app_bio;
|
||||||
SSL *ssl;
|
isc_tls_t *tls;
|
||||||
SSL_CTX *ctx;
|
isc_tlsctx_t *ctx;
|
||||||
BIO *ssl_bio;
|
BIO *ssl_bio;
|
||||||
isc_nmsocket_t *tlslistener;
|
isc_nmsocket_t *tlslistener;
|
||||||
|
isc_nmiface_t server_iface;
|
||||||
|
isc_nmiface_t local_iface;
|
||||||
|
bool connect_from_networker;
|
||||||
|
atomic_bool result_updated;
|
||||||
enum {
|
enum {
|
||||||
TLS_INIT,
|
TLS_INIT,
|
||||||
TLS_HANDSHAKE,
|
TLS_HANDSHAKE,
|
||||||
TLS_IO,
|
TLS_IO,
|
||||||
TLS_ERROR,
|
|
||||||
TLS_CLOSING,
|
TLS_CLOSING,
|
||||||
TLS_CLOSED
|
TLS_CLOSED
|
||||||
} state;
|
} state; /*%< The order of these is significant */
|
||||||
size_t nsending;
|
size_t nsending;
|
||||||
/* List of active send requests. */
|
|
||||||
ISC_LIST(isc__nm_uvreq_t) sends;
|
|
||||||
} tlsstream;
|
} tlsstream;
|
||||||
|
|
||||||
isc_nmsocket_h2_t h2;
|
isc_nmsocket_h2_t h2;
|
||||||
@@ -1149,11 +1157,15 @@ isc__nmsocket_clearcb(isc_nmsocket_t *sock);
|
|||||||
void
|
void
|
||||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||||
isc_result_t eresult);
|
isc_result_t eresult);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||||
|
isc_result_t eresult);
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0);
|
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
/*%<
|
/*%<
|
||||||
* Issue a connect callback on the socket, used to call the callback
|
* Issue a connect callback on the socket, used to call the callback
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1518,19 +1530,42 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock);
|
|||||||
void
|
void
|
||||||
isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
|
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
|
void
|
||||||
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||||
|
|
||||||
void
|
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
|
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
|
void
|
||||||
isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||||
isc_nm_cb_t cb, void *cbarg);
|
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
|
void
|
||||||
isc__nm_http_close(isc_nmsocket_t *sock);
|
isc__nm_http_close(isc_nmsocket_t *sock);
|
||||||
|
|
||||||
@@ -1544,7 +1579,7 @@ void
|
|||||||
isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isc__nm_parse_doh_query_string(const char *query_string, const char **start,
|
isc__nm_parse_httpquery(const char *query_string, const char **start,
|
||||||
size_t *len);
|
size_t *len);
|
||||||
|
|
||||||
char *
|
char *
|
||||||
@@ -1555,6 +1590,12 @@ char *
|
|||||||
isc__nm_base64_to_base64url(isc_mem_t *mem, const char *base64,
|
isc__nm_base64_to_base64url(isc_mem_t *mem, const char *base64,
|
||||||
const size_t base64_len, size_t *res_len);
|
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) \
|
#define isc__nm_uverr2result(x) \
|
||||||
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
||||||
isc_result_t
|
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).
|
* 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
|
* 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->cond);
|
||||||
isc_condition_destroy(&sock->scond);
|
isc_condition_destroy(&sock->scond);
|
||||||
isc__nm_tls_cleanup_data(sock);
|
isc__nm_tls_cleanup_data(sock);
|
||||||
|
isc__nm_http_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);
|
|
||||||
#ifdef NETMGR_TRACE
|
#ifdef NETMGR_TRACE
|
||||||
LOCK(&sock->mgr->lock);
|
LOCK(&sock->mgr->lock);
|
||||||
ISC_LIST_UNLINK(sock->mgr->active_sockets, sock, active_link);
|
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:
|
case isc_nm_tlsdnssocket:
|
||||||
isc__nm_tlsdns_close(sock);
|
isc__nm_tlsdns_close(sock);
|
||||||
return;
|
return;
|
||||||
case isc_nm_httpstream:
|
case isc_nm_httpsocket:
|
||||||
isc__nm_http_close(sock);
|
isc__nm_http_close(sock);
|
||||||
return;
|
return;
|
||||||
default:
|
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_tcpdnslistener:
|
||||||
case isc_nm_tlsdnssocket:
|
case isc_nm_tlsdnssocket:
|
||||||
case isc_nm_tlsdnslistener:
|
case isc_nm_tlsdnslistener:
|
||||||
case isc_nm_httpstream:
|
case isc_nm_httpsocket:
|
||||||
case isc_nm_httplistener:
|
case isc_nm_httplistener:
|
||||||
if (family == AF_INET) {
|
if (family == AF_INET) {
|
||||||
sock->statsindex = tcp4statsindex;
|
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);
|
isc_refcount_init(&sock->references, 1);
|
||||||
|
|
||||||
memset(&sock->tlsstream, 0, sizeof(sock->tlsstream));
|
memset(&sock->tlsstream, 0, sizeof(sock->tlsstream));
|
||||||
ISC_LIST_INIT(sock->tlsstream.sends);
|
|
||||||
|
|
||||||
NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %lu\n", sock,
|
NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %lu\n", sock,
|
||||||
isc_refcount_current(&sock->references));
|
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);
|
atomic_store(&sock->active_child_connections, 0);
|
||||||
|
|
||||||
if (type == isc_nm_httplistener) {
|
isc__nm_http_initsocket(sock);
|
||||||
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;
|
|
||||||
|
|
||||||
sock->magic = NMSOCK_MAGIC;
|
sock->magic = NMSOCK_MAGIC;
|
||||||
}
|
}
|
||||||
@@ -1449,8 +1402,9 @@ isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
|
|||||||
sock->statichandle = handle;
|
sock->statichandle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->type == isc_nm_httpstream) {
|
if (sock->type == isc_nm_httpsocket && sock->h2.session) {
|
||||||
handle->httpsession = sock->h2.session;
|
isc__nm_httpsession_attach(sock->h2.session,
|
||||||
|
&handle->httpsession);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (handle);
|
return (handle);
|
||||||
@@ -1582,6 +1536,10 @@ nmhandle_detach_cb(isc_nmhandle_t **handlep FLARG) {
|
|||||||
handle->doreset(handle->opaque);
|
handle->doreset(handle->opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->type == isc_nm_httpsocket && handle->httpsession != NULL) {
|
||||||
|
isc__nm_httpsession_detach(&handle->httpsession);
|
||||||
|
}
|
||||||
|
|
||||||
nmhandle_deactivate(sock, handle);
|
nmhandle_deactivate(sock, handle);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1642,6 +1600,12 @@ isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
|||||||
case isc_nm_tlsdnssocket:
|
case isc_nm_tlsdnssocket:
|
||||||
isc__nm_tlsdns_settimeout(handle, timeout);
|
isc__nm_tlsdns_settimeout(handle, timeout);
|
||||||
break;
|
break;
|
||||||
|
case isc_nm_tlssocket:
|
||||||
|
isc__nm_tls_settimeout(handle, timeout);
|
||||||
|
break;
|
||||||
|
case isc_nm_httpsocket:
|
||||||
|
isc__nm_http_settimeout(handle, timeout);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
ISC_UNREACHABLE();
|
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:
|
case isc_nm_tlsdnssocket:
|
||||||
isc__nm_tlsdns_send(handle, region, cb, cbarg);
|
isc__nm_tlsdns_send(handle, region, cb, cbarg);
|
||||||
break;
|
break;
|
||||||
case isc_nm_httpstream:
|
case isc_nm_httpsocket:
|
||||||
isc__nm_http_send(handle, region, cb, cbarg);
|
isc__nm_http_send(handle, region, cb, cbarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1794,6 +1758,9 @@ isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
|
|||||||
case isc_nm_tlsdnssocket:
|
case isc_nm_tlsdnssocket:
|
||||||
isc__nm_tlsdns_read(handle, cb, cbarg);
|
isc__nm_tlsdns_read(handle, cb, cbarg);
|
||||||
break;
|
break;
|
||||||
|
case isc_nm_httpsocket:
|
||||||
|
isc__nm_http_read(handle, cb, cbarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
ISC_UNREACHABLE();
|
ISC_UNREACHABLE();
|
||||||
@@ -1893,27 +1860,38 @@ isc_nm_stoplistening(isc_nmsocket_t *sock) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq, isc_result_t eresult,
|
||||||
isc_result_t eresult) {
|
bool force_async) {
|
||||||
|
isc__netievent_connectcb_t *ievent = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(VALID_UVREQ(uvreq));
|
REQUIRE(VALID_UVREQ(uvreq));
|
||||||
REQUIRE(VALID_NMHANDLE(uvreq->handle));
|
REQUIRE(VALID_NMHANDLE(uvreq->handle));
|
||||||
|
|
||||||
if (eresult == ISC_R_SUCCESS) {
|
ievent = isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
|
||||||
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);
|
eresult);
|
||||||
|
if (force_async) {
|
||||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||||
(isc__netievent_t *)ievent);
|
(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
|
void
|
||||||
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_connectcb_t *ievent = (isc__netievent_connectcb_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
|
#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
|
#ifdef NETMGR_TRACE
|
||||||
/*
|
/*
|
||||||
* Dump all active sockets in netmgr. We output to stderr
|
* 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");
|
return ("isc_nm_tlsdnssocket");
|
||||||
case isc_nm_httplistener:
|
case isc_nm_httplistener:
|
||||||
return ("isc_nm_httplistener");
|
return ("isc_nm_httplistener");
|
||||||
case isc_nm_httpstream:
|
case isc_nm_httpsocket:
|
||||||
return ("isc_nm_httpstream");
|
return ("isc_nm_httpsocket");
|
||||||
default:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
ISC_UNREACHABLE();
|
ISC_UNREACHABLE();
|
||||||
|
@@ -167,23 +167,6 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
|||||||
REQUIRE(isc__nm_in_netthread());
|
REQUIRE(isc__nm_in_netthread());
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
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,
|
result = isc__nm_socket_connectiontimeout(sock->fd,
|
||||||
sock->connect_timeout);
|
sock->connect_timeout);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
@@ -231,7 +214,7 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
result = isc__nm_uverr2result(r);
|
result = isc__nm_uverr2result(r);
|
||||||
error:
|
|
||||||
LOCK(&sock->lock);
|
LOCK(&sock->lock);
|
||||||
sock->result = result;
|
sock->result = result;
|
||||||
SIGNAL(&sock->cond);
|
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->parent == NULL);
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
sock->fd = (uv_os_sock_t)(-1);
|
|
||||||
result = tcp_connect_direct(sock, req);
|
result = tcp_connect_direct(sock, req);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
atomic_store(&sock->active, false);
|
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_nmsocket_t *sock = NULL;
|
||||||
isc__netievent_tcpconnect_t *ievent = NULL;
|
isc__netievent_tcpconnect_t *ievent = NULL;
|
||||||
isc__nm_uvreq_t *req = NULL;
|
isc__nm_uvreq_t *req = NULL;
|
||||||
|
sa_family_t sa_family;
|
||||||
|
uv_os_sock_t fd;
|
||||||
|
|
||||||
REQUIRE(VALID_NM(mgr));
|
REQUIRE(VALID_NM(mgr));
|
||||||
REQUIRE(local != NULL);
|
REQUIRE(local != NULL);
|
||||||
REQUIRE(peer != 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));
|
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
|
||||||
isc__nmsocket_init(sock, mgr, isc_nm_tcpsocket, local);
|
isc__nmsocket_init(sock, mgr, isc_nm_tcpsocket, local);
|
||||||
|
|
||||||
sock->extrahandlesize = extrahandlesize;
|
sock->extrahandlesize = extrahandlesize;
|
||||||
sock->connect_timeout = timeout;
|
sock->connect_timeout = timeout;
|
||||||
sock->result = ISC_R_DEFAULT;
|
sock->result = ISC_R_DEFAULT;
|
||||||
|
sock->fd = fd;
|
||||||
atomic_init(&sock->client, true);
|
atomic_init(&sock->client, true);
|
||||||
|
|
||||||
req = isc__nm_uvreq_get(mgr, sock);
|
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.state = TLS_STATE_NONE;
|
||||||
sock->tls.ssl = SSL_new(sock->tls.ctx);
|
sock->tls.tls = isc_tls_create(sock->tls.ctx);
|
||||||
RUNTIME_CHECK(sock->tls.ssl != NULL);
|
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
|
* may be necessary to increment the number of references available
|
||||||
* using BIO_up_ref(3) before calling the set0 functions.
|
* using BIO_up_ref(3) before calling the set0 functions.
|
||||||
*/
|
*/
|
||||||
SSL_set0_rbio(sock->tls.ssl, sock->tls.ssl_rbio);
|
SSL_set0_rbio(sock->tls.tls, sock->tls.ssl_rbio);
|
||||||
SSL_set0_wbio(sock->tls.ssl, sock->tls.ssl_wbio);
|
SSL_set0_wbio(sock->tls.tls, sock->tls.ssl_wbio);
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
SSL_set_connect_state(sock->tls.ssl);
|
SSL_set_connect_state(sock->tls.tls);
|
||||||
|
|
||||||
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
|
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
@@ -782,7 +782,7 @@ isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = SSL_shutdown(sock->tls.ssl);
|
rv = SSL_shutdown(sock->tls.tls);
|
||||||
|
|
||||||
if (rv == 1) {
|
if (rv == 1) {
|
||||||
sock->tls.state = TLS_STATE_NONE;
|
sock->tls.state = TLS_STATE_NONE;
|
||||||
@@ -802,7 +802,7 @@ isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = SSL_get_error(sock->tls.ssl, rv);
|
err = SSL_get_error(sock->tls.tls, rv);
|
||||||
|
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
@@ -1167,9 +1167,9 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
for (;;) {
|
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) {
|
if (pending > TLS_BUF_SIZE) {
|
||||||
pending = TLS_BUF_SIZE;
|
pending = TLS_BUF_SIZE;
|
||||||
}
|
}
|
||||||
@@ -1179,7 +1179,7 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
rv = SSL_read_ex(sock->tls.ssl,
|
rv = SSL_read_ex(sock->tls.tls,
|
||||||
sock->buf + sock->buf_len,
|
sock->buf + sock->buf_len,
|
||||||
sock->buf_size - sock->buf_len, &len);
|
sock->buf_size - sock->buf_len, &len);
|
||||||
if (rv != 1) {
|
if (rv != 1) {
|
||||||
@@ -1196,11 +1196,11 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||||||
|
|
||||||
process_sock_buffer(sock);
|
process_sock_buffer(sock);
|
||||||
}
|
}
|
||||||
} else if (!SSL_is_init_finished(sock->tls.ssl)) {
|
} else if (!SSL_is_init_finished(sock->tls.tls)) {
|
||||||
if (SSL_is_server(sock->tls.ssl)) {
|
if (SSL_is_server(sock->tls.tls)) {
|
||||||
rv = SSL_accept(sock->tls.ssl);
|
rv = SSL_accept(sock->tls.tls);
|
||||||
} else {
|
} else {
|
||||||
rv = SSL_connect(sock->tls.ssl);
|
rv = SSL_connect(sock->tls.tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -1208,13 +1208,13 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rv <= 0) {
|
if (rv <= 0) {
|
||||||
err = SSL_get_error(sock->tls.ssl, rv);
|
err = SSL_get_error(sock->tls.tls, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
if (sock->tls.state == TLS_STATE_NONE &&
|
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;
|
sock->tls.state = TLS_STATE_HANDSHAKE;
|
||||||
start_reading(sock);
|
start_reading(sock);
|
||||||
}
|
}
|
||||||
@@ -1237,11 +1237,11 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||||||
|
|
||||||
/* Stop state after handshake */
|
/* Stop state after handshake */
|
||||||
if (sock->tls.state == TLS_STATE_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;
|
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);
|
REQUIRE(sock->recv_handle != NULL);
|
||||||
result = sock->accept_cb(sock->recv_handle,
|
result = sock->accept_cb(sock->recv_handle,
|
||||||
ISC_R_SUCCESS,
|
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.state = TLS_STATE_NONE;
|
||||||
|
|
||||||
csock->tls.ssl = SSL_new(ssock->tls.ctx);
|
csock->tls.tls = isc_tls_create(ssock->tls.ctx);
|
||||||
|
RUNTIME_CHECK(csock->tls.tls != NULL);
|
||||||
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);
|
|
||||||
|
|
||||||
r = BIO_new_bio_pair(&csock->tls.ssl_wbio, TLS_BUF_SIZE,
|
r = BIO_new_bio_pair(&csock->tls.ssl_wbio, TLS_BUF_SIZE,
|
||||||
&csock->tls.app_rbio, 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
|
* may be necessary to increment the number of references available
|
||||||
* using BIO_up_ref(3) before calling the set0 functions.
|
* using BIO_up_ref(3) before calling the set0 functions.
|
||||||
*/
|
*/
|
||||||
SSL_set0_rbio(csock->tls.ssl, csock->tls.ssl_rbio);
|
SSL_set0_rbio(csock->tls.tls, csock->tls.ssl_rbio);
|
||||||
SSL_set0_wbio(csock->tls.ssl, csock->tls.ssl_wbio);
|
SSL_set0_wbio(csock->tls.tls, csock->tls.ssl_wbio);
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
SSL_set_accept_state(csock->tls.ssl);
|
SSL_set_accept_state(csock->tls.tls);
|
||||||
|
|
||||||
/* FIXME: Set SSL_MODE_RELEASE_BUFFERS */
|
/* 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 */
|
/* 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;
|
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,
|
memmove(worker->sendbuf + sizeof(uint16_t), req->uvbuf.base,
|
||||||
req->uvbuf.len);
|
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) {
|
if (rv > 0) {
|
||||||
/* SSL_write_ex() doesn't do partial writes */
|
/* SSL_write_ex() doesn't do partial writes */
|
||||||
INSIST(sendlen == bytes);
|
INSIST(sendlen == bytes);
|
||||||
@@ -1848,7 +1838,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing was written, maybe enqueue? */
|
/* Nothing was written, maybe enqueue? */
|
||||||
err = SSL_get_error(sock->tls.ssl, rv);
|
err = SSL_get_error(sock->tls.tls, rv);
|
||||||
|
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
@@ -1921,9 +1911,8 @@ tlsdns_close_cb(uv_handle_t *handle) {
|
|||||||
|
|
||||||
atomic_store(&sock->connected, false);
|
atomic_store(&sock->connected, false);
|
||||||
|
|
||||||
if (sock->tls.ssl) {
|
if (sock->tls.tls != NULL) {
|
||||||
SSL_free(sock->tls.ssl);
|
isc_tls_free(&sock->tls.tls);
|
||||||
sock->tls.ssl = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BIO_free_all(sock->tls.app_rbio);
|
BIO_free_all(sock->tls.app_rbio);
|
||||||
|
@@ -44,13 +44,15 @@ tls_error_to_result(int tls_err) {
|
|||||||
switch (tls_err) {
|
switch (tls_err) {
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
return (ISC_R_EOF);
|
return (ISC_R_EOF);
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
return (ISC_R_TLSERROR);
|
||||||
default:
|
default:
|
||||||
return (ISC_R_UNEXPECTED);
|
return (ISC_R_UNEXPECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_do_bio(isc_nmsocket_t *sock);
|
tls_do_bio(isc_nmsocket_t *sock, isc__nm_uvreq_t *send_data, bool finish);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_close_direct(isc_nmsocket_t *sock);
|
tls_close_direct(isc_nmsocket_t *sock);
|
||||||
@@ -67,6 +69,8 @@ static bool
|
|||||||
inactive(isc_nmsocket_t *sock) {
|
inactive(isc_nmsocket_t *sock) {
|
||||||
return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
|
return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
|
||||||
sock->outerhandle == NULL ||
|
sock->outerhandle == NULL ||
|
||||||
|
!isc__nmsocket_active(sock->outerhandle->sock) ||
|
||||||
|
atomic_load(&sock->outerhandle->sock->closing) ||
|
||||||
(sock->listener != NULL &&
|
(sock->listener != NULL &&
|
||||||
!isc__nmsocket_active(sock->listener)) ||
|
!isc__nmsocket_active(sock->listener)) ||
|
||||||
atomic_load(&sock->mgr->closing));
|
atomic_load(&sock->mgr->closing));
|
||||||
@@ -74,17 +78,34 @@ inactive(isc_nmsocket_t *sock) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
update_result(isc_nmsocket_t *sock, const isc_result_t result) {
|
update_result(isc_nmsocket_t *sock, const isc_result_t result) {
|
||||||
|
if (!atomic_load(&sock->tlsstream.result_updated)) {
|
||||||
|
atomic_store(&sock->tlsstream.result_updated, true);
|
||||||
|
if (!sock->tlsstream.server) {
|
||||||
LOCK(&sock->lock);
|
LOCK(&sock->lock);
|
||||||
sock->result = result;
|
sock->result = result;
|
||||||
SIGNAL(&sock->cond);
|
SIGNAL(&sock->cond);
|
||||||
if (!atomic_load(&sock->active)) {
|
while (!atomic_load(&sock->active)) {
|
||||||
WAIT(&sock->scond, &sock->lock);
|
WAIT(&sock->scond, &sock->lock);
|
||||||
}
|
}
|
||||||
UNLOCK(&sock->lock);
|
UNLOCK(&sock->lock);
|
||||||
if (sock->parent) {
|
} else {
|
||||||
LOCK(&sock->parent->lock);
|
LOCK(&sock->lock);
|
||||||
sock->parent->result = result;
|
sock->result = result;
|
||||||
UNLOCK(&sock->parent->lock);
|
UNLOCK(&sock->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tls_call_connect_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
||||||
|
const isc_result_t result) {
|
||||||
|
if (sock->connect_cb == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sock->connect_cb(handle, result, sock->connect_cbarg);
|
||||||
|
update_result(sock, result);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
isc__nmsocket_clearcb(handle->sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,26 +113,38 @@ static void
|
|||||||
tls_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
|
tls_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
|
||||||
isc_nmsocket_tls_send_req_t *send_req =
|
isc_nmsocket_tls_send_req_t *send_req =
|
||||||
(isc_nmsocket_tls_send_req_t *)cbarg;
|
(isc_nmsocket_tls_send_req_t *)cbarg;
|
||||||
isc_nmsocket_t *sock = send_req->tlssock;
|
isc_nmsocket_t *tlssock = NULL;
|
||||||
|
bool finish = send_req->finish;
|
||||||
|
|
||||||
REQUIRE(VALID_NMHANDLE(handle));
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(send_req->tlssock));
|
||||||
|
|
||||||
/* XXXWPK TODO */
|
tlssock = send_req->tlssock;
|
||||||
UNUSED(eresult);
|
send_req->tlssock = NULL;
|
||||||
|
|
||||||
|
if (send_req->cb != NULL) {
|
||||||
|
send_req->cb(send_req->handle, eresult, send_req->cbarg);
|
||||||
|
isc_nmhandle_detach(&send_req->handle);
|
||||||
|
}
|
||||||
|
|
||||||
isc_mem_put(handle->sock->mgr->mctx, send_req->data.base,
|
isc_mem_put(handle->sock->mgr->mctx, send_req->data.base,
|
||||||
send_req->data.length);
|
send_req->data.length);
|
||||||
isc_mem_put(handle->sock->mgr->mctx, send_req, sizeof(*send_req));
|
isc_mem_put(handle->sock->mgr->mctx, send_req, sizeof(*send_req));
|
||||||
|
tlssock->tlsstream.nsending--;
|
||||||
|
|
||||||
sock->tlsstream.nsending--;
|
if (finish && eresult == ISC_R_SUCCESS) {
|
||||||
async_tls_do_bio(sock);
|
isc_nm_cancelread(handle);
|
||||||
isc__nmsocket_detach(&sock);
|
} else if (eresult == ISC_R_SUCCESS) {
|
||||||
|
tls_do_bio(tlssock, NULL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc__nmsocket_detach(&tlssock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
||||||
const isc_result_t result, const bool close) {
|
const isc_result_t result) {
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
|
|
||||||
if (!sock->tlsstream.server &&
|
if (!sock->tlsstream.server &&
|
||||||
@@ -121,9 +154,7 @@ tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
|||||||
{
|
{
|
||||||
INSIST(handle == NULL);
|
INSIST(handle == NULL);
|
||||||
handle = isc__nmhandle_get(sock, NULL, NULL);
|
handle = isc__nmhandle_get(sock, NULL, NULL);
|
||||||
sock->connect_cb(handle, result, sock->connect_cbarg);
|
tls_call_connect_cb(sock, handle, result);
|
||||||
update_result(sock, result);
|
|
||||||
isc__nmsocket_clearcb(sock);
|
|
||||||
isc_nmhandle_detach(&handle);
|
isc_nmhandle_detach(&handle);
|
||||||
} else if (sock->recv_cb != NULL) {
|
} else if (sock->recv_cb != NULL) {
|
||||||
isc__nm_uvreq_t *req = NULL;
|
isc__nm_uvreq_t *req = NULL;
|
||||||
@@ -131,7 +162,7 @@ tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
|||||||
req->cb.recv = sock->recv_cb;
|
req->cb.recv = sock->recv_cb;
|
||||||
req->cbarg = sock->recv_cbarg;
|
req->cbarg = sock->recv_cbarg;
|
||||||
req->handle = NULL;
|
req->handle = NULL;
|
||||||
if (handle) {
|
if (handle != NULL) {
|
||||||
REQUIRE(VALID_NMHANDLE(handle));
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
isc_nmhandle_attach(handle, &req->handle);
|
isc_nmhandle_attach(handle, &req->handle);
|
||||||
} else {
|
} else {
|
||||||
@@ -140,11 +171,9 @@ tls_failed_read_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle,
|
|||||||
isc__nmsocket_clearcb(sock);
|
isc__nmsocket_clearcb(sock);
|
||||||
isc__nm_readcb(sock, req, result);
|
isc__nm_readcb(sock, req, result);
|
||||||
}
|
}
|
||||||
sock->tlsstream.state = TLS_ERROR;
|
|
||||||
|
|
||||||
if (close) {
|
|
||||||
isc__nmsocket_prep_destroy(sock);
|
isc__nmsocket_prep_destroy(sock);
|
||||||
}
|
isc__nmsocket_detach(&sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -155,12 +184,70 @@ async_tls_do_bio(isc_nmsocket_t *sock) {
|
|||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tls_send_outgoing(isc_nmsocket_t *sock, bool finish, isc_nmhandle_t *tlshandle,
|
||||||
|
isc_nm_cb_t cb, void *cbarg) {
|
||||||
|
isc_nmsocket_tls_send_req_t *send_req = NULL;
|
||||||
|
int pending;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (inactive(sock)) {
|
||||||
|
if (cb != NULL) {
|
||||||
|
INSIST(VALID_NMHANDLE(tlshandle));
|
||||||
|
cb(tlshandle, ISC_R_CANCELED, cbarg);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finish && (SSL_get_shutdown(sock->tlsstream.tls) &
|
||||||
|
SSL_SENT_SHUTDOWN) != SSL_SENT_SHUTDOWN)
|
||||||
|
{
|
||||||
|
(void)SSL_shutdown(sock->tlsstream.tls);
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = BIO_pending(sock->tlsstream.app_bio);
|
||||||
|
if (pending <= 0) {
|
||||||
|
return (pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO Should we keep track of these requests in a list? */
|
||||||
|
if (pending > TLS_BUF_SIZE) {
|
||||||
|
pending = TLS_BUF_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
send_req = isc_mem_get(sock->mgr->mctx, sizeof(*send_req));
|
||||||
|
*send_req = (isc_nmsocket_tls_send_req_t){
|
||||||
|
.finish = finish,
|
||||||
|
.data.base = isc_mem_get(sock->mgr->mctx, pending),
|
||||||
|
.data.length = pending
|
||||||
|
};
|
||||||
|
|
||||||
|
isc__nmsocket_attach(sock, &send_req->tlssock);
|
||||||
|
if (cb != NULL) {
|
||||||
|
send_req->cb = cb;
|
||||||
|
send_req->cbarg = cbarg;
|
||||||
|
isc_nmhandle_attach(tlshandle, &send_req->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = BIO_read(sock->tlsstream.app_bio, send_req->data.base, pending);
|
||||||
|
/* There's something pending, read must succeed */
|
||||||
|
RUNTIME_CHECK(rv == pending);
|
||||||
|
|
||||||
|
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||||
|
|
||||||
|
sock->tlsstream.nsending++;
|
||||||
|
isc_nm_send(sock->outerhandle, &send_req->data, tls_senddone, send_req);
|
||||||
|
|
||||||
|
return (pending);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_do_bio(isc_nmsocket_t *sock) {
|
tls_do_bio(isc_nmsocket_t *sock, isc__nm_uvreq_t *send_data, bool finish) {
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
int pending, tls_err = 0;
|
int pending, tls_err = 0;
|
||||||
int rv;
|
int rv;
|
||||||
isc__nm_uvreq_t *req;
|
char buf[1];
|
||||||
|
bool sent_shutdown, received_shutdown;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
@@ -172,79 +259,91 @@ tls_do_bio(isc_nmsocket_t *sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sock->tlsstream.state == TLS_INIT) {
|
if (sock->tlsstream.state == TLS_INIT) {
|
||||||
(void)SSL_do_handshake(sock->tlsstream.ssl);
|
(void)SSL_do_handshake(sock->tlsstream.tls);
|
||||||
sock->tlsstream.state = TLS_HANDSHAKE;
|
sock->tlsstream.state = TLS_HANDSHAKE;
|
||||||
} else if (sock->tlsstream.state == TLS_ERROR) {
|
|
||||||
result = ISC_R_FAILURE;
|
|
||||||
goto low_level_error;
|
|
||||||
} else if (sock->tlsstream.state == TLS_CLOSED) {
|
} else if (sock->tlsstream.state == TLS_CLOSED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
received_shutdown = (SSL_get_shutdown(sock->tlsstream.tls) &
|
||||||
|
SSL_RECEIVED_SHUTDOWN) == SSL_RECEIVED_SHUTDOWN;
|
||||||
|
|
||||||
/* Data from TLS to client */
|
/* Data from TLS to client */
|
||||||
char buf[1];
|
if (sock->tlsstream.state >= TLS_IO && sock->recv_cb != NULL &&
|
||||||
if (sock->tlsstream.state == TLS_IO && sock->recv_cb != NULL &&
|
|
||||||
!atomic_load(&sock->readpaused))
|
!atomic_load(&sock->readpaused))
|
||||||
{
|
{
|
||||||
(void)SSL_peek(sock->tlsstream.ssl, buf, 1);
|
(void)SSL_peek(sock->tlsstream.tls, buf, 1);
|
||||||
while ((pending = SSL_pending(sock->tlsstream.ssl)) > 0) {
|
while ((pending = SSL_pending(sock->tlsstream.tls)) > 0) {
|
||||||
|
uint8_t recv_buf[TLS_BUF_SIZE];
|
||||||
|
isc_region_t region, dregion;
|
||||||
|
|
||||||
if (pending > TLS_BUF_SIZE) {
|
if (pending > TLS_BUF_SIZE) {
|
||||||
pending = TLS_BUF_SIZE;
|
pending = TLS_BUF_SIZE;
|
||||||
}
|
}
|
||||||
isc_region_t region = {
|
region = (isc_region_t){ .base = &recv_buf[0],
|
||||||
isc_mem_get(sock->mgr->mctx, pending), pending
|
.length = pending };
|
||||||
};
|
|
||||||
isc_region_t dregion;
|
rv = SSL_read(sock->tlsstream.tls, region.base,
|
||||||
memset(region.base, 0, region.length);
|
|
||||||
rv = SSL_read(sock->tlsstream.ssl, region.base,
|
|
||||||
region.length);
|
region.length);
|
||||||
/* Pending succeded, so should read */
|
/* Pending succeded, so should read */
|
||||||
RUNTIME_CHECK(rv == pending);
|
RUNTIME_CHECK(rv == pending);
|
||||||
|
|
||||||
dregion = (isc_region_t){ region.base, rv };
|
dregion = (isc_region_t){ region.base, rv };
|
||||||
sock->recv_cb(sock->statichandle, ISC_R_SUCCESS,
|
sock->recv_cb(sock->statichandle, ISC_R_SUCCESS,
|
||||||
&dregion, sock->recv_cbarg);
|
&dregion, sock->recv_cbarg);
|
||||||
isc_mem_put(sock->mgr->mctx, region.base,
|
|
||||||
region.length);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (send_data != NULL) {
|
||||||
|
INSIST(sock->tlsstream.state > TLS_HANDSHAKE);
|
||||||
|
rv = SSL_write(sock->tlsstream.tls, send_data->uvbuf.base,
|
||||||
|
send_data->uvbuf.len);
|
||||||
|
if (rv != (int)send_data->uvbuf.len) {
|
||||||
|
result = received_shutdown ? ISC_R_CANCELED
|
||||||
|
: ISC_R_TLSERROR;
|
||||||
|
send_data->cb.send(send_data->handle, result,
|
||||||
|
send_data->cbarg);
|
||||||
|
send_data = NULL;
|
||||||
|
if (!received_shutdown) {
|
||||||
|
isc__nmsocket_detach(&sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sent_shutdown = (SSL_get_shutdown(sock->tlsstream.tls) &
|
||||||
|
SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN;
|
||||||
|
|
||||||
/* Peek to move the session forward */
|
/* Peek to move the session forward */
|
||||||
(void)SSL_peek(sock->tlsstream.ssl, buf, 1);
|
(void)SSL_peek(sock->tlsstream.tls, buf, 1);
|
||||||
|
|
||||||
/* Data from TLS to network */
|
/* Data from TLS to network */
|
||||||
pending = BIO_pending(sock->tlsstream.app_bio);
|
if (send_data != NULL) {
|
||||||
if (pending > 0) {
|
pending = tls_send_outgoing(sock, finish, send_data->handle,
|
||||||
/*TODO Should we keep the track of these requests in a list? */
|
send_data->cb.send,
|
||||||
isc_nmsocket_tls_send_req_t *send_req = NULL;
|
send_data->cbarg);
|
||||||
if (pending > TLS_BUF_SIZE) {
|
} else {
|
||||||
pending = TLS_BUF_SIZE;
|
if (received_shutdown && !sent_shutdown) {
|
||||||
|
finish = true;
|
||||||
|
(void)SSL_shutdown(sock->tlsstream.tls);
|
||||||
}
|
}
|
||||||
send_req = isc_mem_get(sock->mgr->mctx, sizeof(*send_req));
|
pending = tls_send_outgoing(sock, finish, NULL, NULL, NULL);
|
||||||
send_req->data.base = isc_mem_get(sock->mgr->mctx, pending);
|
}
|
||||||
send_req->data.length = pending;
|
|
||||||
send_req->tlssock = NULL;
|
if (pending > 0) {
|
||||||
isc__nmsocket_attach(sock, &send_req->tlssock);
|
|
||||||
rv = BIO_read(sock->tlsstream.app_bio, send_req->data.base,
|
|
||||||
pending);
|
|
||||||
/* There's something pending, read must succeed */
|
|
||||||
RUNTIME_CHECK(rv == pending);
|
|
||||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
|
||||||
isc_nm_send(sock->outerhandle, &send_req->data, tls_senddone,
|
|
||||||
send_req);
|
|
||||||
/* We'll continue in tls_senddone */
|
/* We'll continue in tls_senddone */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the potential error code */
|
/* Get the potential error code */
|
||||||
rv = SSL_peek(sock->tlsstream.ssl, buf, 1);
|
rv = SSL_peek(sock->tlsstream.tls, buf, 1);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
tls_err = SSL_get_error(sock->tlsstream.ssl, rv);
|
tls_err = SSL_get_error(sock->tlsstream.tls, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only after doing the IO we can check if SSL handshake is done */
|
/* Only after doing the IO we can check if SSL handshake is done */
|
||||||
if (sock->tlsstream.state == TLS_HANDSHAKE &&
|
if (sock->tlsstream.state == TLS_HANDSHAKE &&
|
||||||
SSL_is_init_finished(sock->tlsstream.ssl) == 1)
|
SSL_is_init_finished(sock->tlsstream.tls) == 1)
|
||||||
{
|
{
|
||||||
isc_nmhandle_t *tlshandle = isc__nmhandle_get(sock, NULL, NULL);
|
isc_nmhandle_t *tlshandle = isc__nmhandle_get(sock, NULL, NULL);
|
||||||
if (sock->tlsstream.server) {
|
if (sock->tlsstream.server) {
|
||||||
@@ -252,9 +351,7 @@ tls_do_bio(isc_nmsocket_t *sock) {
|
|||||||
ISC_R_SUCCESS,
|
ISC_R_SUCCESS,
|
||||||
sock->listener->accept_cbarg);
|
sock->listener->accept_cbarg);
|
||||||
} else {
|
} else {
|
||||||
sock->connect_cb(tlshandle, ISC_R_SUCCESS,
|
tls_call_connect_cb(sock, tlshandle, ISC_R_SUCCESS);
|
||||||
sock->connect_cbarg);
|
|
||||||
update_result(tlshandle->sock, ISC_R_SUCCESS);
|
|
||||||
}
|
}
|
||||||
isc_nmhandle_detach(&tlshandle);
|
isc_nmhandle_detach(&tlshandle);
|
||||||
sock->tlsstream.state = TLS_IO;
|
sock->tlsstream.state = TLS_IO;
|
||||||
@@ -263,8 +360,14 @@ tls_do_bio(isc_nmsocket_t *sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (tls_err) {
|
switch (tls_err) {
|
||||||
case 0:
|
case SSL_ERROR_NONE:
|
||||||
|
if (sent_shutdown && received_shutdown) {
|
||||||
|
/* clean shutdown */
|
||||||
|
isc_nm_cancelread(sock->outerhandle);
|
||||||
|
isc__nm_tls_close(sock);
|
||||||
|
};
|
||||||
return;
|
return;
|
||||||
|
break;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
if (sock->tlsstream.nsending == 0) {
|
if (sock->tlsstream.nsending == 0) {
|
||||||
/*
|
/*
|
||||||
@@ -272,83 +375,30 @@ tls_do_bio(isc_nmsocket_t *sock) {
|
|||||||
* already the send callback will call it.
|
* already the send callback will call it.
|
||||||
*/
|
*/
|
||||||
async_tls_do_bio(sock);
|
async_tls_do_bio(sock);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
|
if (sock->outerhandle != NULL) {
|
||||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||||
isc_nm_resumeread(sock->outerhandle);
|
isc_nm_resumeread(sock->outerhandle);
|
||||||
|
}
|
||||||
|
return;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = tls_error_to_result(tls_err);
|
result = tls_error_to_result(tls_err);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((req = ISC_LIST_HEAD(sock->tlsstream.sends)) != NULL) {
|
|
||||||
INSIST(VALID_UVREQ(req));
|
|
||||||
rv = SSL_write(sock->tlsstream.ssl, req->uvbuf.base,
|
|
||||||
req->uvbuf.len);
|
|
||||||
if (rv < 0) {
|
|
||||||
if (sock->tlsstream.nsending == 0) {
|
|
||||||
async_tls_do_bio(sock);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rv != (int)req->uvbuf.len) {
|
|
||||||
if (!sock->tlsstream.server &&
|
|
||||||
(sock->tlsstream.state == TLS_HANDSHAKE ||
|
|
||||||
TLS_INIT))
|
|
||||||
{
|
|
||||||
isc_nmhandle_t *tlshandle =
|
|
||||||
isc__nmhandle_get(sock, NULL, NULL);
|
|
||||||
sock->connect_cb(tlshandle, result,
|
|
||||||
sock->connect_cbarg);
|
|
||||||
update_result(tlshandle->sock, result);
|
|
||||||
isc_nmhandle_detach(&tlshandle);
|
|
||||||
}
|
|
||||||
sock->tlsstream.state = TLS_ERROR;
|
|
||||||
async_tls_do_bio(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ISC_LIST_UNLINK(sock->tlsstream.sends, req, link);
|
|
||||||
req->cb.send(sock->statichandle, ISC_R_SUCCESS, req->cbarg);
|
|
||||||
isc__nm_uvreq_put(&req, sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR,
|
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR,
|
||||||
ISC_LOG_ERROR, "SSL error in BIO: %d %s", tls_err,
|
ISC_LOG_ERROR, "SSL error in BIO: %d %s", tls_err,
|
||||||
isc_result_totext(result));
|
isc_result_totext(result));
|
||||||
low_level_error:
|
tls_failed_read_cb(sock, sock->statichandle, result);
|
||||||
if (sock->tlsstream.state == TLS_HANDSHAKE) {
|
|
||||||
isc_nmhandle_t *tlshandle = isc__nmhandle_get(sock, NULL, NULL);
|
|
||||||
if (!sock->tlsstream.server) {
|
|
||||||
sock->connect_cb(tlshandle, result,
|
|
||||||
sock->connect_cbarg);
|
|
||||||
update_result(tlshandle->sock, result);
|
|
||||||
}
|
|
||||||
isc_nmhandle_detach(&tlshandle);
|
|
||||||
} else if (sock->tlsstream.state == TLS_IO) {
|
|
||||||
if (ISC_LIST_HEAD(sock->tlsstream.sends) != NULL) {
|
|
||||||
while ((req = ISC_LIST_HEAD(sock->tlsstream.sends)) !=
|
|
||||||
NULL) {
|
|
||||||
req->cb.send(sock->statichandle, result,
|
|
||||||
req->cbarg);
|
|
||||||
ISC_LIST_UNLINK(sock->tlsstream.sends, req,
|
|
||||||
link);
|
|
||||||
isc__nm_uvreq_put(&req, sock);
|
|
||||||
}
|
|
||||||
} else if (sock->recv_cb != NULL) {
|
|
||||||
tls_failed_read_cb(sock, sock->statichandle, result,
|
|
||||||
false);
|
|
||||||
} else {
|
|
||||||
tls_close_direct(sock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sock->tlsstream.state = TLS_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -360,19 +410,20 @@ tls_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
|
|||||||
REQUIRE(VALID_NMSOCK(tlssock));
|
REQUIRE(VALID_NMSOCK(tlssock));
|
||||||
REQUIRE(VALID_NMHANDLE(handle));
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
REQUIRE(tlssock->tid == isc_nm_tid());
|
REQUIRE(tlssock->tid == isc_nm_tid());
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
tls_failed_read_cb(tlssock, tlssock->statichandle, result,
|
tls_failed_read_cb(tlssock, tlssock->statichandle, result);
|
||||||
true);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = BIO_write(tlssock->tlsstream.app_bio, region->base,
|
rv = BIO_write(tlssock->tlsstream.app_bio, region->base,
|
||||||
region->length);
|
region->length);
|
||||||
|
|
||||||
if (rv != (int)region->length) {
|
if (rv != (int)region->length) {
|
||||||
/* XXXWPK log it? */
|
/* XXXWPK log it? */
|
||||||
tlssock->tlsstream.state = TLS_ERROR;
|
tls_failed_read_cb(tlssock, tlssock->statichandle,
|
||||||
|
ISC_R_TLSERROR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
tls_do_bio(tlssock);
|
tls_do_bio(tlssock, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
@@ -382,20 +433,20 @@ initialize_tls(isc_nmsocket_t *sock, bool server) {
|
|||||||
if (BIO_new_bio_pair(&(sock->tlsstream.ssl_bio), TLS_BUF_SIZE,
|
if (BIO_new_bio_pair(&(sock->tlsstream.ssl_bio), TLS_BUF_SIZE,
|
||||||
&(sock->tlsstream.app_bio), TLS_BUF_SIZE) != 1)
|
&(sock->tlsstream.app_bio), TLS_BUF_SIZE) != 1)
|
||||||
{
|
{
|
||||||
SSL_free(sock->tlsstream.ssl);
|
isc_tls_free(&sock->tlsstream.tls);
|
||||||
return (ISC_R_TLSERROR);
|
return (ISC_R_TLSERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_set_bio(sock->tlsstream.ssl, sock->tlsstream.ssl_bio,
|
SSL_set_bio(sock->tlsstream.tls, sock->tlsstream.ssl_bio,
|
||||||
sock->tlsstream.ssl_bio);
|
sock->tlsstream.ssl_bio);
|
||||||
if (server) {
|
if (server) {
|
||||||
SSL_set_accept_state(sock->tlsstream.ssl);
|
SSL_set_accept_state(sock->tlsstream.tls);
|
||||||
} else {
|
} else {
|
||||||
SSL_set_connect_state(sock->tlsstream.ssl);
|
SSL_set_connect_state(sock->tlsstream.tls);
|
||||||
}
|
}
|
||||||
sock->tlsstream.nsending = 0;
|
sock->tlsstream.nsending = 0;
|
||||||
isc_nm_read(sock->outerhandle, tls_readcb, sock);
|
isc_nm_read(sock->outerhandle, tls_readcb, sock);
|
||||||
tls_do_bio(sock);
|
tls_do_bio(sock, NULL, false);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +454,6 @@ static isc_result_t
|
|||||||
tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||||
isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg;
|
isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg;
|
||||||
isc_nmsocket_t *tlssock = NULL;
|
isc_nmsocket_t *tlssock = NULL;
|
||||||
int r;
|
|
||||||
|
|
||||||
/* If accept() was unsuccessful we can't do anything */
|
/* If accept() was unsuccessful we can't do anything */
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
@@ -420,14 +470,12 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||||||
*/
|
*/
|
||||||
tlssock = isc_mem_get(handle->sock->mgr->mctx, sizeof(*tlssock));
|
tlssock = isc_mem_get(handle->sock->mgr->mctx, sizeof(*tlssock));
|
||||||
isc__nmsocket_init(tlssock, handle->sock->mgr, isc_nm_tlssocket,
|
isc__nmsocket_init(tlssock, handle->sock->mgr, isc_nm_tlssocket,
|
||||||
handle->sock->iface);
|
&tlslistensock->tlsstream.server_iface);
|
||||||
|
|
||||||
/* We need to initialize SSL now to reference SSL_CTX properly */
|
/* We need to initialize SSL now to reference SSL_CTX properly */
|
||||||
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
||||||
tlssock->tlsstream.ssl = SSL_new(tlssock->tlsstream.ctx);
|
tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx);
|
||||||
ISC_LIST_INIT(tlssock->tlsstream.sends);
|
if (tlssock->tlsstream.tls == NULL) {
|
||||||
if (tlssock->tlsstream.ssl == NULL) {
|
|
||||||
update_result(tlssock, ISC_R_TLSERROR);
|
|
||||||
atomic_store(&tlssock->closed, true);
|
atomic_store(&tlssock->closed, true);
|
||||||
isc__nmsocket_detach(&tlssock);
|
isc__nmsocket_detach(&tlssock);
|
||||||
return (ISC_R_TLSERROR);
|
return (ISC_R_TLSERROR);
|
||||||
@@ -442,12 +490,6 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||||||
tlssock->tlsstream.server = true;
|
tlssock->tlsstream.server = true;
|
||||||
tlssock->tlsstream.state = TLS_INIT;
|
tlssock->tlsstream.state = TLS_INIT;
|
||||||
|
|
||||||
r = uv_timer_init(&tlssock->mgr->workers[isc_nm_tid()].loop,
|
|
||||||
&tlssock->timer);
|
|
||||||
RUNTIME_CHECK(r == 0);
|
|
||||||
|
|
||||||
tlssock->timer.data = tlssock;
|
|
||||||
tlssock->timer_initialized = true;
|
|
||||||
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
||||||
|
|
||||||
result = initialize_tls(tlssock, true);
|
result = initialize_tls(tlssock, true);
|
||||||
@@ -469,12 +511,15 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
REQUIRE(VALID_NM(mgr));
|
REQUIRE(VALID_NM(mgr));
|
||||||
|
|
||||||
isc__nmsocket_init(tlssock, mgr, isc_nm_tlslistener, iface);
|
isc__nmsocket_init(tlssock, mgr, isc_nm_tlslistener, iface);
|
||||||
|
tlssock->tlsstream.server_iface = *iface;
|
||||||
|
ISC_LINK_INIT(&tlssock->tlsstream.server_iface.addr, link);
|
||||||
|
tlssock->iface = &tlssock->tlsstream.server_iface;
|
||||||
tlssock->result = ISC_R_DEFAULT;
|
tlssock->result = ISC_R_DEFAULT;
|
||||||
tlssock->accept_cb = accept_cb;
|
tlssock->accept_cb = accept_cb;
|
||||||
tlssock->accept_cbarg = accept_cbarg;
|
tlssock->accept_cbarg = accept_cbarg;
|
||||||
tlssock->extrahandlesize = extrahandlesize;
|
tlssock->extrahandlesize = extrahandlesize;
|
||||||
tlssock->tlsstream.ctx = sslctx;
|
tlssock->tlsstream.ctx = sslctx;
|
||||||
tlssock->tlsstream.ssl = NULL;
|
tlssock->tlsstream.tls = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tlssock will be a TLS 'wrapper' around an unencrypted stream.
|
* tlssock will be a TLS 'wrapper' around an unencrypted stream.
|
||||||
@@ -515,46 +560,25 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface,
|
|||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
int rv;
|
|
||||||
isc__netievent_tlssend_t *ievent = (isc__netievent_tlssend_t *)ev0;
|
isc__netievent_tlssend_t *ievent = (isc__netievent_tlssend_t *)ev0;
|
||||||
isc_nmsocket_t *sock = ievent->sock;
|
isc_nmsocket_t *sock = ievent->sock;
|
||||||
isc__nm_uvreq_t *req = ievent->req;
|
isc__nm_uvreq_t *req = ievent->req;
|
||||||
ievent->req = NULL;
|
|
||||||
REQUIRE(VALID_UVREQ(req));
|
REQUIRE(VALID_UVREQ(req));
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
|
||||||
|
ievent->req = NULL;
|
||||||
|
|
||||||
if (inactive(sock)) {
|
if (inactive(sock)) {
|
||||||
req->cb.send(req->handle, ISC_R_CANCELED, req->cbarg);
|
req->cb.send(req->handle, ISC_R_CANCELED, req->cbarg);
|
||||||
isc__nm_uvreq_put(&req, sock);
|
isc__nm_uvreq_put(&req, sock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!ISC_LIST_EMPTY(sock->tlsstream.sends)) {
|
|
||||||
/* We're not the first */
|
|
||||||
ISC_LIST_APPEND(sock->tlsstream.sends, req, link);
|
|
||||||
tls_do_bio(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = SSL_write(sock->tlsstream.ssl, req->uvbuf.base, req->uvbuf.len);
|
tls_do_bio(sock, req, false);
|
||||||
if (rv < 0) {
|
|
||||||
/*
|
|
||||||
* We might need to read, we might need to write, or the
|
|
||||||
* TLS socket might be dead - in any case, we need to
|
|
||||||
* enqueue the uvreq and let the TLS BIO layer do the rest.
|
|
||||||
*/
|
|
||||||
ISC_LIST_APPEND(sock->tlsstream.sends, req, link);
|
|
||||||
tls_do_bio(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rv != (int)req->uvbuf.len) {
|
|
||||||
sock->tlsstream.state = TLS_ERROR;
|
|
||||||
async_tls_do_bio(sock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req->cb.send(sock->statichandle, ISC_R_SUCCESS, req->cbarg);
|
|
||||||
isc__nm_uvreq_put(&req, sock);
|
isc__nm_uvreq_put(&req, sock);
|
||||||
tls_do_bio(sock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,20 +624,24 @@ isc__nm_async_tlsstartread(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
isc_nmsocket_t *sock = ievent->sock;
|
isc_nmsocket_t *sock = ievent->sock;
|
||||||
|
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
|
||||||
tls_do_bio(sock);
|
tls_do_bio(sock, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
|
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
|
||||||
REQUIRE(VALID_NMHANDLE(handle));
|
|
||||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
|
||||||
REQUIRE(handle->sock->statichandle == handle);
|
|
||||||
REQUIRE(handle->sock->tid == isc_nm_tid());
|
|
||||||
|
|
||||||
isc__netievent_tlsstartread_t *ievent = NULL;
|
isc__netievent_tlsstartread_t *ievent = NULL;
|
||||||
isc_nmsocket_t *sock = handle->sock;
|
isc_nmsocket_t *sock = NULL;
|
||||||
|
|
||||||
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
|
|
||||||
|
sock = handle->sock;
|
||||||
|
|
||||||
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
|
REQUIRE(sock->statichandle == handle);
|
||||||
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
if (inactive(sock)) {
|
if (inactive(sock)) {
|
||||||
cb(handle, ISC_R_NOTCONNECTED, NULL, cbarg);
|
cb(handle, ISC_R_NOTCONNECTED, NULL, cbarg);
|
||||||
@@ -632,56 +660,26 @@ void
|
|||||||
isc__nm_tls_pauseread(isc_nmhandle_t *handle) {
|
isc__nm_tls_pauseread(isc_nmhandle_t *handle) {
|
||||||
REQUIRE(VALID_NMHANDLE(handle));
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||||
isc_nmsocket_t *sock = handle->sock;
|
|
||||||
|
|
||||||
atomic_store(&sock->readpaused, true);
|
atomic_store(&handle->sock->readpaused, true);
|
||||||
|
if (handle->sock->outerhandle != NULL) {
|
||||||
|
isc_nm_pauseread(handle->sock->outerhandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_tls_resumeread(isc_nmhandle_t *handle) {
|
isc__nm_tls_resumeread(isc_nmhandle_t *handle) {
|
||||||
REQUIRE(VALID_NMHANDLE(handle));
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||||
isc_nmsocket_t *sock = handle->sock;
|
|
||||||
|
|
||||||
atomic_store(&sock->readpaused, false);
|
atomic_store(&handle->sock->readpaused, false);
|
||||||
async_tls_do_bio(sock);
|
async_tls_do_bio(handle->sock);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
timer_close_cb(uv_handle_t *handle) {
|
|
||||||
isc_nmsocket_t *sock = (isc_nmsocket_t *)uv_handle_get_data(handle);
|
|
||||||
tls_close_direct(sock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_close_direct(isc_nmsocket_t *sock) {
|
tls_close_direct(isc_nmsocket_t *sock) {
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
/* if (!sock->tlsstream.server) { */
|
|
||||||
/* INSIST(sock->tlsstream.state != TLS_HANDSHAKE && */
|
|
||||||
/* sock->tlsstream.state != TLS_INIT); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
sock->tlsstream.state = TLS_CLOSING;
|
|
||||||
|
|
||||||
if (sock->timer_running) {
|
|
||||||
uv_timer_stop(&sock->timer);
|
|
||||||
sock->timer_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't need atomics here, it's all in single network thread
|
|
||||||
*/
|
|
||||||
if (sock->timer_initialized) {
|
|
||||||
/*
|
|
||||||
* We need to fire the timer callback to clean it up,
|
|
||||||
* it will then call us again (via detach) so that we
|
|
||||||
* can finally close the socket.
|
|
||||||
*/
|
|
||||||
sock->timer_initialized = false;
|
|
||||||
uv_timer_stop(&sock->timer);
|
|
||||||
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
|
|
||||||
} else {
|
|
||||||
/*
|
/*
|
||||||
* At this point we're certain that there are no
|
* At this point we're certain that there are no
|
||||||
* external references, we can close everything.
|
* external references, we can close everything.
|
||||||
@@ -690,28 +688,21 @@ tls_close_direct(isc_nmsocket_t *sock) {
|
|||||||
isc_nm_pauseread(sock->outerhandle);
|
isc_nm_pauseread(sock->outerhandle);
|
||||||
isc_nmhandle_detach(&sock->outerhandle);
|
isc_nmhandle_detach(&sock->outerhandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->listener != NULL) {
|
if (sock->listener != NULL) {
|
||||||
isc__nmsocket_detach(&sock->listener);
|
isc__nmsocket_detach(&sock->listener);
|
||||||
}
|
}
|
||||||
if (sock->tlsstream.ssl != NULL) {
|
|
||||||
SSL_free(sock->tlsstream.ssl);
|
/* further cleanup performed in isc__nm_tls_cleanup_data() */
|
||||||
sock->tlsstream.ssl = NULL;
|
atomic_store(&sock->active, false);
|
||||||
/* These are destroyed when we free SSL* */
|
|
||||||
sock->tlsstream.ctx = NULL;
|
|
||||||
sock->tlsstream.ssl_bio = NULL;
|
|
||||||
}
|
|
||||||
if (sock->tlsstream.app_bio != NULL) {
|
|
||||||
BIO_free(sock->tlsstream.app_bio);
|
|
||||||
sock->tlsstream.app_bio = NULL;
|
|
||||||
}
|
|
||||||
sock->tlsstream.state = TLS_CLOSED;
|
|
||||||
atomic_store(&sock->closed, true);
|
atomic_store(&sock->closed, true);
|
||||||
isc__nmsocket_detach(&sock);
|
sock->tlsstream.state = TLS_CLOSED;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_tls_close(isc_nmsocket_t *sock) {
|
isc__nm_tls_close(isc_nmsocket_t *sock) {
|
||||||
|
isc__netievent_tlsclose_t *ievent = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(sock->type == isc_nm_tlssocket);
|
REQUIRE(sock->type == isc_nm_tlssocket);
|
||||||
|
|
||||||
@@ -720,24 +711,21 @@ isc__nm_tls_close(isc_nmsocket_t *sock) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->tid == isc_nm_tid()) {
|
ievent = isc__nm_get_netievent_tlsclose(sock->mgr, sock);
|
||||||
tls_close_direct(sock);
|
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||||
} else {
|
|
||||||
isc__netievent_tlsclose_t *ievent =
|
|
||||||
isc__nm_get_netievent_tlsclose(sock->mgr, sock);
|
|
||||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
|
||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_tlsclose_t *ievent = (isc__netievent_tlsclose_t *)ev0;
|
isc__netievent_tlsclose_t *ievent = (isc__netievent_tlsclose_t *)ev0;
|
||||||
|
isc_nmsocket_t *sock = ievent->sock;
|
||||||
|
|
||||||
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
|
||||||
tls_close_direct(ievent->sock);
|
tls_close_direct(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -749,9 +737,8 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
|
|||||||
atomic_store(&sock->closed, true);
|
atomic_store(&sock->closed, true);
|
||||||
sock->recv_cb = NULL;
|
sock->recv_cb = NULL;
|
||||||
sock->recv_cbarg = NULL;
|
sock->recv_cbarg = NULL;
|
||||||
if (sock->tlsstream.ssl != NULL) {
|
if (sock->tlsstream.tls != NULL) {
|
||||||
SSL_free(sock->tlsstream.ssl);
|
isc_tls_free(&sock->tlsstream.tls);
|
||||||
sock->tlsstream.ssl = NULL;
|
|
||||||
sock->tlsstream.ctx = NULL;
|
sock->tlsstream.ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,17 +755,25 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
|||||||
isc_nmsocket_t *nsock = NULL, *tsock = NULL;
|
isc_nmsocket_t *nsock = NULL, *tsock = NULL;
|
||||||
isc__netievent_tlsconnect_t *ievent = NULL;
|
isc__netievent_tlsconnect_t *ievent = NULL;
|
||||||
isc_result_t result = ISC_R_DEFAULT;
|
isc_result_t result = ISC_R_DEFAULT;
|
||||||
|
#if defined(NETMGR_TRACE) && defined(NETMGR_TRACE_VERBOSE)
|
||||||
|
fprintf(stderr, "TLS: isc_nm_tlsconnect(): in net thread: %s\n",
|
||||||
|
isc__nm_in_netthread() ? "yes" : "no");
|
||||||
|
#endif /* NETMGR_TRACE */
|
||||||
|
|
||||||
REQUIRE(VALID_NM(mgr));
|
REQUIRE(VALID_NM(mgr));
|
||||||
|
|
||||||
nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
|
nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
|
||||||
isc__nmsocket_init(nsock, mgr, isc_nm_tlssocket, local);
|
isc__nmsocket_init(nsock, mgr, isc_nm_tlssocket, local);
|
||||||
|
nsock->tlsstream.local_iface = *local;
|
||||||
|
ISC_LINK_INIT(&nsock->tlsstream.local_iface.addr, link);
|
||||||
|
nsock->iface = &nsock->tlsstream.local_iface;
|
||||||
nsock->extrahandlesize = extrahandlesize;
|
nsock->extrahandlesize = extrahandlesize;
|
||||||
nsock->result = ISC_R_DEFAULT;
|
nsock->result = ISC_R_DEFAULT;
|
||||||
nsock->connect_cb = cb;
|
nsock->connect_cb = cb;
|
||||||
nsock->connect_cbarg = cbarg;
|
nsock->connect_cbarg = cbarg;
|
||||||
nsock->connect_timeout = timeout;
|
nsock->connect_timeout = timeout;
|
||||||
nsock->tlsstream.ctx = ctx;
|
nsock->tlsstream.ctx = ctx;
|
||||||
|
nsock->tlsstream.connect_from_networker = isc__nm_in_netthread();
|
||||||
|
|
||||||
ievent = isc__nm_get_netievent_tlsconnect(mgr, nsock);
|
ievent = isc__nm_get_netievent_tlsconnect(mgr, nsock);
|
||||||
ievent->local = local->addr;
|
ievent->local = local->addr;
|
||||||
@@ -815,29 +810,31 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tls_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||||
isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg;
|
isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg;
|
||||||
|
isc_nmhandle_t *tlshandle = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(tlssock));
|
REQUIRE(VALID_NMSOCK(tlssock));
|
||||||
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
tlssock->connect_cb(handle, result, tlssock->connect_cbarg);
|
goto error;
|
||||||
update_result(tlssock, result);
|
|
||||||
tls_close_direct(tlssock);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INSIST(VALID_NMHANDLE(handle));
|
|
||||||
|
|
||||||
tlssock->peer = isc_nmhandle_peeraddr(handle);
|
tlssock->peer = isc_nmhandle_peeraddr(handle);
|
||||||
isc_nmhandle_attach(handle, &tlssock->outerhandle);
|
isc_nmhandle_attach(handle, &tlssock->outerhandle);
|
||||||
result = initialize_tls(tlssock, false);
|
result = initialize_tls(tlssock, false);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
tlssock->connect_cb(handle, result, tlssock->connect_cbarg);
|
goto error;
|
||||||
update_result(tlssock, result);
|
|
||||||
tls_close_direct(tlssock);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
error:
|
||||||
|
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
|
||||||
|
atomic_store(&tlssock->closed, true);
|
||||||
|
tls_call_connect_cb(tlssock, tlshandle, result);
|
||||||
|
isc_nmhandle_detach(&tlshandle);
|
||||||
|
isc__nmsocket_detach(&tlssock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -846,7 +843,6 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
(isc__netievent_tlsconnect_t *)ev0;
|
(isc__netievent_tlsconnect_t *)ev0;
|
||||||
isc_nmsocket_t *tlssock = ievent->sock;
|
isc_nmsocket_t *tlssock = ievent->sock;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
int r;
|
|
||||||
isc_nmhandle_t *tlshandle = NULL;
|
isc_nmhandle_t *tlshandle = NULL;
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
@@ -854,36 +850,39 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
/*
|
/*
|
||||||
* We need to initialize SSL now to reference SSL_CTX properly.
|
* We need to initialize SSL now to reference SSL_CTX properly.
|
||||||
*/
|
*/
|
||||||
tlssock->tlsstream.ssl = SSL_new(tlssock->tlsstream.ctx);
|
tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx);
|
||||||
if (tlssock->tlsstream.ssl == NULL) {
|
if (tlssock->tlsstream.tls == NULL) {
|
||||||
result = ISC_R_TLSERROR;
|
result = ISC_R_TLSERROR;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
tlssock->tid = isc_nm_tid();
|
tlssock->tid = isc_nm_tid();
|
||||||
r = uv_timer_init(&tlssock->mgr->workers[isc_nm_tid()].loop,
|
|
||||||
&tlssock->timer);
|
|
||||||
RUNTIME_CHECK(r == 0);
|
|
||||||
|
|
||||||
tlssock->timer.data = tlssock;
|
|
||||||
tlssock->timer_initialized = true;
|
|
||||||
tlssock->tlsstream.state = TLS_INIT;
|
tlssock->tlsstream.state = TLS_INIT;
|
||||||
|
|
||||||
result = isc_nm_tcpconnect(worker->mgr, (isc_nmiface_t *)&ievent->local,
|
result = isc_nm_tcpconnect(worker->mgr, (isc_nmiface_t *)&ievent->local,
|
||||||
(isc_nmiface_t *)&ievent->peer,
|
(isc_nmiface_t *)&ievent->peer,
|
||||||
tls_connect_cb, tlssock,
|
tcp_connected, tlssock,
|
||||||
tlssock->connect_timeout, 0);
|
tlssock->connect_timeout, 0);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (tlssock->tlsstream.connect_from_networker) {
|
||||||
goto error;
|
update_result(tlssock, result);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
|
tlshandle = isc__nmhandle_get(tlssock, NULL, NULL);
|
||||||
atomic_store(&tlssock->closed, true);
|
atomic_store(&tlssock->closed, true);
|
||||||
tlssock->connect_cb(tlshandle, result, tlssock->connect_cbarg);
|
tls_call_connect_cb(tlssock, tlshandle, result);
|
||||||
isc_nmhandle_detach(&tlshandle);
|
isc_nmhandle_detach(&tlshandle);
|
||||||
update_result(tlssock, result);
|
isc__nmsocket_detach(&tlssock);
|
||||||
tls_close_direct(tlssock);
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tls_cancelread(isc_nmsocket_t *sock) {
|
||||||
|
if (!inactive(sock) && sock->tlsstream.state == TLS_IO) {
|
||||||
|
tls_do_bio(sock, NULL, true);
|
||||||
|
} else if (sock->outerhandle != NULL) {
|
||||||
|
isc_nm_cancelread(sock->outerhandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -897,40 +896,69 @@ isc__nm_tls_cancelread(isc_nmhandle_t *handle) {
|
|||||||
|
|
||||||
REQUIRE(sock->type == isc_nm_tlssocket);
|
REQUIRE(sock->type == isc_nm_tlssocket);
|
||||||
|
|
||||||
ievent = isc__nm_get_netievent_tlscancel(sock->mgr, sock, handle);
|
if (sock->tid == isc_nm_tid()) {
|
||||||
|
tls_cancelread(sock);
|
||||||
|
} else {
|
||||||
|
ievent = isc__nm_get_netievent_tlscancel(sock->mgr, sock,
|
||||||
|
handle);
|
||||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||||
(isc__netievent_t *)ievent);
|
(isc__netievent_t *)ievent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_async_tlscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tlscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
isc__netievent_tlscancel_t *ievent = (isc__netievent_tlscancel_t *)ev0;
|
isc__netievent_tlscancel_t *ievent = (isc__netievent_tlscancel_t *)ev0;
|
||||||
isc_nmsocket_t *sock = ievent->sock;
|
isc_nmsocket_t *sock = ievent->sock;
|
||||||
isc_nmhandle_t *handle = ievent->handle;
|
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(worker->id == sock->tid);
|
REQUIRE(worker->id == sock->tid);
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
tls_cancelread(sock);
|
||||||
tls_failed_read_cb(sock, handle, ISC_R_EOF, false);
|
|
||||||
|
|
||||||
if (sock->outerhandle) {
|
|
||||||
isc__nm_tcp_cancelread(sock->outerhandle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_async_tlsdobio(isc__networker_t *worker, isc__netievent_t *ev0) {
|
isc__nm_async_tlsdobio(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
UNUSED(worker);
|
|
||||||
isc__netievent_tlsdobio_t *ievent = (isc__netievent_tlsdobio_t *)ev0;
|
isc__netievent_tlsdobio_t *ievent = (isc__netievent_tlsdobio_t *)ev0;
|
||||||
tls_do_bio(ievent->sock);
|
|
||||||
|
UNUSED(worker);
|
||||||
|
|
||||||
|
tls_do_bio(ievent->sock, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
|
isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
|
||||||
if (sock->tlsstream.tlslistener) {
|
if (sock->type == isc_nm_tcplistener &&
|
||||||
|
sock->tlsstream.tlslistener != NULL) {
|
||||||
REQUIRE(VALID_NMSOCK(sock->tlsstream.tlslistener));
|
REQUIRE(VALID_NMSOCK(sock->tlsstream.tlslistener));
|
||||||
isc__nmsocket_detach(&sock->tlsstream.tlslistener);
|
isc__nmsocket_detach(&sock->tlsstream.tlslistener);
|
||||||
|
} else if (sock->type == isc_nm_tlssocket) {
|
||||||
|
if (sock->tlsstream.tls != NULL) {
|
||||||
|
isc_tls_free(&sock->tlsstream.tls);
|
||||||
|
/* These are destroyed when we free SSL */
|
||||||
|
sock->tlsstream.ctx = NULL;
|
||||||
|
sock->tlsstream.ssl_bio = NULL;
|
||||||
|
}
|
||||||
|
if (sock->tlsstream.app_bio != NULL) {
|
||||||
|
BIO_free(sock->tlsstream.app_bio);
|
||||||
|
sock->tlsstream.app_bio = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||||
|
isc_nmsocket_t *sock = NULL;
|
||||||
|
|
||||||
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
|
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||||
|
REQUIRE(handle->sock->type == isc_nm_tlssocket);
|
||||||
|
|
||||||
|
sock = handle->sock;
|
||||||
|
if (sock->outerhandle != NULL) {
|
||||||
|
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||||
|
isc_nmhandle_settimeout(sock->outerhandle, timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -102,10 +102,10 @@ static const char *description[ISC_R_NRESULTS] = {
|
|||||||
"default", /*%< 68 */
|
"default", /*%< 68 */
|
||||||
"IPv4 prefix", /*%< 69 */
|
"IPv4 prefix", /*%< 69 */
|
||||||
"TLS error", /*%< 70 */
|
"TLS error", /*%< 70 */
|
||||||
|
"ALPN for HTTP/2 failed" /*%< 71 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *identifier[ISC_R_NRESULTS] = {
|
static const char *identifier[ISC_R_NRESULTS] = { "ISC_R_SUCCESS",
|
||||||
"ISC_R_SUCCESS",
|
|
||||||
"ISC_R_NOMEMORY",
|
"ISC_R_NOMEMORY",
|
||||||
"ISC_R_TIMEDOUT",
|
"ISC_R_TIMEDOUT",
|
||||||
"ISC_R_NOTHREADS",
|
"ISC_R_NOTHREADS",
|
||||||
@@ -176,7 +176,7 @@ static const char *identifier[ISC_R_NRESULTS] = {
|
|||||||
"ISC_R_DEFAULT",
|
"ISC_R_DEFAULT",
|
||||||
"ISC_R_IPV4PREFIX",
|
"ISC_R_IPV4PREFIX",
|
||||||
"ISC_R_TLSERROR",
|
"ISC_R_TLSERROR",
|
||||||
};
|
"ISC_R_HTTP2ALPNERROR" };
|
||||||
|
|
||||||
#define ISC_RESULT_RESULTSET 2
|
#define ISC_RESULT_RESULTSET 2
|
||||||
#define ISC_RESULT_UNAVAILABLESET 3
|
#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 POST = ATOMIC_VAR_INIT(true);
|
||||||
|
|
||||||
static atomic_bool use_TLS = ATOMIC_VAR_INIT(false);
|
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 NSENDS 100
|
||||||
#define NWRITES 10
|
#define NWRITES 10
|
||||||
@@ -101,6 +102,63 @@ static SSL_CTX *server_ssl_ctx = NULL;
|
|||||||
#define X(v)
|
#define X(v)
|
||||||
#endif
|
#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
|
static int
|
||||||
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
|
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
@@ -171,7 +229,7 @@ static int
|
|||||||
_setup(void **state) {
|
_setup(void **state) {
|
||||||
UNUSED(state);
|
UNUSED(state);
|
||||||
|
|
||||||
/*workers = isc_os_ncpus();*/
|
workers = isc_os_ncpus();
|
||||||
|
|
||||||
if (isc_test_begin(NULL, false, workers) != ISC_R_SUCCESS) {
|
if (isc_test_begin(NULL, false, workers) != ISC_R_SUCCESS) {
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -243,8 +301,11 @@ nm_setup(void **state) {
|
|||||||
assert_non_null(nm[i]);
|
assert_non_null(nm[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
server_ssl_ctx = NULL;
|
server_tlsctx = NULL;
|
||||||
isc_tlsctx_createserver(NULL, NULL, &server_ssl_ctx);
|
isc_tlsctx_createserver(NULL, NULL, &server_tlsctx);
|
||||||
|
client_tlsctx = NULL;
|
||||||
|
isc_tlsctx_createclient(&client_tlsctx);
|
||||||
|
isc_tlsctx_enable_http2client_alpn(client_tlsctx);
|
||||||
|
|
||||||
*state = nm;
|
*state = nm;
|
||||||
|
|
||||||
@@ -261,8 +322,11 @@ nm_teardown(void **state) {
|
|||||||
}
|
}
|
||||||
isc_mem_put(test_mctx, nm, MAX_NM * sizeof(nm[0]));
|
isc_mem_put(test_mctx, nm, MAX_NM * sizeof(nm[0]));
|
||||||
|
|
||||||
if (server_ssl_ctx) {
|
if (server_tlsctx != NULL) {
|
||||||
isc_tlsctx_free(&server_ssl_ctx);
|
isc_tlsctx_free(&server_tlsctx);
|
||||||
|
}
|
||||||
|
if (client_tlsctx != NULL) {
|
||||||
|
isc_tlsctx_free(&client_tlsctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@@ -276,6 +340,7 @@ sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf,
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
char saddr[INET6_ADDRSTRLEN] = { 0 };
|
char saddr[INET6_ADDRSTRLEN] = { 0 };
|
||||||
int family;
|
int family;
|
||||||
|
|
||||||
if (sa == NULL || outbuf == NULL || outbuf_len == 0) {
|
if (sa == NULL || outbuf == NULL || outbuf_len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -321,8 +386,6 @@ doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
atomic_store(&was_error, true);
|
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_nm_t *listen_nm = nm[0];
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
isc_nmsocket_t *listen_sock = NULL;
|
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);
|
WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE);
|
||||||
|
|
||||||
@@ -404,17 +463,13 @@ doh_noop(void **state) {
|
|||||||
isc_nm_t *connect_nm = nm[1];
|
isc_nm_t *connect_nm = nm[1];
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
isc_sockaddr_t tcp_connect_addr;
|
|
||||||
char req_url[256];
|
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,
|
result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr,
|
||||||
0, NULL, NULL, &listen_sock);
|
0, NULL, NULL, &listen_sock);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
|
||||||
noop_read_cb, NULL, 0);
|
0);
|
||||||
|
|
||||||
isc_nm_stoplistening(listen_sock);
|
isc_nm_stoplistening(listen_sock);
|
||||||
isc_nmsocket_close(&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),
|
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
|
||||||
DOH_PATH);
|
DOH_PATH);
|
||||||
(void)isc_nm_http_connect_send_request(
|
(void)connect_send_request(
|
||||||
connect_nm, req_url, atomic_load(&POST),
|
connect_nm, req_url, atomic_load(&POST),
|
||||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||||
.length = send_msg.len },
|
.length = send_msg.len },
|
||||||
noop_read_cb, NULL, NULL, 30000);
|
noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
|
||||||
|
|
||||||
isc_nm_closedown(connect_nm);
|
isc_nm_closedown(connect_nm);
|
||||||
|
|
||||||
@@ -455,27 +510,23 @@ doh_noresponse(void **state) {
|
|||||||
isc_nm_t *connect_nm = nm[1];
|
isc_nm_t *connect_nm = nm[1];
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
isc_sockaddr_t tcp_connect_addr;
|
|
||||||
char req_url[256];
|
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,
|
result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr,
|
||||||
0, NULL, NULL, &listen_sock);
|
0, NULL, NULL, &listen_sock);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
|
||||||
noop_read_cb, NULL, 0);
|
0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
|
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
|
||||||
DOH_PATH);
|
DOH_PATH);
|
||||||
(void)isc_nm_http_connect_send_request(
|
(void)connect_send_request(
|
||||||
connect_nm, req_url, atomic_load(&POST),
|
connect_nm, req_url, atomic_load(&POST),
|
||||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||||
.length = send_msg.len },
|
.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_nm_stoplistening(listen_sock);
|
||||||
isc_nmsocket_close(&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;
|
size_t i;
|
||||||
atomic_fetch_sub(&nsends, 1);
|
atomic_fetch_sub(&nsends, 1);
|
||||||
for (i = 0; i < NWRITES / 2; i++) {
|
for (i = 0; i < NWRITES / 2; i++) {
|
||||||
eresult = isc_nm_httprequest(
|
eresult = isc__nm_http_request(
|
||||||
handle,
|
handle,
|
||||||
&(isc_region_t){
|
&(isc_region_t){
|
||||||
.base = (uint8_t *)send_msg.base,
|
.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
|
static isc_threadresult_t
|
||||||
doh_connect_thread(isc_threadarg_t arg) {
|
doh_connect_thread(isc_threadarg_t arg) {
|
||||||
isc_nm_t *connect_nm = (isc_nm_t *)arg;
|
isc_nm_t *connect_nm = (isc_nm_t *)arg;
|
||||||
isc_sockaddr_t tcp_connect_addr;
|
|
||||||
char req_url[256];
|
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,
|
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
||||||
sizeof(req_url), DOH_PATH);
|
sizeof(req_url), DOH_PATH);
|
||||||
|
|
||||||
while (atomic_load(&nsends) > 0) {
|
while (atomic_load(&nsends) > 0) {
|
||||||
(void)isc_nm_http_connect_send_request(
|
(void)connect_send_request(
|
||||||
connect_nm, req_url, atomic_load(&POST),
|
connect_nm, req_url, atomic_load(&POST),
|
||||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||||
.length = send_msg.len },
|
.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);
|
return ((isc_threadresult_t)0);
|
||||||
@@ -561,33 +610,26 @@ doh_recv_one(void **state) {
|
|||||||
isc_nm_t *connect_nm = nm[1];
|
isc_nm_t *connect_nm = nm[1];
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
isc_sockaddr_t tcp_connect_addr;
|
|
||||||
char req_url[256];
|
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);
|
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(
|
result = isc_nm_listenhttp(
|
||||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
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);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||||
doh_receive_request_cb, NULL, 0);
|
doh_receive_request_cb, NULL, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
||||||
sizeof(req_url), DOH_PATH);
|
sizeof(req_url), DOH_PATH);
|
||||||
result = isc_nm_http_connect_send_request(
|
result = connect_send_request(
|
||||||
connect_nm, req_url, atomic_load(&POST),
|
connect_nm, req_url, atomic_load(&POST),
|
||||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||||
.length = send_msg.len },
|
.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);
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = isc_nm_httprequest(
|
result = isc__nm_http_request(
|
||||||
handle,
|
handle,
|
||||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||||
.length = send_msg.len },
|
.length = send_msg.len },
|
||||||
@@ -666,7 +708,7 @@ doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = isc_nm_httprequest(
|
result = isc__nm_http_request(
|
||||||
handle,
|
handle,
|
||||||
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
&(isc_region_t){ .base = (uint8_t *)send_msg.base,
|
||||||
.length = send_msg.len },
|
.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) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_nm_resumeread(handle);
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
atomic_store(&was_error, true);
|
atomic_store(&was_error, true);
|
||||||
@@ -688,31 +728,31 @@ doh_recv_two(void **state) {
|
|||||||
isc_nm_t *connect_nm = nm[1];
|
isc_nm_t *connect_nm = nm[1];
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
isc_sockaddr_t tcp_connect_addr;
|
|
||||||
char req_url[256];
|
char req_url[256];
|
||||||
|
isc_tlsctx_t *ctx = NULL;
|
||||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
|
||||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
|
||||||
|
|
||||||
atomic_store(&nsends, 2);
|
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(
|
result = isc_nm_listenhttp(
|
||||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
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);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||||
doh_receive_request_cb, NULL, 0);
|
doh_receive_request_cb, NULL, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
|
||||||
sizeof(req_url), DOH_PATH);
|
sizeof(req_url), DOH_PATH);
|
||||||
|
|
||||||
|
if (atomic_load(&use_TLS)) {
|
||||||
|
ctx = client_tlsctx;
|
||||||
|
}
|
||||||
|
|
||||||
result = isc_nm_httpconnect(
|
result = isc_nm_httpconnect(
|
||||||
connect_nm, NULL, NULL, req_url, atomic_load(&POST),
|
connect_nm, NULL, (isc_nmiface_t *)&tcp_listen_addr, req_url,
|
||||||
doh_connect_send_two_requests_cb, NULL, NULL, 5000, 0);
|
atomic_load(&POST), doh_connect_send_two_requests_cb, NULL, ctx,
|
||||||
|
5000, 0);
|
||||||
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
@@ -783,20 +823,13 @@ doh_recv_send(void **state) {
|
|||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||||
isc_thread_t threads[32] = { 0 };
|
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(
|
result = isc_nm_listenhttp(
|
||||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
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);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||||
doh_receive_request_cb, NULL, 0);
|
doh_receive_request_cb, NULL, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
@@ -859,20 +892,13 @@ doh_recv_half_send(void **state) {
|
|||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||||
isc_thread_t threads[32] = { 0 };
|
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(
|
result = isc_nm_listenhttp(
|
||||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
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);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||||
doh_receive_request_cb, NULL, 0);
|
doh_receive_request_cb, NULL, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
@@ -940,20 +966,13 @@ doh_half_recv_send(void **state) {
|
|||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||||
isc_thread_t threads[32] = { 0 };
|
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(
|
result = isc_nm_listenhttp(
|
||||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
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);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||||
doh_receive_request_cb, NULL, 0);
|
doh_receive_request_cb, NULL, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
@@ -1021,20 +1040,13 @@ doh_half_recv_half_send(void **state) {
|
|||||||
isc_nmsocket_t *listen_sock = NULL;
|
isc_nmsocket_t *listen_sock = NULL;
|
||||||
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1);
|
||||||
isc_thread_t threads[32] = { 0 };
|
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(
|
result = isc_nm_listenhttp(
|
||||||
listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL,
|
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);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH,
|
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
|
||||||
doh_receive_request_cb, NULL, 0);
|
doh_receive_request_cb, NULL, 0);
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
|
|
||||||
@@ -1105,7 +1117,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
|
"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
|
||||||
"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ";
|
"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ";
|
||||||
|
|
||||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||||
assert_true(ret);
|
assert_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
assert_true(len > 0);
|
||||||
@@ -1122,7 +1134,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
|
"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
|
||||||
"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ&";
|
"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ&";
|
||||||
|
|
||||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||||
assert_true(ret);
|
assert_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
assert_true(len > 0);
|
||||||
@@ -1136,7 +1148,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123&dns=567";
|
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_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
assert_true(len > 0);
|
||||||
@@ -1150,7 +1162,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?name1=123&dns=567&name2=123&";
|
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_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
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%"
|
"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";
|
"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_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
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%"
|
"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";
|
"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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1196,7 +1208,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "";
|
char str[] = "";
|
||||||
|
|
||||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||||
assert_false(ret);
|
assert_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1208,7 +1220,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?&";
|
char str[] = "?&";
|
||||||
|
|
||||||
ret = isc__nm_parse_doh_query_string(str, &queryp, &len);
|
ret = isc__nm_parse_httpquery(str, &queryp, &len);
|
||||||
assert_false(ret);
|
assert_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1220,7 +1232,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns&";
|
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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1232,7 +1244,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=&";
|
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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1244,7 +1256,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123&&";
|
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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1256,7 +1268,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123%12&";
|
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_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
assert_true(len > 0);
|
||||||
@@ -1270,7 +1282,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123%ZZ&";
|
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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1282,7 +1294,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123%%&";
|
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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1294,7 +1306,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123%AZ&";
|
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_false(ret);
|
||||||
assert_null(queryp);
|
assert_null(queryp);
|
||||||
assert_true(len == 0);
|
assert_true(len == 0);
|
||||||
@@ -1306,7 +1318,7 @@ doh_parse_GET_query_string(void **state) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char str[] = "?dns=123%0AZ&";
|
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_true(ret);
|
||||||
assert_non_null(queryp);
|
assert_non_null(queryp);
|
||||||
assert_true(len > 0);
|
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
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
const struct CMUnitTest tests_short[] = {
|
const struct CMUnitTest tests_short[] = {
|
||||||
@@ -1745,17 +1697,21 @@ main(void) {
|
|||||||
cmocka_unit_test_setup_teardown(doh_cloudflare_POST, nm_setup,
|
cmocka_unit_test_setup_teardown(doh_cloudflare_POST, nm_setup,
|
||||||
nm_teardown)*/
|
nm_teardown)*/
|
||||||
};
|
};
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
UNUSED(tests_long);
|
UNUSED(tests_long);
|
||||||
return (cmocka_run_group_tests(tests_short, _setup, _teardown));
|
result = (cmocka_run_group_tests(tests_short, _setup, _teardown));
|
||||||
#else
|
#else
|
||||||
if (getenv("CI") != NULL || !reuse_supported) {
|
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 {
|
} else {
|
||||||
return (cmocka_run_group_tests(tests_long, _setup, _teardown));
|
result =
|
||||||
|
(cmocka_run_group_tests(tests_long, _setup, _teardown));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* HAVE_CMOCKA */
|
#else /* HAVE_CMOCKA */
|
||||||
|
132
lib/isc/tls.c
132
lib/isc/tls.c
@@ -9,6 +9,9 @@
|
|||||||
* information regarding copyright ownership.
|
* information regarding copyright ownership.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include <openssl/conf.h>
|
#include <openssl/conf.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/opensslv.h>
|
#include <openssl/opensslv.h>
|
||||||
@@ -220,14 +223,7 @@ isc_tlsctx_createserver(const char *keyfile, const char *certfile,
|
|||||||
const SSL_METHOD *method = NULL;
|
const SSL_METHOD *method = NULL;
|
||||||
|
|
||||||
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
||||||
|
REQUIRE((keyfile == NULL) == (certfile == NULL));
|
||||||
if (ephemeral) {
|
|
||||||
INSIST(keyfile == NULL);
|
|
||||||
INSIST(certfile == NULL);
|
|
||||||
} else {
|
|
||||||
INSIST(keyfile != NULL);
|
|
||||||
INSIST(certfile != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
method = TLS_server_method();
|
method = TLS_server_method();
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
@@ -355,3 +351,123 @@ ssl_error:
|
|||||||
|
|
||||||
return (ISC_R_TLSERROR);
|
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_closedown
|
||||||
isc_nm_destroy
|
isc_nm_destroy
|
||||||
isc_nm_detach
|
isc_nm_detach
|
||||||
isc_nm_http_add_doh_endpoint
|
isc_nm_http_endpoint
|
||||||
isc_nm_http_add_endpoint
|
|
||||||
isc_nm_http_connect_send_request
|
|
||||||
isc_nm_httpconnect
|
isc_nm_httpconnect
|
||||||
isc_nm_httprequest
|
|
||||||
isc_nm_listenhttp
|
isc_nm_listenhttp
|
||||||
isc_nm_listentcpdns
|
isc_nm_listentcpdns
|
||||||
isc_nm_listentls
|
isc_nm_listentls
|
||||||
@@ -710,17 +707,20 @@ isc_timermgr_create
|
|||||||
isc_timermgr_createinctx
|
isc_timermgr_createinctx
|
||||||
isc_timermgr_destroy
|
isc_timermgr_destroy
|
||||||
isc_timermgr_poke
|
isc_timermgr_poke
|
||||||
isc__tls_initialize
|
isc_tls_get_http2_alpn
|
||||||
isc__tls_shutdown
|
isc_tls_create
|
||||||
|
isc_tls_free
|
||||||
isc_tlsctx_createclient
|
isc_tlsctx_createclient
|
||||||
isc_tlsctx_createserver
|
isc_tlsctx_createserver
|
||||||
isc_tlsctx_free
|
isc_tlsctx_free
|
||||||
|
isc_tlsctx_enable_http2client_alpn
|
||||||
|
isc_tlsctx_enable_http2server_alpn
|
||||||
|
isc_tm_timegm
|
||||||
|
isc_tm_strptime
|
||||||
isc__trampoline_initialize
|
isc__trampoline_initialize
|
||||||
isc__trampoline_shutdown
|
isc__trampoline_shutdown
|
||||||
isc__trampoline_get
|
isc__trampoline_get
|
||||||
isc__trampoline_run
|
isc__trampoline_run
|
||||||
isc_tm_timegm
|
|
||||||
isc_tm_strptime
|
|
||||||
isc_url_parse
|
isc_url_parse
|
||||||
isc_utf8_bom
|
isc_utf8_bom
|
||||||
isc_utf8_valid
|
isc_utf8_valid
|
||||||
|
@@ -556,8 +556,8 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
|
|||||||
|
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
for (i = 0; i < neps; i++) {
|
for (i = 0; i < neps; i++) {
|
||||||
result = isc_nm_http_add_doh_endpoint(
|
result = isc_nm_http_endpoint(sock, eps[i],
|
||||||
sock, eps[i], ns__client_request, ifp,
|
ns__client_request, ifp,
|
||||||
sizeof(ns_client_t));
|
sizeof(ns_client_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -368,9 +368,12 @@
|
|||||||
./bin/tests/system/dnstap/setup.sh SH 2018,2019,2020,2021
|
./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/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/dnstap/ydump.py PYTHON 2016,2017,2018,2019,2020,2021
|
||||||
./bin/tests/system/dot/clean.sh SH 2020,2021
|
./bin/tests/system/doth/clean.sh SH 2020,2021
|
||||||
./bin/tests/system/dot/setup.sh SH 2020,2021
|
./bin/tests/system/doth/dig1.good X 2021
|
||||||
./bin/tests/system/dot/tests.sh SH 2020,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/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/ns1/named.args X 2013,2014,2018,2019,2020,2021
|
||||||
./bin/tests/system/dscp/ns2/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.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/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/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/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/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
|
./bin/tests/system/zero/setup.sh SH 2013,2014,2016,2018,2019,2020,2021
|
||||||
|
Reference in New Issue
Block a user