xref: /netbsd-src/external/mpl/bind/dist/tests/isc/doh_test.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
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