Home | History | Annotate | Line # | Download | only in isc
doh_test.c revision 1.3
      1 /*	$NetBSD: doh_test.c,v 1.3 2025/01/26 16:25:49 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #include <inttypes.h>
     17 #include <sched.h> /* IWYU pragma: keep */
     18 #include <setjmp.h>
     19 #include <stdarg.h>
     20 #include <stdbool.h>
     21 #include <stddef.h>
     22 #include <stdlib.h>
     23 #include <time.h>
     24 #include <unistd.h>
     25 
     26 /*
     27  * As a workaround, include an OpenSSL header file before including cmocka.h,
     28  * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a
     29  * redefined malloc in cmocka.h.
     30  */
     31 #include <openssl/err.h>
     32 
     33 #define UNIT_TESTING
     34 #include <cmocka.h>
     35 
     36 #include <isc/async.h>
     37 #include <isc/atomic.h>
     38 #include <isc/buffer.h>
     39 #include <isc/condition.h>
     40 #include <isc/mutex.h>
     41 #include <isc/netmgr.h>
     42 #include <isc/nonce.h>
     43 #include <isc/os.h>
     44 #include <isc/refcount.h>
     45 #include <isc/sockaddr.h>
     46 #include <isc/thread.h>
     47 #include <isc/util.h>
     48 #include <isc/uv.h>
     49 
     50 #include "uv_wrap.h"
     51 #define KEEP_BEFORE
     52 
     53 #include "netmgr/http.c"
     54 #include "netmgr/netmgr-int.h"
     55 #include "netmgr/socket.c"
     56 
     57 #include <tests/isc.h>
     58 
     59 #define MAX_NM 2
     60 
     61 static isc_sockaddr_t tcp_listen_addr;
     62 
     63 static uint64_t send_magic = 0;
     64 static uint64_t stop_magic = 0;
     65 
     66 static uv_buf_t send_msg = { .base = (char *)&send_magic,
     67 			     .len = sizeof(send_magic) };
     68 
     69 static atomic_int_fast64_t active_cconnects = 0;
     70 static atomic_int_fast64_t nsends = 0;
     71 static atomic_int_fast64_t ssends = 0;
     72 static atomic_int_fast64_t sreads = 0;
     73 static atomic_int_fast64_t csends = 0;
     74 static atomic_int_fast64_t creads = 0;
     75 static atomic_int_fast64_t ctimeouts = 0;
     76 static atomic_int_fast64_t total_sends = 0;
     77 
     78 static int expected_ssends;
     79 static int expected_sreads;
     80 static int expected_csends;
     81 static int expected_cconnects;
     82 static int expected_creads;
     83 static int expected_ctimeouts;
     84 
     85 #define have_expected_ssends(v) ((v) >= expected_ssends && expected_ssends >= 0)
     86 #define have_expected_sreads(v) ((v) >= expected_sreads && expected_sreads >= 0)
     87 #define have_expected_csends(v) ((v) >= expected_csends && expected_csends >= 0)
     88 #define have_expected_cconnects(v) \
     89 	((v) >= expected_cconnects && expected_cconnects >= 0)
     90 #define have_expected_creads(v) ((v) >= expected_creads && expected_creads >= 0)
     91 #define have_expected_ctimeouts(v) \
     92 	((v) >= expected_ctimeouts && expected_ctimeouts >= 0)
     93 
     94 static bool noanswer = false;
     95 
     96 static atomic_bool POST = true;
     97 
     98 static atomic_bool use_TLS = false;
     99 static isc_tlsctx_t *server_tlsctx = NULL;
    100 static isc_tlsctx_t *client_tlsctx = NULL;
    101 static isc_tlsctx_client_session_cache_t *client_sess_cache = NULL;
    102 
    103 static isc_quota_t listener_quota;
    104 static atomic_bool check_listener_quota = false;
    105 
    106 static isc_nm_http_endpoints_t *endpoints = NULL;
    107 
    108 static atomic_bool use_PROXY = false;
    109 static atomic_bool use_PROXY_over_TLS = false;
    110 
    111 static isc_nm_t **nm = NULL;
    112 
    113 /* Timeout for soft-timeout tests (0.05 seconds) */
    114 #define T_SOFT	  50
    115 #define T_CONNECT 30 * 1000
    116 
    117 #define NSENDS	100
    118 #define NWRITES 10
    119 
    120 #define CHECK_RANGE_FULL(v)                                    \
    121 	{                                                      \
    122 		int __v = atomic_load(&v);                     \
    123 		assert_true(__v >= atomic_load(&total_sends)); \
    124 	}
    125 
    126 #define CHECK_RANGE_HALF(v)                                        \
    127 	{                                                          \
    128 		int __v = atomic_load(&v);                         \
    129 		assert_true(__v >= atomic_load(&total_sends) / 2); \
    130 	}
    131 
    132 /* Enable this to print values while running tests */
    133 #undef PRINT_DEBUG
    134 #ifdef PRINT_DEBUG
    135 #define X(v) fprintf(stderr, #v " = %" PRIu64 "\n", atomic_load(&v))
    136 #else
    137 #define X(v)
    138 #endif
    139 
    140 static isc_nm_proxy_type_t
    141 get_proxy_type(void) {
    142 	if (!atomic_load(&use_PROXY)) {
    143 		return ISC_NM_PROXY_NONE;
    144 	} else if (atomic_load(&use_TLS) && atomic_load(&use_PROXY_over_TLS)) {
    145 		return ISC_NM_PROXY_ENCRYPTED;
    146 	}
    147 
    148 	return ISC_NM_PROXY_PLAIN;
    149 }
    150 
    151 static void
    152 proxy_verify_unspec_endpoint(isc_nmhandle_t *handle) {
    153 	isc_sockaddr_t real_local, real_peer, local, peer;
    154 
    155 	if (isc_nm_is_proxy_unspec(handle)) {
    156 		peer = isc_nmhandle_peeraddr(handle);
    157 		local = isc_nmhandle_localaddr(handle);
    158 		real_peer = isc_nmhandle_real_peeraddr(handle);
    159 		real_local = isc_nmhandle_real_localaddr(handle);
    160 
    161 		assert_true(isc_sockaddr_equal(&peer, &real_peer));
    162 		assert_true(isc_sockaddr_equal(&local, &real_local));
    163 	}
    164 }
    165 
    166 typedef struct csdata {
    167 	isc_mem_t *mctx;
    168 	isc_nm_recv_cb_t reply_cb;
    169 	void *cb_arg;
    170 	isc_region_t region;
    171 } csdata_t;
    172 
    173 static void
    174 connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
    175 	csdata_t data;
    176 
    177 	(void)atomic_fetch_sub(&active_cconnects, 1);
    178 	memmove(&data, arg, sizeof(data));
    179 	isc_mem_put(data.mctx, arg, sizeof(data));
    180 	if (result != ISC_R_SUCCESS) {
    181 		goto error;
    182 	}
    183 
    184 	REQUIRE(VALID_NMHANDLE(handle));
    185 
    186 	result = isc__nm_http_request(handle, &data.region, data.reply_cb,
    187 				      data.cb_arg);
    188 	if (result != ISC_R_SUCCESS) {
    189 		goto error;
    190 	}
    191 
    192 	isc_mem_putanddetach(&data.mctx, data.region.base, data.region.length);
    193 	return;
    194 error:
    195 	data.reply_cb(handle, result, NULL, data.cb_arg);
    196 	isc_mem_putanddetach(&data.mctx, data.region.base, data.region.length);
    197 }
    198 
    199 static void
    200 connect_send_request(isc_nm_t *mgr, const char *uri, bool post,
    201 		     isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg,
    202 		     bool tls, unsigned int timeout) {
    203 	isc_region_t copy;
    204 	csdata_t *data = NULL;
    205 	isc_tlsctx_t *ctx = NULL;
    206 
    207 	copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length),
    208 			       .length = region->length };
    209 	memmove(copy.base, region->base, region->length);
    210 	data = isc_mem_get(mgr->mctx, sizeof(*data));
    211 	*data = (csdata_t){ .reply_cb = cb, .cb_arg = cbarg, .region = copy };
    212 	isc_mem_attach(mgr->mctx, &data->mctx);
    213 	if (tls) {
    214 		ctx = client_tlsctx;
    215 	}
    216 
    217 	isc_nm_httpconnect(mgr, NULL, &tcp_listen_addr, uri, post,
    218 			   connect_send_cb, data, ctx, client_sess_cache,
    219 			   timeout, get_proxy_type(), NULL);
    220 }
    221 
    222 static int
    223 setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
    224 	isc_result_t result;
    225 	socklen_t addrlen = sizeof(*addr);
    226 	int fd;
    227 	int r;
    228 
    229 	isc_sockaddr_fromin6(addr, &in6addr_loopback, 0);
    230 
    231 	fd = socket(AF_INET6, family, 0);
    232 	if (fd < 0) {
    233 		perror("setup_ephemeral_port: socket()");
    234 		return -1;
    235 	}
    236 
    237 	r = bind(fd, (const struct sockaddr *)&addr->type.sa,
    238 		 sizeof(addr->type.sin6));
    239 	if (r != 0) {
    240 		perror("setup_ephemeral_port: bind()");
    241 		isc__nm_closesocket(fd);
    242 		return r;
    243 	}
    244 
    245 	r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen);
    246 	if (r != 0) {
    247 		perror("setup_ephemeral_port: getsockname()");
    248 		isc__nm_closesocket(fd);
    249 		return r;
    250 	}
    251 
    252 	result = isc__nm_socket_reuse(fd, 1);
    253 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
    254 		fprintf(stderr,
    255 			"setup_ephemeral_port: isc__nm_socket_reuse(): %s",
    256 			isc_result_totext(result));
    257 		close(fd);
    258 		return -1;
    259 	}
    260 
    261 	result = isc__nm_socket_reuse_lb(fd);
    262 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
    263 		fprintf(stderr,
    264 			"setup_ephemeral_port: isc__nm_socket_reuse_lb(): %s",
    265 			isc_result_totext(result));
    266 		close(fd);
    267 		return -1;
    268 	}
    269 
    270 #if IPV6_RECVERR
    271 #define setsockopt_on(socket, level, name) \
    272 	setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
    273 
    274 	r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR);
    275 	if (r != 0) {
    276 		perror("setup_ephemeral_port");
    277 		close(fd);
    278 		return r;
    279 	}
    280 #endif
    281 
    282 	return fd;
    283 }
    284 
    285 /* Generic */
    286 
    287 static void
    288 noop_read_cb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
    289 	     void *cbarg) {
    290 	UNUSED(handle);
    291 	UNUSED(result);
    292 	UNUSED(region);
    293 	UNUSED(cbarg);
    294 }
    295 
    296 thread_local uint8_t tcp_buffer_storage[4096];
    297 thread_local size_t tcp_buffer_length = 0;
    298 
    299 static int
    300 setup_test(void **state) {
    301 	char *env_workers = getenv("ISC_TASK_WORKERS");
    302 	uv_os_sock_t tcp_listen_sock = -1;
    303 
    304 	tcp_listen_addr = (isc_sockaddr_t){ .length = 0 };
    305 	tcp_listen_sock = setup_ephemeral_port(&tcp_listen_addr, SOCK_STREAM);
    306 	if (tcp_listen_sock < 0) {
    307 		return -1;
    308 	}
    309 	close(tcp_listen_sock);
    310 	tcp_listen_sock = -1;
    311 
    312 	if (env_workers != NULL) {
    313 		workers = atoi(env_workers);
    314 	} else {
    315 		workers = isc_os_ncpus();
    316 	}
    317 	INSIST(workers > 0);
    318 
    319 	atomic_store(&total_sends, NSENDS * NWRITES);
    320 	atomic_store(&nsends, atomic_load(&total_sends));
    321 
    322 	atomic_store(&csends, 0);
    323 	atomic_store(&creads, 0);
    324 	atomic_store(&sreads, 0);
    325 	atomic_store(&ssends, 0);
    326 	atomic_store(&ctimeouts, 0);
    327 	atomic_store(&active_cconnects, 0);
    328 
    329 	expected_cconnects = -1;
    330 	expected_csends = -1;
    331 	expected_creads = -1;
    332 	expected_sreads = -1;
    333 	expected_ssends = -1;
    334 	expected_ctimeouts = -1;
    335 
    336 	atomic_store(&POST, false);
    337 	atomic_store(&use_TLS, false);
    338 	atomic_store(&use_PROXY, false);
    339 	atomic_store(&use_PROXY_over_TLS, false);
    340 
    341 	noanswer = false;
    342 
    343 	isc_nonce_buf(&send_magic, sizeof(send_magic));
    344 	isc_nonce_buf(&stop_magic, sizeof(stop_magic));
    345 	if (send_magic == stop_magic) {
    346 		return -1;
    347 	}
    348 
    349 	setup_loopmgr(state);
    350 
    351 	nm = isc_mem_cget(mctx, MAX_NM, sizeof(nm[0]));
    352 	for (size_t i = 0; i < MAX_NM; i++) {
    353 		isc_netmgr_create(mctx, loopmgr, &nm[i]);
    354 		assert_non_null(nm[i]);
    355 	}
    356 
    357 	server_tlsctx = NULL;
    358 	isc_tlsctx_createserver(NULL, NULL, &server_tlsctx);
    359 	isc_tlsctx_enable_http2server_alpn(server_tlsctx);
    360 	client_tlsctx = NULL;
    361 	isc_tlsctx_createclient(&client_tlsctx);
    362 	isc_tlsctx_enable_http2client_alpn(client_tlsctx);
    363 	isc_tlsctx_client_session_cache_create(
    364 		mctx, client_tlsctx,
    365 		ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE,
    366 		&client_sess_cache);
    367 
    368 	isc_quota_init(&listener_quota, 0);
    369 	atomic_store(&check_listener_quota, false);
    370 
    371 	INSIST(endpoints == NULL);
    372 	endpoints = isc_nm_http_endpoints_new(mctx);
    373 
    374 	*state = nm;
    375 
    376 	return 0;
    377 }
    378 
    379 static int
    380 teardown_test(void **state ISC_ATTR_UNUSED) {
    381 	for (size_t i = 0; i < MAX_NM; i++) {
    382 		isc_netmgr_destroy(&nm[i]);
    383 		assert_null(nm[i]);
    384 	}
    385 	isc_mem_cput(mctx, nm, MAX_NM, sizeof(nm[0]));
    386 
    387 	teardown_loopmgr(state);
    388 
    389 	if (server_tlsctx != NULL) {
    390 		isc_tlsctx_free(&server_tlsctx);
    391 	}
    392 	if (client_tlsctx != NULL) {
    393 		isc_tlsctx_free(&client_tlsctx);
    394 	}
    395 
    396 	isc_tlsctx_client_session_cache_detach(&client_sess_cache);
    397 
    398 	isc_quota_destroy(&listener_quota);
    399 
    400 	isc_nm_http_endpoints_detach(&endpoints);
    401 
    402 	return 0;
    403 }
    404 
    405 thread_local size_t nwrites = NWRITES;
    406 
    407 static void
    408 sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf,
    409 		size_t outbuf_len, const char *append) {
    410 	isc_nm_http_makeuri(https, sa, NULL, 0, append, outbuf, outbuf_len);
    411 }
    412 
    413 static isc_quota_t *
    414 init_listener_quota(size_t nthreads) {
    415 	isc_quota_t *quotap = NULL;
    416 	if (atomic_load(&check_listener_quota)) {
    417 		unsigned int max_quota = ISC_MAX(nthreads / 2, 1);
    418 		isc_quota_max(&listener_quota, max_quota);
    419 		quotap = &listener_quota;
    420 	}
    421 	return quotap;
    422 }
    423 
    424 static void
    425 doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
    426 		     isc_region_t *region, void *cbarg) {
    427 	assert_non_null(handle);
    428 	UNUSED(cbarg);
    429 	UNUSED(region);
    430 
    431 	if (eresult == ISC_R_SUCCESS) {
    432 		if (atomic_load(&use_PROXY)) {
    433 			assert_true(isc_nm_is_proxy_handle(handle));
    434 		}
    435 		(void)atomic_fetch_sub(&nsends, 1);
    436 		if (have_expected_csends(atomic_fetch_add(&csends, 1) + 1) ||
    437 		    have_expected_creads(atomic_fetch_add(&creads, 1) + 1))
    438 		{
    439 			isc_loopmgr_shutdown(loopmgr);
    440 		}
    441 	} else {
    442 		isc_loopmgr_shutdown(loopmgr);
    443 	}
    444 }
    445 
    446 static void
    447 doh_reply_sent_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
    448 	UNUSED(eresult);
    449 	UNUSED(cbarg);
    450 
    451 	assert_non_null(handle);
    452 
    453 	if (eresult == ISC_R_SUCCESS) {
    454 		atomic_fetch_add(&ssends, 1);
    455 	}
    456 }
    457 
    458 static void
    459 doh_receive_request_cb(isc_nmhandle_t *handle, isc_result_t eresult,
    460 		       isc_region_t *region, void *cbarg) {
    461 	uint64_t magic = 0;
    462 
    463 	UNUSED(cbarg);
    464 	assert_non_null(handle);
    465 
    466 	if (eresult != ISC_R_SUCCESS) {
    467 		return;
    468 	}
    469 
    470 	if (atomic_load(&use_PROXY)) {
    471 		assert_true(isc_nm_is_proxy_handle(handle));
    472 		proxy_verify_unspec_endpoint(handle);
    473 	}
    474 
    475 	atomic_fetch_add(&sreads, 1);
    476 
    477 	memmove(tcp_buffer_storage + tcp_buffer_length, region->base,
    478 		region->length);
    479 	tcp_buffer_length += region->length;
    480 
    481 	while (tcp_buffer_length >= sizeof(magic)) {
    482 		magic = *(uint64_t *)tcp_buffer_storage;
    483 		assert_true(magic == stop_magic || magic == send_magic);
    484 
    485 		tcp_buffer_length -= sizeof(magic);
    486 		memmove(tcp_buffer_storage, tcp_buffer_storage + sizeof(magic),
    487 			tcp_buffer_length);
    488 
    489 		if (magic == send_magic) {
    490 			if (!noanswer) {
    491 				isc_nm_send(handle, region, doh_reply_sent_cb,
    492 					    NULL);
    493 			}
    494 			return;
    495 		} else if (magic == stop_magic) {
    496 			/*
    497 			 * We are done, so we don't send anything back.
    498 			 * There should be no more packets in the buffer.
    499 			 */
    500 			assert_int_equal(tcp_buffer_length, 0);
    501 		}
    502 	}
    503 }
    504 
    505 ISC_LOOP_TEST_IMPL(mock_doh_uv_tcp_bind) {
    506 	isc_nm_t *listen_nm = nm[0];
    507 	isc_result_t result = ISC_R_SUCCESS;
    508 	isc_nmsocket_t *listen_sock = NULL;
    509 
    510 	WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE);
    511 
    512 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
    513 					   noop_read_cb, NULL);
    514 	assert_int_equal(result, ISC_R_SUCCESS);
    515 	result = isc_nm_listenhttp(listen_nm, ISC_NM_LISTEN_ALL,
    516 				   &tcp_listen_addr, 0, NULL, NULL, endpoints,
    517 				   0, false, &listen_sock);
    518 	assert_int_not_equal(result, ISC_R_SUCCESS);
    519 	assert_null(listen_sock);
    520 
    521 	RESET_RETURN;
    522 
    523 	isc_loopmgr_shutdown(loopmgr);
    524 }
    525 
    526 static void
    527 listen_sock_close(void *arg) {
    528 	isc_nmsocket_t *listen_sock = arg;
    529 
    530 	isc_nm_stoplistening(listen_sock);
    531 	isc_nmsocket_close(&listen_sock);
    532 	assert_null(listen_sock);
    533 }
    534 
    535 static void
    536 doh_noop(void *arg ISC_ATTR_UNUSED) {
    537 	isc_nm_t *listen_nm = nm[0];
    538 	isc_nm_t *connect_nm = nm[1];
    539 	isc_result_t result = ISC_R_SUCCESS;
    540 	isc_nmsocket_t *listen_sock = NULL;
    541 	char req_url[256];
    542 
    543 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
    544 					   noop_read_cb, NULL);
    545 	assert_int_equal(result, ISC_R_SUCCESS);
    546 
    547 	result = isc_nm_listenhttp(listen_nm, ISC_NM_LISTEN_ALL,
    548 				   &tcp_listen_addr, 0, NULL, NULL, endpoints,
    549 				   0, get_proxy_type(), &listen_sock);
    550 	assert_int_equal(result, ISC_R_SUCCESS);
    551 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
    552 
    553 	sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
    554 			ISC_NM_HTTP_DEFAULT_PATH);
    555 	connect_send_request(connect_nm, req_url, atomic_load(&POST),
    556 			     &(isc_region_t){ .base = (uint8_t *)send_msg.base,
    557 					      .length = send_msg.len },
    558 			     noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
    559 
    560 	isc_loopmgr_shutdown(loopmgr);
    561 
    562 	assert_int_equal(0, atomic_load(&csends));
    563 	assert_int_equal(0, atomic_load(&creads));
    564 	assert_int_equal(0, atomic_load(&sreads));
    565 	assert_int_equal(0, atomic_load(&ssends));
    566 }
    567 
    568 ISC_LOOP_TEST_IMPL(doh_noop_POST) {
    569 	atomic_store(&POST, true);
    570 	doh_noop(arg);
    571 }
    572 
    573 ISC_LOOP_TEST_IMPL(doh_noop_GET) {
    574 	atomic_store(&POST, false);
    575 	doh_noop(arg);
    576 }
    577 
    578 static void
    579 doh_noresponse(void *arg ISC_ATTR_UNUSED) {
    580 	isc_nm_t *listen_nm = nm[0];
    581 	isc_nm_t *connect_nm = nm[1];
    582 	isc_result_t result = ISC_R_SUCCESS;
    583 	isc_nmsocket_t *listen_sock = NULL;
    584 	char req_url[256];
    585 
    586 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
    587 					   noop_read_cb, NULL);
    588 	assert_int_equal(result, ISC_R_SUCCESS);
    589 
    590 	result = isc_nm_listenhttp(listen_nm, ISC_NM_LISTEN_ALL,
    591 				   &tcp_listen_addr, 0, NULL, NULL, endpoints,
    592 				   0, get_proxy_type(), &listen_sock);
    593 	assert_int_equal(result, ISC_R_SUCCESS);
    594 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
    595 
    596 	sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
    597 			ISC_NM_HTTP_DEFAULT_PATH);
    598 	connect_send_request(connect_nm, req_url, atomic_load(&POST),
    599 			     &(isc_region_t){ .base = (uint8_t *)send_msg.base,
    600 					      .length = send_msg.len },
    601 			     noop_read_cb, NULL, atomic_load(&use_TLS), 30000);
    602 
    603 	isc_loopmgr_shutdown(loopmgr);
    604 }
    605 
    606 ISC_LOOP_TEST_IMPL(doh_noresponse_POST) {
    607 	atomic_store(&POST, true);
    608 	doh_noresponse(arg);
    609 }
    610 
    611 ISC_LOOP_TEST_IMPL(doh_noresponse_GET) {
    612 	atomic_store(&POST, false);
    613 	doh_noresponse(arg);
    614 }
    615 
    616 static void
    617 timeout_query_sent_cb(isc_nmhandle_t *handle, isc_result_t eresult,
    618 		      void *cbarg) {
    619 	UNUSED(eresult);
    620 	UNUSED(cbarg);
    621 
    622 	assert_non_null(handle);
    623 
    624 	if (eresult == ISC_R_SUCCESS) {
    625 		atomic_fetch_add(&csends, 1);
    626 	}
    627 
    628 	isc_nmhandle_detach(&handle);
    629 }
    630 
    631 static void
    632 timeout_retry_cb(isc_nmhandle_t *handle, isc_result_t eresult,
    633 		 isc_region_t *region ISC_ATTR_UNUSED,
    634 		 void *arg ISC_ATTR_UNUSED) {
    635 	assert_non_null(handle);
    636 
    637 	atomic_fetch_add(&ctimeouts, 1);
    638 
    639 	if (eresult == ISC_R_TIMEDOUT && atomic_load(&ctimeouts) < 5) {
    640 		isc_nmhandle_settimeout(handle, T_SOFT);
    641 		return;
    642 	}
    643 
    644 	isc_nmhandle_detach(&handle);
    645 	isc_loopmgr_shutdown(loopmgr);
    646 }
    647 
    648 static void
    649 timeout_request_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
    650 	isc_nmhandle_t *sendhandle = NULL;
    651 	isc_nmhandle_t *readhandle = NULL;
    652 
    653 	REQUIRE(VALID_NMHANDLE(handle));
    654 
    655 	if (result != ISC_R_SUCCESS) {
    656 		return;
    657 	}
    658 
    659 	isc_nmhandle_attach(handle, &sendhandle);
    660 	isc_nm_send(handle,
    661 		    &(isc_region_t){ .base = (uint8_t *)send_msg.base,
    662 				     .length = send_msg.len },
    663 		    timeout_query_sent_cb, arg);
    664 
    665 	isc_nmhandle_attach(handle, &readhandle);
    666 	isc_nm_read(handle, timeout_retry_cb, NULL);
    667 }
    668 
    669 static void
    670 doh_timeout_recovery(void *arg ISC_ATTR_UNUSED) {
    671 	isc_nm_t *listen_nm = nm[0];
    672 	isc_nmsocket_t *listen_sock = NULL;
    673 	isc_nm_t *connect_nm = nm[1];
    674 	isc_result_t result = ISC_R_SUCCESS;
    675 	isc_tlsctx_t *ctx = atomic_load(&use_TLS) ? server_tlsctx : NULL;
    676 	char req_url[256];
    677 
    678 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
    679 					   doh_receive_request_cb, NULL);
    680 	assert_int_equal(result, ISC_R_SUCCESS);
    681 
    682 	result = isc_nm_listenhttp(listen_nm, ISC_NM_LISTEN_ALL,
    683 				   &tcp_listen_addr, 0, NULL, NULL, endpoints,
    684 				   0, get_proxy_type(), &listen_sock);
    685 	assert_int_equal(result, ISC_R_SUCCESS);
    686 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
    687 
    688 	/*
    689 	 * Accept connections but don't send responses, forcing client
    690 	 * reads to time out.
    691 	 */
    692 	noanswer = true;
    693 
    694 	/*
    695 	 * Shorten all the TCP client timeouts to 0.05 seconds.
    696 	 * timeout_retry_cb() will give up after five timeouts.
    697 	 */
    698 	isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
    699 	sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
    700 			ISC_NM_HTTP_DEFAULT_PATH);
    701 	isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url,
    702 			   atomic_load(&POST), timeout_request_cb, NULL, ctx,
    703 			   client_sess_cache, T_CONNECT, get_proxy_type(),
    704 			   NULL);
    705 }
    706 
    707 static int
    708 doh_timeout_recovery_teardown(void **state) {
    709 	assert_true(atomic_load(&ctimeouts) == 5);
    710 	return teardown_test(state);
    711 }
    712 
    713 ISC_LOOP_TEST_IMPL(doh_timeout_recovery_POST) {
    714 	atomic_store(&POST, true);
    715 	doh_timeout_recovery(arg);
    716 }
    717 
    718 ISC_LOOP_TEST_IMPL(doh_timeout_recovery_GET) {
    719 	atomic_store(&POST, false);
    720 	doh_timeout_recovery(arg);
    721 }
    722 
    723 static void
    724 doh_connect_thread(void *arg);
    725 
    726 static void
    727 doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult,
    728 			  isc_region_t *region, void *cbarg) {
    729 	isc_nm_t *connect_nm = (isc_nm_t *)cbarg;
    730 
    731 	if (eresult != ISC_R_SUCCESS) {
    732 		return;
    733 	}
    734 
    735 	assert_non_null(handle);
    736 	UNUSED(region);
    737 
    738 	int_fast64_t sends = atomic_fetch_sub(&nsends, 1);
    739 	atomic_fetch_add(&csends, 1);
    740 	atomic_fetch_add(&creads, 1);
    741 	if (sends > 0 && connect_nm != NULL) {
    742 		size_t i;
    743 		for (i = 0; i < NWRITES / 2; i++) {
    744 			eresult = isc__nm_http_request(
    745 				handle,
    746 				&(isc_region_t){
    747 					.base = (uint8_t *)send_msg.base,
    748 					.length = send_msg.len },
    749 				doh_receive_send_reply_cb, NULL);
    750 			if (eresult == ISC_R_CANCELED) {
    751 				break;
    752 			}
    753 			assert_true(eresult == ISC_R_SUCCESS);
    754 		}
    755 
    756 		isc_async_current(doh_connect_thread, connect_nm);
    757 	}
    758 	if (sends <= 0) {
    759 		isc_loopmgr_shutdown(loopmgr);
    760 	}
    761 }
    762 
    763 static void
    764 doh_connect_thread(void *arg) {
    765 	isc_nm_t *connect_nm = (isc_nm_t *)arg;
    766 	char req_url[256];
    767 	int64_t sends = atomic_load(&nsends);
    768 
    769 	sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
    770 			sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH);
    771 
    772 	/*
    773 	 * We need to back off and slow down if we start getting
    774 	 * errors, to prevent a thundering herd problem.
    775 	 */
    776 	int_fast64_t active = atomic_fetch_add(&active_cconnects, 1);
    777 	if (active > workers) {
    778 		atomic_fetch_sub(&active_cconnects, 1);
    779 		return;
    780 	}
    781 	connect_send_request(connect_nm, req_url, atomic_load(&POST),
    782 			     &(isc_region_t){ .base = (uint8_t *)send_msg.base,
    783 					      .length = send_msg.len },
    784 			     doh_receive_send_reply_cb, connect_nm,
    785 			     atomic_load(&use_TLS), 30000);
    786 
    787 	if (sends <= 0) {
    788 		isc_loopmgr_shutdown(loopmgr);
    789 	}
    790 }
    791 
    792 static void
    793 doh_recv_one(void *arg ISC_ATTR_UNUSED) {
    794 	isc_nm_t *listen_nm = nm[0];
    795 	isc_nm_t *connect_nm = nm[1];
    796 	isc_result_t result = ISC_R_SUCCESS;
    797 	isc_nmsocket_t *listen_sock = NULL;
    798 	char req_url[256];
    799 	isc_quota_t *quotap = init_listener_quota(workers);
    800 
    801 	atomic_store(&total_sends, 1);
    802 	expected_creads = 1;
    803 
    804 	atomic_store(&nsends, atomic_load(&total_sends));
    805 
    806 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
    807 					   doh_receive_request_cb, NULL);
    808 	assert_int_equal(result, ISC_R_SUCCESS);
    809 
    810 	result = isc_nm_listenhttp(
    811 		listen_nm, ISC_NM_LISTEN_ALL, &tcp_listen_addr, 0, quotap,
    812 		atomic_load(&use_TLS) ? server_tlsctx : NULL, endpoints, 0,
    813 		get_proxy_type(), &listen_sock);
    814 	assert_int_equal(result, ISC_R_SUCCESS);
    815 
    816 	sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
    817 			sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH);
    818 	connect_send_request(connect_nm, req_url, atomic_load(&POST),
    819 			     &(isc_region_t){ .base = (uint8_t *)send_msg.base,
    820 					      .length = send_msg.len },
    821 			     doh_receive_reply_cb, NULL, atomic_load(&use_TLS),
    822 			     30000);
    823 
    824 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
    825 }
    826 
    827 static int
    828 doh_recv_one_teardown(void **state) {
    829 	X(total_sends);
    830 	X(csends);
    831 	X(creads);
    832 	X(sreads);
    833 	X(ssends);
    834 
    835 	assert_int_equal(atomic_load(&csends), 1);
    836 	assert_int_equal(atomic_load(&creads), 1);
    837 	assert_int_equal(atomic_load(&sreads), 1);
    838 	assert_int_equal(atomic_load(&ssends), 1);
    839 
    840 	return teardown_test(state);
    841 }
    842 
    843 ISC_LOOP_TEST_IMPL(doh_recv_one_POST) {
    844 	atomic_store(&POST, true);
    845 	doh_recv_one(arg);
    846 }
    847 
    848 ISC_LOOP_TEST_IMPL(doh_recv_one_GET) {
    849 	atomic_store(&POST, false);
    850 	doh_recv_one(arg);
    851 }
    852 
    853 ISC_LOOP_TEST_IMPL(doh_recv_one_POST_TLS) {
    854 	atomic_store(&use_TLS, true);
    855 	atomic_store(&POST, true);
    856 	doh_recv_one(arg);
    857 }
    858 
    859 ISC_LOOP_TEST_IMPL(doh_recv_one_GET_TLS) {
    860 	atomic_store(&use_TLS, true);
    861 	atomic_store(&POST, false);
    862 	doh_recv_one(arg);
    863 }
    864 
    865 ISC_LOOP_TEST_IMPL(doh_recv_one_POST_quota) {
    866 	atomic_store(&POST, true);
    867 	atomic_store(&check_listener_quota, true);
    868 	doh_recv_one(arg);
    869 }
    870 
    871 ISC_LOOP_TEST_IMPL(doh_recv_one_GET_quota) {
    872 	atomic_store(&POST, false);
    873 	atomic_store(&check_listener_quota, true);
    874 	doh_recv_one(arg);
    875 }
    876 
    877 ISC_LOOP_TEST_IMPL(doh_recv_one_POST_TLS_quota) {
    878 	atomic_store(&use_TLS, true);
    879 	atomic_store(&POST, true);
    880 	atomic_store(&check_listener_quota, true);
    881 	doh_recv_one(arg);
    882 }
    883 
    884 ISC_LOOP_TEST_IMPL(doh_recv_one_GET_TLS_quota) {
    885 	atomic_store(&use_TLS, true);
    886 	atomic_store(&POST, false);
    887 	atomic_store(&check_listener_quota, true);
    888 	doh_recv_one(arg);
    889 }
    890 
    891 static void
    892 doh_connect_send_two_requests_cb(isc_nmhandle_t *handle, isc_result_t result,
    893 				 void *arg) {
    894 	REQUIRE(VALID_NMHANDLE(handle));
    895 	if (result != ISC_R_SUCCESS) {
    896 		return;
    897 	}
    898 
    899 	result = isc__nm_http_request(
    900 		handle,
    901 		&(isc_region_t){ .base = (uint8_t *)send_msg.base,
    902 				 .length = send_msg.len },
    903 		doh_receive_reply_cb, arg);
    904 	if (result != ISC_R_SUCCESS) {
    905 		return;
    906 	}
    907 
    908 	result = isc__nm_http_request(
    909 		handle,
    910 		&(isc_region_t){ .base = (uint8_t *)send_msg.base,
    911 				 .length = send_msg.len },
    912 		doh_receive_reply_cb, arg);
    913 	if (result != ISC_R_SUCCESS) {
    914 		return;
    915 	}
    916 }
    917 
    918 static void
    919 doh_recv_two(void *arg ISC_ATTR_UNUSED) {
    920 	isc_nm_t *listen_nm = nm[0];
    921 	isc_nm_t *connect_nm = nm[1];
    922 	isc_result_t result = ISC_R_SUCCESS;
    923 	isc_nmsocket_t *listen_sock = NULL;
    924 	char req_url[256];
    925 	isc_tlsctx_t *ctx = NULL;
    926 	isc_quota_t *quotap = init_listener_quota(workers);
    927 
    928 	atomic_store(&total_sends, 2);
    929 	expected_creads = 2;
    930 
    931 	atomic_store(&nsends, atomic_load(&total_sends));
    932 
    933 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
    934 					   doh_receive_request_cb, NULL);
    935 	assert_int_equal(result, ISC_R_SUCCESS);
    936 
    937 	result = isc_nm_listenhttp(
    938 		listen_nm, ISC_NM_LISTEN_ALL, &tcp_listen_addr, 0, quotap,
    939 		atomic_load(&use_TLS) ? server_tlsctx : NULL, endpoints, 0,
    940 		get_proxy_type(), &listen_sock);
    941 	assert_int_equal(result, ISC_R_SUCCESS);
    942 
    943 	sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
    944 			sizeof(req_url), ISC_NM_HTTP_DEFAULT_PATH);
    945 
    946 	if (atomic_load(&use_TLS)) {
    947 		ctx = client_tlsctx;
    948 	}
    949 
    950 	isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url,
    951 			   atomic_load(&POST), doh_connect_send_two_requests_cb,
    952 			   NULL, ctx, client_sess_cache, 5000, get_proxy_type(),
    953 			   NULL);
    954 
    955 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
    956 }
    957 
    958 static int
    959 doh_recv_two_teardown(void **state) {
    960 	X(total_sends);
    961 	X(csends);
    962 	X(creads);
    963 	X(sreads);
    964 	X(ssends);
    965 
    966 	assert_int_equal(atomic_load(&csends), 2);
    967 	assert_int_equal(atomic_load(&creads), 2);
    968 	assert_int_equal(atomic_load(&sreads), 2);
    969 	assert_int_equal(atomic_load(&ssends), 2);
    970 
    971 	return teardown_test(state);
    972 }
    973 
    974 ISC_LOOP_TEST_IMPL(doh_recv_two_POST) {
    975 	atomic_store(&POST, true);
    976 	doh_recv_two(arg);
    977 }
    978 
    979 ISC_LOOP_TEST_IMPL(doh_recv_two_GET) {
    980 	atomic_store(&POST, false);
    981 	doh_recv_two(arg);
    982 }
    983 
    984 ISC_LOOP_TEST_IMPL(doh_recv_two_POST_TLS) {
    985 	atomic_store(&use_TLS, true);
    986 	atomic_store(&POST, true);
    987 	doh_recv_two(arg);
    988 }
    989 
    990 ISC_LOOP_TEST_IMPL(doh_recv_two_GET_TLS) {
    991 	atomic_store(&use_TLS, true);
    992 	atomic_store(&POST, false);
    993 	doh_recv_two(arg);
    994 }
    995 
    996 ISC_LOOP_TEST_IMPL(doh_recv_two_POST_quota) {
    997 	atomic_store(&POST, true);
    998 	atomic_store(&check_listener_quota, true);
    999 	doh_recv_two(arg);
   1000 }
   1001 
   1002 ISC_LOOP_TEST_IMPL(doh_recv_two_GET_quota) {
   1003 	atomic_store(&POST, false);
   1004 	atomic_store(&check_listener_quota, true);
   1005 	doh_recv_two(arg);
   1006 }
   1007 
   1008 ISC_LOOP_TEST_IMPL(doh_recv_two_POST_TLS_quota) {
   1009 	atomic_store(&use_TLS, true);
   1010 	atomic_store(&POST, true);
   1011 	atomic_store(&check_listener_quota, true);
   1012 	doh_recv_two(arg);
   1013 }
   1014 
   1015 ISC_LOOP_TEST_IMPL(doh_recv_two_GET_TLS_quota) {
   1016 	atomic_store(&use_TLS, true);
   1017 	atomic_store(&POST, false);
   1018 	atomic_store(&check_listener_quota, true);
   1019 	doh_recv_two(arg);
   1020 }
   1021 
   1022 static void
   1023 doh_recv_send(void *arg ISC_ATTR_UNUSED) {
   1024 	isc_nm_t *listen_nm = nm[0];
   1025 	isc_nm_t *connect_nm = nm[1];
   1026 	isc_result_t result = ISC_R_SUCCESS;
   1027 	isc_nmsocket_t *listen_sock = NULL;
   1028 	size_t nthreads = isc_loopmgr_nloops(loopmgr);
   1029 	isc_quota_t *quotap = init_listener_quota(workers);
   1030 
   1031 	atomic_store(&total_sends, 1000);
   1032 	atomic_store(&nsends, 1000);
   1033 
   1034 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
   1035 					   doh_receive_request_cb, NULL);
   1036 	assert_int_equal(result, ISC_R_SUCCESS);
   1037 
   1038 	result = isc_nm_listenhttp(
   1039 		listen_nm, ISC_NM_LISTEN_ALL, &tcp_listen_addr, 0, quotap,
   1040 		atomic_load(&use_TLS) ? server_tlsctx : NULL, endpoints, 0,
   1041 		get_proxy_type(), &listen_sock);
   1042 	assert_int_equal(result, ISC_R_SUCCESS);
   1043 
   1044 	for (size_t i = 0; i < nthreads; i++) {
   1045 		isc_async_run(isc_loop_get(loopmgr, i), doh_connect_thread,
   1046 			      connect_nm);
   1047 	}
   1048 
   1049 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
   1050 }
   1051 
   1052 static int
   1053 doh_recv_send_teardown(void **state) {
   1054 	int res = teardown_test(state);
   1055 
   1056 	X(total_sends);
   1057 	X(csends);
   1058 	X(creads);
   1059 	X(sreads);
   1060 	X(ssends);
   1061 
   1062 	CHECK_RANGE_FULL(csends);
   1063 	CHECK_RANGE_FULL(creads);
   1064 	CHECK_RANGE_FULL(sreads);
   1065 	CHECK_RANGE_FULL(ssends);
   1066 
   1067 	return res;
   1068 }
   1069 
   1070 ISC_LOOP_TEST_IMPL(doh_recv_send_POST) {
   1071 	atomic_store(&POST, true);
   1072 	doh_recv_send(arg);
   1073 }
   1074 
   1075 ISC_LOOP_TEST_IMPL(doh_recv_send_GET) {
   1076 	atomic_store(&POST, false);
   1077 	doh_recv_send(arg);
   1078 }
   1079 
   1080 ISC_LOOP_TEST_IMPL(doh_recv_send_POST_TLS) {
   1081 	atomic_store(&POST, true);
   1082 	atomic_store(&use_TLS, true);
   1083 	doh_recv_send(arg);
   1084 }
   1085 
   1086 ISC_LOOP_TEST_IMPL(doh_recv_send_GET_TLS) {
   1087 	atomic_store(&POST, false);
   1088 	atomic_store(&use_TLS, true);
   1089 	doh_recv_send(arg);
   1090 }
   1091 
   1092 ISC_LOOP_TEST_IMPL(doh_recv_send_POST_quota) {
   1093 	atomic_store(&POST, true);
   1094 	atomic_store(&check_listener_quota, true);
   1095 	doh_recv_send(arg);
   1096 }
   1097 
   1098 ISC_LOOP_TEST_IMPL(doh_recv_send_GET_quota) {
   1099 	atomic_store(&POST, false);
   1100 	atomic_store(&check_listener_quota, true);
   1101 	doh_recv_send(arg);
   1102 }
   1103 
   1104 ISC_LOOP_TEST_IMPL(doh_recv_send_POST_TLS_quota) {
   1105 	atomic_store(&POST, true);
   1106 	atomic_store(&use_TLS, true);
   1107 	atomic_store(&check_listener_quota, true);
   1108 	doh_recv_send(arg);
   1109 }
   1110 
   1111 ISC_LOOP_TEST_IMPL(doh_recv_send_GET_TLS_quota) {
   1112 	atomic_store(&POST, false);
   1113 	atomic_store(&use_TLS, true);
   1114 	atomic_store(&check_listener_quota, true);
   1115 	doh_recv_send(arg);
   1116 }
   1117 
   1118 static int
   1119 doh_bad_connect_uri_teardown(void **state) {
   1120 	X(total_sends);
   1121 	X(csends);
   1122 	X(creads);
   1123 	X(sreads);
   1124 	X(ssends);
   1125 
   1126 	/* As we used an ill-formed URI, there ought to be an error. */
   1127 	assert_int_equal(atomic_load(&csends), 0);
   1128 	assert_int_equal(atomic_load(&creads), 0);
   1129 	assert_int_equal(atomic_load(&sreads), 0);
   1130 	assert_int_equal(atomic_load(&ssends), 0);
   1131 
   1132 	return teardown_test(state);
   1133 }
   1134 
   1135 /* See: GL #2858, !5319 */
   1136 ISC_LOOP_TEST_IMPL(doh_bad_connect_uri) {
   1137 	isc_nm_t *listen_nm = nm[0];
   1138 	isc_nm_t *connect_nm = nm[1];
   1139 	isc_result_t result = ISC_R_SUCCESS;
   1140 	isc_nmsocket_t *listen_sock = NULL;
   1141 	char req_url[256];
   1142 	isc_quota_t *quotap = init_listener_quota(workers);
   1143 
   1144 	atomic_store(&total_sends, 1);
   1145 
   1146 	atomic_store(&nsends, atomic_load(&total_sends));
   1147 
   1148 	result = isc_nm_http_endpoints_add(endpoints, ISC_NM_HTTP_DEFAULT_PATH,
   1149 					   doh_receive_request_cb, NULL);
   1150 	assert_int_equal(result, ISC_R_SUCCESS);
   1151 
   1152 	result = isc_nm_listenhttp(
   1153 		listen_nm, ISC_NM_LISTEN_ALL, &tcp_listen_addr, 0, quotap,
   1154 		server_tlsctx, endpoints, 0, get_proxy_type(), &listen_sock);
   1155 	assert_int_equal(result, ISC_R_SUCCESS);
   1156 
   1157 	/*
   1158 	 * "https://::1:XXXX/dns-query" is a bad URI, it should be
   1159 	 * "https://[::1]:XXXX/dns-query"
   1160 	 */
   1161 	(void)snprintf(req_url, sizeof(req_url), "https://::1:%u/%s",
   1162 		       isc_sockaddr_getport(&tcp_listen_addr),
   1163 		       ISC_NM_HTTP_DEFAULT_PATH);
   1164 	connect_send_request(connect_nm, req_url, atomic_load(&POST),
   1165 			     &(isc_region_t){ .base = (uint8_t *)send_msg.base,
   1166 					      .length = send_msg.len },
   1167 			     doh_receive_reply_cb, NULL, true, 30000);
   1168 
   1169 	isc_loop_teardown(mainloop, listen_sock_close, listen_sock);
   1170 }
   1171 
   1172 ISC_RUN_TEST_IMPL(doh_parse_GET_query_string) {
   1173 	/* valid */
   1174 	{
   1175 		bool ret;
   1176 		const char *queryp = NULL;
   1177 		size_t len = 0;
   1178 		char str[] =
   1179 			"dns=AAABAAABAAAAAAAAAWE-"
   1180 			"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
   1181 			"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ";
   1182 
   1183 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1184 		assert_true(ret);
   1185 		assert_non_null(queryp);
   1186 		assert_true(len > 0);
   1187 		assert_true(len == strlen(str) - 4);
   1188 		assert_true(memcmp(queryp, str + 4, len) == 0);
   1189 	}
   1190 	/* valid */
   1191 	{
   1192 		bool ret;
   1193 		const char *queryp = NULL;
   1194 		size_t len = 0;
   1195 		char str[] =
   1196 			"?dns=AAABAAABAAAAAAAAAWE-"
   1197 			"NjJjaGFyYWN0ZXJsYWJlbC1tYWtlcy1iYXNlNjR1cmwtZGlzdGluY3"
   1198 			"QtZnJvbS1zdGFuZGFyZC1iYXNlNjQHZXhhbXBsZQNjb20AAAEAAQ&";
   1199 
   1200 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1201 		assert_true(ret);
   1202 		assert_non_null(queryp);
   1203 		assert_true(len > 0);
   1204 		assert_true(len == strlen(str) - 6);
   1205 		assert_true(memcmp(queryp, str + 5, len) == 0);
   1206 	}
   1207 	/* valid */
   1208 	{
   1209 		bool ret;
   1210 		const char *queryp = NULL;
   1211 		size_t len = 0;
   1212 		char str[] = "?dns=123&dns=567";
   1213 
   1214 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1215 		assert_true(ret);
   1216 		assert_non_null(queryp);
   1217 		assert_true(len > 0);
   1218 		assert_true(len == 3);
   1219 		assert_true(memcmp(queryp, "567", 3) == 0);
   1220 	}
   1221 	/* valid */
   1222 	{
   1223 		bool ret;
   1224 		const char *queryp = NULL;
   1225 		size_t len = 0;
   1226 		char str[] = "?name1=123&dns=567&name2=123&";
   1227 
   1228 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1229 		assert_true(ret);
   1230 		assert_non_null(queryp);
   1231 		assert_true(len > 0);
   1232 		assert_true(len == 3);
   1233 		assert_true(memcmp(queryp, "567", 3) == 0);
   1234 	}
   1235 	/* complex, but still valid */
   1236 	{
   1237 		bool ret;
   1238 		const char *queryp = NULL;
   1239 		size_t len = 0;
   1240 		char str[] =
   1241 			"?title=%D0%92%D1%96%D0%B4%D1%81%D0%BE%D1%82%D0%BA%D0%"
   1242 			"BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%"
   1243 			"D0%BD%D0%BD%D1%8F&dns=123&veaction=edit&section=0";
   1244 
   1245 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1246 		assert_true(ret);
   1247 		assert_non_null(queryp);
   1248 		assert_true(len > 0);
   1249 		assert_true(len == 3);
   1250 		assert_true(memcmp(queryp, "123", 3) == 0);
   1251 	}
   1252 	/* invalid */
   1253 	{
   1254 		bool ret;
   1255 		const char *queryp = NULL;
   1256 		size_t len = 0;
   1257 		char str[] =
   1258 			"?title=%D0%92%D1%96%D0%B4%D1%81%D0%BE%D1%82%D0%BA%D0%"
   1259 			"BE%D0%B2%D0%B5_%D0%BA%D0%BE%D0%B4%D1%83%D0%B2%D0%B0%"
   1260 			"D0%BD%D0%BD%D1%8F&veaction=edit&section=0";
   1261 
   1262 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1263 		assert_false(ret);
   1264 		assert_null(queryp);
   1265 		assert_true(len == 0);
   1266 	}
   1267 	/* invalid */
   1268 	{
   1269 		bool ret;
   1270 		const char *queryp = NULL;
   1271 		size_t len = 0;
   1272 		char str[] = "";
   1273 
   1274 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1275 		assert_false(ret);
   1276 		assert_null(queryp);
   1277 		assert_true(len == 0);
   1278 	}
   1279 	/* invalid */
   1280 	{
   1281 		bool ret;
   1282 		const char *queryp = NULL;
   1283 		size_t len = 0;
   1284 		char str[] = "?&";
   1285 
   1286 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1287 		assert_false(ret);
   1288 		assert_null(queryp);
   1289 		assert_true(len == 0);
   1290 	}
   1291 	/* invalid */
   1292 	{
   1293 		bool ret;
   1294 		const char *queryp = NULL;
   1295 		size_t len = 0;
   1296 		char str[] = "?dns&";
   1297 
   1298 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1299 		assert_false(ret);
   1300 		assert_null(queryp);
   1301 		assert_true(len == 0);
   1302 	}
   1303 	/* invalid */
   1304 	{
   1305 		bool ret;
   1306 		const char *queryp = NULL;
   1307 		size_t len = 0;
   1308 		char str[] = "?dns=&";
   1309 
   1310 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1311 		assert_false(ret);
   1312 		assert_null(queryp);
   1313 		assert_true(len == 0);
   1314 	}
   1315 	/* invalid */
   1316 	{
   1317 		bool ret;
   1318 		const char *queryp = NULL;
   1319 		size_t len = 0;
   1320 		char str[] = "?dns=123&&";
   1321 
   1322 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1323 		assert_false(ret);
   1324 		assert_null(queryp);
   1325 		assert_true(len == 0);
   1326 	}
   1327 	/* valid */
   1328 	{
   1329 		bool ret;
   1330 		const char *queryp = NULL;
   1331 		size_t len = 0;
   1332 		char str[] = "?dns=123%12&";
   1333 
   1334 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1335 		assert_true(ret);
   1336 		assert_non_null(queryp);
   1337 		assert_true(len > 0);
   1338 		assert_true(len == 6);
   1339 		assert_true(memcmp(queryp, "123%12", 6) == 0);
   1340 	}
   1341 	/* invalid */
   1342 	{
   1343 		bool ret;
   1344 		const char *queryp = NULL;
   1345 		size_t len = 0;
   1346 		char str[] = "?dns=123%ZZ&";
   1347 
   1348 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1349 		assert_false(ret);
   1350 		assert_null(queryp);
   1351 		assert_true(len == 0);
   1352 	}
   1353 	/* invalid */
   1354 	{
   1355 		bool ret;
   1356 		const char *queryp = NULL;
   1357 		size_t len = 0;
   1358 		char str[] = "?dns=123%%&";
   1359 
   1360 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1361 		assert_false(ret);
   1362 		assert_null(queryp);
   1363 		assert_true(len == 0);
   1364 	}
   1365 	/* invalid */
   1366 	{
   1367 		bool ret;
   1368 		const char *queryp = NULL;
   1369 		size_t len = 0;
   1370 		char str[] = "?dns=123%AZ&";
   1371 
   1372 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1373 		assert_false(ret);
   1374 		assert_null(queryp);
   1375 		assert_true(len == 0);
   1376 	}
   1377 	/* valid */
   1378 	{
   1379 		bool ret;
   1380 		const char *queryp = NULL;
   1381 		size_t len = 0;
   1382 		char str[] = "?dns=123%0AZ&";
   1383 
   1384 		ret = isc__nm_parse_httpquery(str, &queryp, &len);
   1385 		assert_true(ret);
   1386 		assert_non_null(queryp);
   1387 		assert_true(len > 0);
   1388 		assert_true(len == 7);
   1389 		assert_true(memcmp(queryp, "123%0AZ", 7) == 0);
   1390 	}
   1391 }
   1392 
   1393 ISC_RUN_TEST_IMPL(doh_base64url_to_base64) {
   1394 	char *res;
   1395 	size_t res_len = 0;
   1396 	/* valid */
   1397 	{
   1398 		char test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4";
   1399 		char res_test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4=";
   1400 
   1401 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1402 						  &res_len);
   1403 		assert_non_null(res);
   1404 		assert_true(res_len == strlen(res_test));
   1405 		assert_true(strcmp(res, res_test) == 0);
   1406 		isc_mem_free(mctx, res);
   1407 	}
   1408 	/* valid */
   1409 	{
   1410 		char test[] = "YW55IGNhcm5hbCBwbGVhcw";
   1411 		char res_test[] = "YW55IGNhcm5hbCBwbGVhcw==";
   1412 
   1413 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1414 						  &res_len);
   1415 		assert_non_null(res);
   1416 		assert_true(res_len == strlen(res_test));
   1417 		assert_true(strcmp(res, res_test) == 0);
   1418 		isc_mem_free(mctx, res);
   1419 	}
   1420 	/* valid */
   1421 	{
   1422 		char test[] = "YW55IGNhcm5hbCBwbGVhc3Vy";
   1423 		char res_test[] = "YW55IGNhcm5hbCBwbGVhc3Vy";
   1424 
   1425 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1426 						  &res_len);
   1427 		assert_non_null(res);
   1428 		assert_true(res_len == strlen(res_test));
   1429 		assert_true(strcmp(res, res_test) == 0);
   1430 		isc_mem_free(mctx, res);
   1431 	}
   1432 	/* valid */
   1433 	{
   1434 		char test[] = "YW55IGNhcm5hbCBwbGVhc3U";
   1435 		char res_test[] = "YW55IGNhcm5hbCBwbGVhc3U=";
   1436 
   1437 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1438 						  &res_len);
   1439 		assert_non_null(res);
   1440 		assert_true(res_len == strlen(res_test));
   1441 		assert_true(strcmp(res, res_test) == 0);
   1442 		isc_mem_free(mctx, res);
   1443 	}
   1444 	/* valid */
   1445 	{
   1446 		char test[] = "YW55IGNhcm5hbCBwbGVhcw";
   1447 		char res_test[] = "YW55IGNhcm5hbCBwbGVhcw==";
   1448 
   1449 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1450 						  &res_len);
   1451 		assert_non_null(res);
   1452 		assert_true(res_len == strlen(res_test));
   1453 		assert_true(strcmp(res, res_test) == 0);
   1454 		isc_mem_free(mctx, res);
   1455 	}
   1456 	/* valid */
   1457 	{
   1458 		char test[] = "PDw_Pz8-Pg";
   1459 		char res_test[] = "PDw/Pz8+Pg==";
   1460 
   1461 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1462 						  &res_len);
   1463 		assert_non_null(res);
   1464 		assert_true(res_len == strlen(res_test));
   1465 		assert_true(strcmp(res, res_test) == 0);
   1466 		isc_mem_free(mctx, res);
   1467 	}
   1468 	/* valid */
   1469 	{
   1470 		char test[] = "PDw_Pz8-Pg";
   1471 		char res_test[] = "PDw/Pz8+Pg==";
   1472 
   1473 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1474 						  NULL);
   1475 		assert_non_null(res);
   1476 		assert_true(strcmp(res, res_test) == 0);
   1477 		isc_mem_free(mctx, res);
   1478 	}
   1479 	/* invalid */
   1480 	{
   1481 		char test[] = "YW55IGNhcm5hbCBwbGVhcw";
   1482 		res_len = 0;
   1483 
   1484 		res = isc__nm_base64url_to_base64(mctx, test, 0, &res_len);
   1485 		assert_null(res);
   1486 		assert_true(res_len == 0);
   1487 	}
   1488 	/* invalid */
   1489 	{
   1490 		char test[] = "";
   1491 		res_len = 0;
   1492 
   1493 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1494 						  &res_len);
   1495 		assert_null(res);
   1496 		assert_true(res_len == 0);
   1497 	}
   1498 	/* invalid */
   1499 	{
   1500 		char test[] = "PDw_Pz8-Pg==";
   1501 		res_len = 0;
   1502 
   1503 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1504 						  &res_len);
   1505 		assert_null(res);
   1506 		assert_true(res_len == 0);
   1507 	}
   1508 	/* invalid */
   1509 	{
   1510 		char test[] = "PDw_Pz8-Pg%3D%3D"; /* percent encoded "==" at the
   1511 						     end */
   1512 		res_len = 0;
   1513 
   1514 		res = isc__nm_base64url_to_base64(mctx, test, strlen(test),
   1515 						  &res_len);
   1516 		assert_null(res);
   1517 		assert_true(res_len == 0);
   1518 	}
   1519 	/* invalid */
   1520 	{
   1521 		res_len = 0;
   1522 
   1523 		res = isc__nm_base64url_to_base64(mctx, NULL, 31231, &res_len);
   1524 		assert_null(res);
   1525 		assert_true(res_len == 0);
   1526 	}
   1527 }
   1528 
   1529 ISC_RUN_TEST_IMPL(doh_base64_to_base64url) {
   1530 	char *res;
   1531 	size_t res_len = 0;
   1532 	/* valid */
   1533 	{
   1534 		char res_test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4";
   1535 		char test[] = "YW55IGNhcm5hbCBwbGVhc3VyZS4=";
   1536 
   1537 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1538 						  &res_len);
   1539 		assert_non_null(res);
   1540 		assert_true(res_len == strlen(res_test));
   1541 		assert_true(strcmp(res, res_test) == 0);
   1542 		isc_mem_free(mctx, res);
   1543 	}
   1544 	/* valid */
   1545 	{
   1546 		char res_test[] = "YW55IGNhcm5hbCBwbGVhcw";
   1547 		char test[] = "YW55IGNhcm5hbCBwbGVhcw==";
   1548 
   1549 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1550 						  &res_len);
   1551 		assert_non_null(res);
   1552 		assert_true(res_len == strlen(res_test));
   1553 		assert_true(strcmp(res, res_test) == 0);
   1554 		isc_mem_free(mctx, res);
   1555 	}
   1556 	/* valid */
   1557 	{
   1558 		char res_test[] = "YW55IGNhcm5hbCBwbGVhc3Vy";
   1559 		char test[] = "YW55IGNhcm5hbCBwbGVhc3Vy";
   1560 
   1561 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1562 						  &res_len);
   1563 		assert_non_null(res);
   1564 		assert_true(res_len == strlen(res_test));
   1565 		assert_true(strcmp(res, res_test) == 0);
   1566 		isc_mem_free(mctx, res);
   1567 	}
   1568 	/* valid */
   1569 	{
   1570 		char res_test[] = "YW55IGNhcm5hbCBwbGVhc3U";
   1571 		char test[] = "YW55IGNhcm5hbCBwbGVhc3U=";
   1572 
   1573 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1574 						  &res_len);
   1575 		assert_non_null(res);
   1576 		assert_true(res_len == strlen(res_test));
   1577 		assert_true(strcmp(res, res_test) == 0);
   1578 		isc_mem_free(mctx, res);
   1579 	}
   1580 	/* valid */
   1581 	{
   1582 		char res_test[] = "YW55IGNhcm5hbCBwbGVhcw";
   1583 		char test[] = "YW55IGNhcm5hbCBwbGVhcw==";
   1584 
   1585 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1586 						  &res_len);
   1587 		assert_non_null(res);
   1588 		assert_true(res_len == strlen(res_test));
   1589 		assert_true(strcmp(res, res_test) == 0);
   1590 		isc_mem_free(mctx, res);
   1591 	}
   1592 	/* valid */
   1593 	{
   1594 		char res_test[] = "PDw_Pz8-Pg";
   1595 		char test[] = "PDw/Pz8+Pg==";
   1596 
   1597 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1598 						  &res_len);
   1599 		assert_non_null(res);
   1600 		assert_true(res_len == strlen(res_test));
   1601 		assert_true(strcmp(res, res_test) == 0);
   1602 		isc_mem_free(mctx, res);
   1603 	}
   1604 	/* valid */
   1605 	{
   1606 		char res_test[] = "PDw_Pz8-Pg";
   1607 		char test[] = "PDw/Pz8+Pg==";
   1608 
   1609 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1610 						  NULL);
   1611 		assert_non_null(res);
   1612 		assert_true(strcmp(res, res_test) == 0);
   1613 		isc_mem_free(mctx, res);
   1614 	}
   1615 	/* invalid */
   1616 	{
   1617 		char test[] = "YW55IGNhcm5hbCBwbGVhcw";
   1618 		res_len = 0;
   1619 
   1620 		res = isc__nm_base64_to_base64url(mctx, test, 0, &res_len);
   1621 		assert_null(res);
   1622 		assert_true(res_len == 0);
   1623 	}
   1624 	/* invalid */
   1625 	{
   1626 		char test[] = "";
   1627 		res_len = 0;
   1628 
   1629 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1630 						  &res_len);
   1631 		assert_null(res);
   1632 		assert_true(res_len == 0);
   1633 	}
   1634 	/* invalid */
   1635 	{
   1636 		char test[] = "PDw_Pz8-Pg==";
   1637 		res_len = 0;
   1638 
   1639 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1640 						  &res_len);
   1641 		assert_null(res);
   1642 		assert_true(res_len == 0);
   1643 	}
   1644 	/* invalid */
   1645 	{
   1646 		char test[] = "PDw_Pz8-Pg%3D%3D"; /* percent encoded "==" at the
   1647 						     end */
   1648 		res_len = 0;
   1649 
   1650 		res = isc__nm_base64_to_base64url(mctx, test, strlen(test),
   1651 						  &res_len);
   1652 		assert_null(res);
   1653 		assert_true(res_len == 0);
   1654 	}
   1655 	/* invalid */
   1656 	{
   1657 		res_len = 0;
   1658 
   1659 		res = isc__nm_base64_to_base64url(mctx, NULL, 31231, &res_len);
   1660 		assert_null(res);
   1661 		assert_true(res_len == 0);
   1662 	}
   1663 }
   1664 
   1665 ISC_RUN_TEST_IMPL(doh_path_validation) {
   1666 	assert_true(isc_nm_http_path_isvalid("/"));
   1667 	assert_true(isc_nm_http_path_isvalid(ISC_NM_HTTP_DEFAULT_PATH));
   1668 	assert_false(isc_nm_http_path_isvalid("laaaa"));
   1669 	assert_false(isc_nm_http_path_isvalid(""));
   1670 	assert_false(isc_nm_http_path_isvalid("//"));
   1671 	assert_true(isc_nm_http_path_isvalid("/lala///"));
   1672 	assert_true(isc_nm_http_path_isvalid("/lalaaaaaa"));
   1673 	assert_true(isc_nm_http_path_isvalid("/lalaaa/la/la/la"));
   1674 	assert_true(isc_nm_http_path_isvalid("/la/a"));
   1675 	assert_true(isc_nm_http_path_isvalid("/la+la"));
   1676 	assert_true(isc_nm_http_path_isvalid("/la&la/la*la/l-a_/la!/la\'"));
   1677 	assert_true(isc_nm_http_path_isvalid("/la/(la)/la"));
   1678 	assert_true(isc_nm_http_path_isvalid("/la,la,la"));
   1679 	assert_true(isc_nm_http_path_isvalid("/la-'la'-la"));
   1680 	assert_true(isc_nm_http_path_isvalid("/la:la=la"));
   1681 	assert_true(isc_nm_http_path_isvalid("/l@l@l@"));
   1682 	assert_false(isc_nm_http_path_isvalid("/#lala"));
   1683 	assert_true(isc_nm_http_path_isvalid("/lala;la"));
   1684 	assert_false(
   1685 		isc_nm_http_path_isvalid("la&la/laalaala*lala/l-al_a/lal!/"));
   1686 	assert_true(isc_nm_http_path_isvalid("/Lal/lAla.jpg"));
   1687 
   1688 	/* had to replace ? with ! because it does not verify a query string */
   1689 	assert_true(isc_nm_http_path_isvalid("/watch!v=oavMtUWDBTM"));
   1690 	assert_false(isc_nm_http_path_isvalid("/watch?v=dQw4w9WgXcQ"));
   1691 	assert_true(isc_nm_http_path_isvalid("/datatracker.ietf.org/doc/html/"
   1692 					     "rfc2616"));
   1693 	assert_true(isc_nm_http_path_isvalid("/doc/html/rfc8484"));
   1694 	assert_true(isc_nm_http_path_isvalid("/123"));
   1695 }
   1696 
   1697 ISC_RUN_TEST_IMPL(doh_connect_makeuri) {
   1698 	struct in_addr localhostv4 = { .s_addr = ntohl(INADDR_LOOPBACK) };
   1699 	isc_sockaddr_t sa;
   1700 	char uri[256];
   1701 
   1702 	/* Firstly, test URI generation using isc_sockaddr_t */
   1703 	isc_sockaddr_fromin(&sa, &localhostv4, 0);
   1704 	uri[0] = '\0';
   1705 	isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri,
   1706 			    sizeof(uri));
   1707 	assert_true(strcmp("https://127.0.0.1:443/dns-query", uri) == 0);
   1708 
   1709 	uri[0] = '\0';
   1710 	isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri,
   1711 			    sizeof(uri));
   1712 	assert_true(strcmp("http://127.0.0.1:80/dns-query", uri) == 0);
   1713 
   1714 	/*
   1715 	 * The port value should be ignored, because we can get one from
   1716 	 * the isc_sockaddr_t object.
   1717 	 */
   1718 	uri[0] = '\0';
   1719 	isc_nm_http_makeuri(true, &sa, NULL, 44343, ISC_NM_HTTP_DEFAULT_PATH,
   1720 			    uri, sizeof(uri));
   1721 	assert_true(strcmp("https://127.0.0.1:443/dns-query", uri) == 0);
   1722 
   1723 	uri[0] = '\0';
   1724 	isc_nm_http_makeuri(false, &sa, NULL, 8080, ISC_NM_HTTP_DEFAULT_PATH,
   1725 			    uri, sizeof(uri));
   1726 	assert_true(strcmp("http://127.0.0.1:80/dns-query", uri) == 0);
   1727 
   1728 	/* IPv6 */
   1729 	isc_sockaddr_fromin6(&sa, &in6addr_loopback, 0);
   1730 	uri[0] = '\0';
   1731 	isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri,
   1732 			    sizeof(uri));
   1733 	assert_true(strcmp("https://[::1]:443/dns-query", uri) == 0);
   1734 
   1735 	uri[0] = '\0';
   1736 	isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri,
   1737 			    sizeof(uri));
   1738 	assert_true(strcmp("http://[::1]:80/dns-query", uri) == 0);
   1739 
   1740 	/*
   1741 	 * The port value should be ignored, because we can get one from
   1742 	 * the isc_sockaddr_t object.
   1743 	 */
   1744 	uri[0] = '\0';
   1745 	isc_nm_http_makeuri(true, &sa, NULL, 44343, ISC_NM_HTTP_DEFAULT_PATH,
   1746 			    uri, sizeof(uri));
   1747 	assert_true(strcmp("https://[::1]:443/dns-query", uri) == 0);
   1748 
   1749 	uri[0] = '\0';
   1750 	isc_nm_http_makeuri(false, &sa, NULL, 8080, ISC_NM_HTTP_DEFAULT_PATH,
   1751 			    uri, sizeof(uri));
   1752 	assert_true(strcmp("http://[::1]:80/dns-query", uri) == 0);
   1753 
   1754 	/* Try to set the port numbers. */
   1755 	isc_sockaddr_setport(&sa, 44343);
   1756 	uri[0] = '\0';
   1757 	isc_nm_http_makeuri(true, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri,
   1758 			    sizeof(uri));
   1759 	assert_true(strcmp("https://[::1]:44343/dns-query", uri) == 0);
   1760 
   1761 	isc_sockaddr_setport(&sa, 8080);
   1762 	uri[0] = '\0';
   1763 	isc_nm_http_makeuri(false, &sa, NULL, 0, ISC_NM_HTTP_DEFAULT_PATH, uri,
   1764 			    sizeof(uri));
   1765 	assert_true(strcmp("http://[::1]:8080/dns-query", uri) == 0);
   1766 
   1767 	/*
   1768 	 * Try to make a URI using a hostname and a port number. The
   1769 	 * isc_sockaddr_t object will be ignored.
   1770 	 */
   1771 	isc_sockaddr_any(&sa);
   1772 	uri[0] = '\0';
   1773 	isc_nm_http_makeuri(true, &sa, "example.com", 0,
   1774 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1775 	assert_true(strcmp("https://example.com:443/dns-query", uri) == 0);
   1776 
   1777 	uri[0] = '\0';
   1778 	isc_nm_http_makeuri(false, &sa, "example.com", 0,
   1779 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1780 	assert_true(strcmp("http://example.com:80/dns-query", uri) == 0);
   1781 
   1782 	/* Try to set the port numbers. */
   1783 	isc_sockaddr_setport(&sa, 443);
   1784 	uri[0] = '\0';
   1785 	isc_nm_http_makeuri(true, &sa, "example.com", 44343,
   1786 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1787 	assert_true(strcmp("https://example.com:44343/dns-query", uri) == 0);
   1788 
   1789 	isc_sockaddr_setport(&sa, 80);
   1790 	uri[0] = '\0';
   1791 	isc_nm_http_makeuri(false, &sa, "example.com", 8080,
   1792 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1793 	assert_true(strcmp("http://example.com:8080/dns-query", uri) == 0);
   1794 
   1795 	/* IPv4 as the hostname - nothing fancy here */
   1796 	uri[0] = '\0';
   1797 	isc_nm_http_makeuri(false, NULL, "127.0.0.1", 8080,
   1798 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1799 	assert_true(strcmp("http://127.0.0.1:8080/dns-query", uri) == 0);
   1800 
   1801 	uri[0] = '\0';
   1802 	isc_nm_http_makeuri(true, NULL, "127.0.0.1", 44343,
   1803 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1804 	assert_true(strcmp("https://127.0.0.1:44343/dns-query", uri) == 0);
   1805 
   1806 	/*
   1807 	 * A peculiar edge case: IPv6 given as the hostname (notice
   1808 	 * the brackets)
   1809 	 */
   1810 	uri[0] = '\0';
   1811 	isc_nm_http_makeuri(false, NULL, "::1", 8080, ISC_NM_HTTP_DEFAULT_PATH,
   1812 			    uri, sizeof(uri));
   1813 	assert_true(strcmp("http://[::1]:8080/dns-query", uri) == 0);
   1814 
   1815 	uri[0] = '\0';
   1816 	isc_nm_http_makeuri(true, NULL, "[::1]", 44343,
   1817 			    ISC_NM_HTTP_DEFAULT_PATH, uri, sizeof(uri));
   1818 	assert_true(strcmp("https://[::1]:44343/dns-query", uri) == 0);
   1819 }
   1820 
   1821 /* PROXY */
   1822 ISC_LOOP_TEST_IMPL(proxy_doh_noop_POST) {
   1823 	atomic_store(&POST, true);
   1824 	atomic_store(&use_PROXY, true);
   1825 	doh_noop(arg);
   1826 }
   1827 
   1828 ISC_LOOP_TEST_IMPL(proxy_doh_noop_GET) {
   1829 	atomic_store(&use_PROXY, true);
   1830 	doh_noop(arg);
   1831 }
   1832 
   1833 ISC_LOOP_TEST_IMPL(proxy_doh_noresponse_POST) {
   1834 	atomic_store(&POST, true);
   1835 	atomic_store(&use_PROXY, true);
   1836 	doh_noresponse(arg);
   1837 }
   1838 
   1839 ISC_LOOP_TEST_IMPL(proxy_doh_noresponse_GET) {
   1840 	atomic_store(&use_PROXY, true);
   1841 	doh_noresponse(arg);
   1842 }
   1843 
   1844 ISC_LOOP_TEST_IMPL(proxy_doh_timeout_recovery_POST) {
   1845 	atomic_store(&POST, true);
   1846 	atomic_store(&use_PROXY, true);
   1847 	doh_timeout_recovery(arg);
   1848 }
   1849 
   1850 ISC_LOOP_TEST_IMPL(proxy_doh_timeout_recovery_GET) {
   1851 	atomic_store(&use_PROXY, true);
   1852 	doh_timeout_recovery(arg);
   1853 }
   1854 
   1855 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_POST) {
   1856 	atomic_store(&POST, true);
   1857 	atomic_store(&use_PROXY, true);
   1858 	doh_recv_one(arg);
   1859 }
   1860 
   1861 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_GET) {
   1862 	atomic_store(&use_PROXY, true);
   1863 	doh_recv_one(arg);
   1864 }
   1865 
   1866 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_POST_TLS) {
   1867 	atomic_store(&POST, true);
   1868 	atomic_store(&use_TLS, true);
   1869 	atomic_store(&use_PROXY, true);
   1870 	doh_recv_one(arg);
   1871 }
   1872 
   1873 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_GET_TLS) {
   1874 	atomic_store(&use_TLS, true);
   1875 	atomic_store(&use_PROXY, true);
   1876 	doh_recv_one(arg);
   1877 }
   1878 
   1879 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_POST_quota) {
   1880 	atomic_store(&POST, true);
   1881 	atomic_store(&use_PROXY, true);
   1882 	atomic_store(&check_listener_quota, true);
   1883 	doh_recv_one(arg);
   1884 }
   1885 
   1886 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_GET_quota) {
   1887 	atomic_store(&use_PROXY, true);
   1888 	atomic_store(&check_listener_quota, true);
   1889 	doh_recv_one(arg);
   1890 }
   1891 
   1892 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_GET_TLS_quota) {
   1893 	atomic_store(&use_TLS, true);
   1894 	atomic_store(&use_PROXY, true);
   1895 	atomic_store(&check_listener_quota, true);
   1896 	doh_recv_one(arg);
   1897 }
   1898 
   1899 ISC_LOOP_TEST_IMPL(proxy_doh_recv_one_POST_TLS_quota) {
   1900 	atomic_store(&POST, true);
   1901 	atomic_store(&use_TLS, true);
   1902 	atomic_store(&use_PROXY, true);
   1903 	atomic_store(&check_listener_quota, true);
   1904 	doh_recv_one(arg);
   1905 }
   1906 
   1907 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_POST) {
   1908 	atomic_store(&POST, true);
   1909 	atomic_store(&use_PROXY, true);
   1910 	doh_recv_two(arg);
   1911 }
   1912 
   1913 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_GET) {
   1914 	;
   1915 	atomic_store(&use_PROXY, true);
   1916 	doh_recv_two(arg);
   1917 }
   1918 
   1919 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_POST_TLS) {
   1920 	atomic_store(&POST, true);
   1921 	atomic_store(&use_TLS, true);
   1922 	atomic_store(&use_PROXY, true);
   1923 	doh_recv_two(arg);
   1924 }
   1925 
   1926 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_GET_TLS) {
   1927 	atomic_store(&use_TLS, true);
   1928 	atomic_store(&use_PROXY, true);
   1929 	doh_recv_two(arg);
   1930 }
   1931 
   1932 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_POST_quota) {
   1933 	atomic_store(&POST, true);
   1934 	atomic_store(&use_PROXY, true);
   1935 	atomic_store(&check_listener_quota, true);
   1936 	doh_recv_two(arg);
   1937 }
   1938 
   1939 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_GET_quota) {
   1940 	atomic_store(&use_PROXY, true);
   1941 	atomic_store(&check_listener_quota, true);
   1942 	doh_recv_two(arg);
   1943 }
   1944 
   1945 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_POST_TLS_quota) {
   1946 	atomic_store(&POST, true);
   1947 	atomic_store(&use_TLS, true);
   1948 	atomic_store(&use_PROXY, true);
   1949 	atomic_store(&check_listener_quota, true);
   1950 	doh_recv_two(arg);
   1951 }
   1952 
   1953 ISC_LOOP_TEST_IMPL(proxy_doh_recv_two_GET_TLS_quota) {
   1954 	atomic_store(&use_TLS, true);
   1955 	atomic_store(&use_PROXY, true);
   1956 	atomic_store(&check_listener_quota, true);
   1957 	doh_recv_two(arg);
   1958 }
   1959 
   1960 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_POST) {
   1961 	atomic_store(&POST, true);
   1962 	atomic_store(&use_PROXY, true);
   1963 	doh_recv_send(arg);
   1964 }
   1965 
   1966 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_GET) {
   1967 	atomic_store(&use_PROXY, true);
   1968 	doh_recv_send(arg);
   1969 }
   1970 
   1971 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_POST_TLS) {
   1972 	atomic_store(&POST, true);
   1973 	atomic_store(&use_TLS, true);
   1974 	atomic_store(&use_PROXY, true);
   1975 	doh_recv_send(arg);
   1976 }
   1977 
   1978 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_GET_TLS) {
   1979 	atomic_store(&use_TLS, true);
   1980 	atomic_store(&use_PROXY, true);
   1981 	doh_recv_send(arg);
   1982 }
   1983 
   1984 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_POST_quota) {
   1985 	atomic_store(&POST, true);
   1986 	atomic_store(&use_PROXY, true);
   1987 	atomic_store(&check_listener_quota, true);
   1988 	doh_recv_send(arg);
   1989 }
   1990 
   1991 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_GET_quota) {
   1992 	atomic_store(&use_PROXY, true);
   1993 	atomic_store(&check_listener_quota, true);
   1994 	doh_recv_send(arg);
   1995 }
   1996 
   1997 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_POST_TLS_quota) {
   1998 	atomic_store(&POST, true);
   1999 	atomic_store(&use_TLS, true);
   2000 	atomic_store(&use_PROXY, true);
   2001 	atomic_store(&check_listener_quota, true);
   2002 	doh_recv_send(arg);
   2003 }
   2004 
   2005 ISC_LOOP_TEST_IMPL(proxy_doh_recv_send_GET_TLS_quota) {
   2006 	atomic_store(&use_TLS, true);
   2007 	atomic_store(&use_PROXY, true);
   2008 	atomic_store(&check_listener_quota, true);
   2009 	doh_recv_send(arg);
   2010 }
   2011 
   2012 /* PROXY over TLS */
   2013 
   2014 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_one_POST_TLS) {
   2015 	atomic_store(&POST, true);
   2016 	atomic_store(&use_TLS, true);
   2017 	atomic_store(&use_PROXY, true);
   2018 	atomic_store(&use_PROXY_over_TLS, true);
   2019 	doh_recv_one(arg);
   2020 }
   2021 
   2022 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_one_GET_TLS) {
   2023 	atomic_store(&use_TLS, true);
   2024 	atomic_store(&use_PROXY, true);
   2025 	atomic_store(&use_PROXY_over_TLS, true);
   2026 	doh_recv_one(arg);
   2027 }
   2028 
   2029 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_one_GET_TLS_quota) {
   2030 	atomic_store(&use_TLS, true);
   2031 	atomic_store(&use_PROXY, true);
   2032 	atomic_store(&use_PROXY_over_TLS, true);
   2033 	atomic_store(&check_listener_quota, true);
   2034 	doh_recv_one(arg);
   2035 }
   2036 
   2037 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_one_POST_TLS_quota) {
   2038 	atomic_store(&POST, true);
   2039 	atomic_store(&use_TLS, true);
   2040 	atomic_store(&use_PROXY, true);
   2041 	atomic_store(&use_PROXY_over_TLS, true);
   2042 	atomic_store(&check_listener_quota, true);
   2043 	doh_recv_one(arg);
   2044 }
   2045 
   2046 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_two_POST_TLS) {
   2047 	atomic_store(&POST, true);
   2048 	atomic_store(&use_TLS, true);
   2049 	atomic_store(&use_PROXY, true);
   2050 	atomic_store(&use_PROXY_over_TLS, true);
   2051 	doh_recv_two(arg);
   2052 }
   2053 
   2054 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_two_GET_TLS) {
   2055 	atomic_store(&use_TLS, true);
   2056 	atomic_store(&use_PROXY, true);
   2057 	atomic_store(&use_PROXY_over_TLS, true);
   2058 	doh_recv_two(arg);
   2059 }
   2060 
   2061 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_two_POST_TLS_quota) {
   2062 	atomic_store(&POST, true);
   2063 	atomic_store(&use_TLS, true);
   2064 	atomic_store(&use_PROXY, true);
   2065 	atomic_store(&use_PROXY_over_TLS, true);
   2066 	atomic_store(&check_listener_quota, true);
   2067 	doh_recv_two(arg);
   2068 }
   2069 
   2070 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_two_GET_TLS_quota) {
   2071 	atomic_store(&use_TLS, true);
   2072 	atomic_store(&use_PROXY, true);
   2073 	atomic_store(&use_PROXY_over_TLS, true);
   2074 	atomic_store(&check_listener_quota, true);
   2075 	doh_recv_two(arg);
   2076 }
   2077 
   2078 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_send_POST_TLS) {
   2079 	atomic_store(&POST, true);
   2080 	atomic_store(&use_TLS, true);
   2081 	atomic_store(&use_PROXY, true);
   2082 	atomic_store(&use_PROXY_over_TLS, true);
   2083 	doh_recv_send(arg);
   2084 }
   2085 
   2086 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_send_GET_TLS) {
   2087 	atomic_store(&use_TLS, true);
   2088 	atomic_store(&use_PROXY, true);
   2089 	atomic_store(&use_PROXY_over_TLS, true);
   2090 	doh_recv_send(arg);
   2091 }
   2092 
   2093 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_send_POST_TLS_quota) {
   2094 	atomic_store(&POST, true);
   2095 	atomic_store(&use_TLS, true);
   2096 	atomic_store(&use_PROXY, true);
   2097 	atomic_store(&use_PROXY_over_TLS, true);
   2098 	atomic_store(&check_listener_quota, true);
   2099 	doh_recv_send(arg);
   2100 }
   2101 
   2102 ISC_LOOP_TEST_IMPL(proxytls_doh_recv_send_GET_TLS_quota) {
   2103 	atomic_store(&use_TLS, true);
   2104 	atomic_store(&use_PROXY, true);
   2105 	atomic_store(&use_PROXY_over_TLS, true);
   2106 	atomic_store(&check_listener_quota, true);
   2107 	doh_recv_send(arg);
   2108 }
   2109 
   2110 ISC_TEST_LIST_START
   2111 
   2112 ISC_TEST_ENTRY_CUSTOM(mock_doh_uv_tcp_bind, setup_test, teardown_test)
   2113 ISC_TEST_ENTRY(doh_parse_GET_query_string)
   2114 ISC_TEST_ENTRY(doh_base64url_to_base64)
   2115 ISC_TEST_ENTRY(doh_base64_to_base64url)
   2116 ISC_TEST_ENTRY(doh_path_validation)
   2117 ISC_TEST_ENTRY(doh_connect_makeuri)
   2118 ISC_TEST_ENTRY_CUSTOM(doh_noop_POST, setup_test, teardown_test)
   2119 ISC_TEST_ENTRY_CUSTOM(doh_noop_GET, setup_test, teardown_test)
   2120 ISC_TEST_ENTRY_CUSTOM(doh_noresponse_POST, setup_test, teardown_test)
   2121 ISC_TEST_ENTRY_CUSTOM(doh_noresponse_GET, setup_test, teardown_test)
   2122 ISC_TEST_ENTRY_CUSTOM(doh_timeout_recovery_POST, setup_test,
   2123 		      doh_timeout_recovery_teardown)
   2124 ISC_TEST_ENTRY_CUSTOM(doh_timeout_recovery_GET, setup_test,
   2125 		      doh_timeout_recovery_teardown)
   2126 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST, setup_test, doh_recv_one_teardown)
   2127 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET, setup_test, doh_recv_one_teardown)
   2128 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_TLS, setup_test, doh_recv_one_teardown)
   2129 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_TLS, setup_test, doh_recv_one_teardown)
   2130 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_quota, setup_test,
   2131 		      doh_recv_one_teardown)
   2132 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_quota, setup_test, doh_recv_one_teardown)
   2133 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_POST_TLS_quota, setup_test,
   2134 		      doh_recv_one_teardown)
   2135 ISC_TEST_ENTRY_CUSTOM(doh_recv_one_GET_TLS_quota, setup_test,
   2136 		      doh_recv_one_teardown)
   2137 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST, setup_test, doh_recv_two_teardown)
   2138 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET, setup_test, doh_recv_two_teardown)
   2139 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_TLS, setup_test, doh_recv_two_teardown)
   2140 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_TLS, setup_test, doh_recv_two_teardown)
   2141 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_quota, setup_test,
   2142 		      doh_recv_two_teardown)
   2143 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_quota, setup_test, doh_recv_two_teardown)
   2144 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_POST_TLS_quota, setup_test,
   2145 		      doh_recv_two_teardown)
   2146 ISC_TEST_ENTRY_CUSTOM(doh_recv_two_GET_TLS_quota, setup_test,
   2147 		      doh_recv_two_teardown)
   2148 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET, setup_test, doh_recv_send_teardown)
   2149 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST, setup_test, doh_recv_send_teardown)
   2150 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_TLS, setup_test, doh_recv_send_teardown)
   2151 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_TLS, setup_test,
   2152 		      doh_recv_send_teardown)
   2153 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_quota, setup_test,
   2154 		      doh_recv_send_teardown)
   2155 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_quota, setup_test,
   2156 		      doh_recv_send_teardown)
   2157 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_GET_TLS_quota, setup_test,
   2158 		      doh_recv_send_teardown)
   2159 ISC_TEST_ENTRY_CUSTOM(doh_recv_send_POST_TLS_quota, setup_test,
   2160 		      doh_recv_send_teardown)
   2161 ISC_TEST_ENTRY_CUSTOM(doh_bad_connect_uri, setup_test,
   2162 		      doh_bad_connect_uri_teardown)
   2163 /* PROXY */
   2164 ISC_TEST_ENTRY_CUSTOM(proxy_doh_noop_POST, setup_test, teardown_test)
   2165 ISC_TEST_ENTRY_CUSTOM(proxy_doh_noop_GET, setup_test, teardown_test)
   2166 ISC_TEST_ENTRY_CUSTOM(proxy_doh_noresponse_POST, setup_test, teardown_test)
   2167 ISC_TEST_ENTRY_CUSTOM(proxy_doh_noresponse_GET, setup_test, teardown_test)
   2168 ISC_TEST_ENTRY_CUSTOM(proxy_doh_timeout_recovery_POST, setup_test,
   2169 		      doh_timeout_recovery_teardown)
   2170 ISC_TEST_ENTRY_CUSTOM(proxy_doh_timeout_recovery_GET, setup_test,
   2171 		      doh_timeout_recovery_teardown)
   2172 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_POST, setup_test,
   2173 		      doh_recv_one_teardown)
   2174 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_GET, setup_test, doh_recv_one_teardown)
   2175 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_POST_TLS, setup_test,
   2176 		      doh_recv_one_teardown)
   2177 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_GET_TLS, setup_test,
   2178 		      doh_recv_one_teardown)
   2179 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_POST_quota, setup_test,
   2180 		      doh_recv_one_teardown)
   2181 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_GET_quota, setup_test,
   2182 		      doh_recv_one_teardown)
   2183 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_POST_TLS_quota, setup_test,
   2184 		      doh_recv_one_teardown)
   2185 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_one_GET_TLS_quota, setup_test,
   2186 		      doh_recv_one_teardown)
   2187 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_POST, setup_test,
   2188 		      doh_recv_two_teardown)
   2189 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_GET, setup_test, doh_recv_two_teardown)
   2190 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_POST_TLS, setup_test,
   2191 		      doh_recv_two_teardown)
   2192 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_GET_TLS, setup_test,
   2193 		      doh_recv_two_teardown)
   2194 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_POST_quota, setup_test,
   2195 		      doh_recv_two_teardown)
   2196 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_GET_quota, setup_test,
   2197 		      doh_recv_two_teardown)
   2198 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_POST_TLS_quota, setup_test,
   2199 		      doh_recv_two_teardown)
   2200 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_two_GET_TLS_quota, setup_test,
   2201 		      doh_recv_two_teardown)
   2202 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_GET, setup_test,
   2203 		      doh_recv_send_teardown)
   2204 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_POST, setup_test,
   2205 		      doh_recv_send_teardown)
   2206 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_GET_TLS, setup_test,
   2207 		      doh_recv_send_teardown)
   2208 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_POST_TLS, setup_test,
   2209 		      doh_recv_send_teardown)
   2210 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_GET_quota, setup_test,
   2211 		      doh_recv_send_teardown)
   2212 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_POST_quota, setup_test,
   2213 		      doh_recv_send_teardown)
   2214 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_GET_TLS_quota, setup_test,
   2215 		      doh_recv_send_teardown)
   2216 ISC_TEST_ENTRY_CUSTOM(proxy_doh_recv_send_POST_TLS_quota, setup_test,
   2217 		      doh_recv_send_teardown)
   2218 /* PROXY over TLS */
   2219 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_one_POST_TLS, setup_test,
   2220 		      doh_recv_one_teardown)
   2221 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_one_GET_TLS, setup_test,
   2222 		      doh_recv_one_teardown)
   2223 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_one_POST_TLS_quota, setup_test,
   2224 		      doh_recv_one_teardown)
   2225 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_one_GET_TLS_quota, setup_test,
   2226 		      doh_recv_one_teardown)
   2227 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_two_POST_TLS, setup_test,
   2228 		      doh_recv_two_teardown)
   2229 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_two_GET_TLS, setup_test,
   2230 		      doh_recv_two_teardown)
   2231 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_two_POST_TLS_quota, setup_test,
   2232 		      doh_recv_two_teardown)
   2233 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_two_GET_TLS_quota, setup_test,
   2234 		      doh_recv_two_teardown)
   2235 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_send_GET_TLS, setup_test,
   2236 		      doh_recv_send_teardown)
   2237 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_send_POST_TLS, setup_test,
   2238 		      doh_recv_send_teardown)
   2239 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_send_GET_TLS_quota, setup_test,
   2240 		      doh_recv_send_teardown)
   2241 ISC_TEST_ENTRY_CUSTOM(proxytls_doh_recv_send_POST_TLS_quota, setup_test,
   2242 		      doh_recv_send_teardown)
   2243 ISC_TEST_LIST_END
   2244 
   2245 ISC_TEST_MAIN
   2246