xref: /openbsd-src/usr.sbin/unbound/testcode/unitmain.c (revision a43524d9cc222a049058246319ec6a29f2d9ca78)
1712b2f30Ssthen /*
2712b2f30Ssthen  * testcode/unitmain.c - unit test main program for unbound.
3712b2f30Ssthen  *
4712b2f30Ssthen  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5712b2f30Ssthen  *
6712b2f30Ssthen  * This software is open source.
7712b2f30Ssthen  *
8712b2f30Ssthen  * Redistribution and use in source and binary forms, with or without
9712b2f30Ssthen  * modification, are permitted provided that the following conditions
10712b2f30Ssthen  * are met:
11712b2f30Ssthen  *
12712b2f30Ssthen  * Redistributions of source code must retain the above copyright notice,
13712b2f30Ssthen  * this list of conditions and the following disclaimer.
14712b2f30Ssthen  *
15712b2f30Ssthen  * Redistributions in binary form must reproduce the above copyright notice,
16712b2f30Ssthen  * this list of conditions and the following disclaimer in the documentation
17712b2f30Ssthen  * and/or other materials provided with the distribution.
18712b2f30Ssthen  *
19712b2f30Ssthen  * Neither the name of the NLNET LABS nor the names of its contributors may
20712b2f30Ssthen  * be used to endorse or promote products derived from this software without
21712b2f30Ssthen  * specific prior written permission.
22712b2f30Ssthen  *
23712b2f30Ssthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24712b2f30Ssthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25712b2f30Ssthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26712b2f30Ssthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27712b2f30Ssthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28712b2f30Ssthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29712b2f30Ssthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30712b2f30Ssthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31712b2f30Ssthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32712b2f30Ssthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33712b2f30Ssthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34712b2f30Ssthen  *
35712b2f30Ssthen  */
36712b2f30Ssthen /**
37712b2f30Ssthen  * \file
38712b2f30Ssthen  * Unit test main program. Calls all the other unit tests.
39712b2f30Ssthen  * Exits with code 1 on a failure. 0 if all unit tests are successful.
40712b2f30Ssthen  */
41712b2f30Ssthen 
42712b2f30Ssthen #include "config.h"
43712b2f30Ssthen #ifdef HAVE_OPENSSL_ERR_H
44712b2f30Ssthen #include <openssl/err.h>
45712b2f30Ssthen #endif
46712b2f30Ssthen 
47712b2f30Ssthen #ifdef HAVE_OPENSSL_RAND_H
48712b2f30Ssthen #include <openssl/rand.h>
49712b2f30Ssthen #endif
50712b2f30Ssthen 
51712b2f30Ssthen #ifdef HAVE_OPENSSL_CONF_H
52712b2f30Ssthen #include <openssl/conf.h>
53712b2f30Ssthen #endif
54712b2f30Ssthen 
55712b2f30Ssthen #ifdef HAVE_OPENSSL_ENGINE_H
56712b2f30Ssthen #include <openssl/engine.h>
57712b2f30Ssthen #endif
58712b2f30Ssthen 
59712b2f30Ssthen #ifdef HAVE_NSS
60712b2f30Ssthen /* nss3 */
61712b2f30Ssthen #include "nss.h"
62712b2f30Ssthen #endif
63712b2f30Ssthen 
64712b2f30Ssthen #include "sldns/rrdef.h"
65712b2f30Ssthen #include "sldns/keyraw.h"
66712b2f30Ssthen #include "util/log.h"
67712b2f30Ssthen #include "testcode/unitmain.h"
68712b2f30Ssthen 
69712b2f30Ssthen /** number of tests done */
70712b2f30Ssthen int testcount = 0;
71712b2f30Ssthen 
72712b2f30Ssthen #include "util/alloc.h"
73712b2f30Ssthen /** test alloc code */
74712b2f30Ssthen static void
75712b2f30Ssthen alloc_test(void) {
76712b2f30Ssthen 	alloc_special_type *t1, *t2;
77712b2f30Ssthen 	struct alloc_cache major, minor1, minor2;
78712b2f30Ssthen 	int i;
79712b2f30Ssthen 
80712b2f30Ssthen 	unit_show_feature("alloc_special_obtain");
81712b2f30Ssthen 	alloc_init(&major, NULL, 0);
82712b2f30Ssthen 	alloc_init(&minor1, &major, 0);
83712b2f30Ssthen 	alloc_init(&minor2, &major, 1);
84712b2f30Ssthen 
85712b2f30Ssthen 	t1 = alloc_special_obtain(&minor1);
86712b2f30Ssthen 	alloc_clear(&minor1);
87712b2f30Ssthen 
88712b2f30Ssthen 	alloc_special_release(&minor2, t1);
89712b2f30Ssthen 	t2 = alloc_special_obtain(&minor2);
90712b2f30Ssthen 	unit_assert( t1 == t2 ); /* reused */
91712b2f30Ssthen 	alloc_special_release(&minor2, t1);
92712b2f30Ssthen 
93712b2f30Ssthen 	for(i=0; i<100; i++) {
94712b2f30Ssthen 		t1 = alloc_special_obtain(&minor1);
95712b2f30Ssthen 		alloc_special_release(&minor2, t1);
96712b2f30Ssthen 	}
97712b2f30Ssthen 	if(0) {
98712b2f30Ssthen 		alloc_stats(&minor1);
99712b2f30Ssthen 		alloc_stats(&minor2);
100712b2f30Ssthen 		alloc_stats(&major);
101712b2f30Ssthen 	}
102712b2f30Ssthen 	/* reuse happened */
103712b2f30Ssthen 	unit_assert(minor1.num_quar + minor2.num_quar + major.num_quar == 11);
104712b2f30Ssthen 
105712b2f30Ssthen 	alloc_clear(&minor1);
106712b2f30Ssthen 	alloc_clear(&minor2);
107712b2f30Ssthen 	unit_assert(major.num_quar == 11);
108712b2f30Ssthen 	alloc_clear(&major);
109712b2f30Ssthen }
110712b2f30Ssthen 
111712b2f30Ssthen #include "util/net_help.h"
112712b2f30Ssthen /** test net code */
113712b2f30Ssthen static void
114712b2f30Ssthen net_test(void)
115712b2f30Ssthen {
116712b2f30Ssthen 	const char* t4[] = {"\000\000\000\000",
117712b2f30Ssthen 		"\200\000\000\000",
118712b2f30Ssthen 		"\300\000\000\000",
119712b2f30Ssthen 		"\340\000\000\000",
120712b2f30Ssthen 		"\360\000\000\000",
121712b2f30Ssthen 		"\370\000\000\000",
122712b2f30Ssthen 		"\374\000\000\000",
123712b2f30Ssthen 		"\376\000\000\000",
124712b2f30Ssthen 		"\377\000\000\000",
125712b2f30Ssthen 		"\377\200\000\000",
126712b2f30Ssthen 		"\377\300\000\000",
127712b2f30Ssthen 		"\377\340\000\000",
128712b2f30Ssthen 		"\377\360\000\000",
129712b2f30Ssthen 		"\377\370\000\000",
130712b2f30Ssthen 		"\377\374\000\000",
131712b2f30Ssthen 		"\377\376\000\000",
132712b2f30Ssthen 		"\377\377\000\000",
133712b2f30Ssthen 		"\377\377\200\000",
134712b2f30Ssthen 		"\377\377\300\000",
135712b2f30Ssthen 		"\377\377\340\000",
136712b2f30Ssthen 		"\377\377\360\000",
137712b2f30Ssthen 		"\377\377\370\000",
138712b2f30Ssthen 		"\377\377\374\000",
139712b2f30Ssthen 		"\377\377\376\000",
140712b2f30Ssthen 		"\377\377\377\000",
141712b2f30Ssthen 		"\377\377\377\200",
142712b2f30Ssthen 		"\377\377\377\300",
143712b2f30Ssthen 		"\377\377\377\340",
144712b2f30Ssthen 		"\377\377\377\360",
145712b2f30Ssthen 		"\377\377\377\370",
146712b2f30Ssthen 		"\377\377\377\374",
147712b2f30Ssthen 		"\377\377\377\376",
148712b2f30Ssthen 		"\377\377\377\377",
149712b2f30Ssthen 		"\377\377\377\377",
150712b2f30Ssthen 		"\377\377\377\377",
151712b2f30Ssthen 	};
152712b2f30Ssthen 	unit_show_func("util/net_help.c", "str_is_ip6");
153712b2f30Ssthen 	unit_assert( str_is_ip6("::") );
154712b2f30Ssthen 	unit_assert( str_is_ip6("::1") );
155712b2f30Ssthen 	unit_assert( str_is_ip6("2001:7b8:206:1:240:f4ff:fe37:8810") );
156712b2f30Ssthen 	unit_assert( str_is_ip6("fe80::240:f4ff:fe37:8810") );
157712b2f30Ssthen 	unit_assert( !str_is_ip6("0.0.0.0") );
158712b2f30Ssthen 	unit_assert( !str_is_ip6("213.154.224.12") );
159712b2f30Ssthen 	unit_assert( !str_is_ip6("213.154.224.255") );
160712b2f30Ssthen 	unit_assert( !str_is_ip6("255.255.255.0") );
161712b2f30Ssthen 	unit_show_func("util/net_help.c", "is_pow2");
162712b2f30Ssthen 	unit_assert( is_pow2(0) );
163712b2f30Ssthen 	unit_assert( is_pow2(1) );
164712b2f30Ssthen 	unit_assert( is_pow2(2) );
165712b2f30Ssthen 	unit_assert( is_pow2(4) );
166712b2f30Ssthen 	unit_assert( is_pow2(8) );
167712b2f30Ssthen 	unit_assert( is_pow2(16) );
168712b2f30Ssthen 	unit_assert( is_pow2(1024) );
169712b2f30Ssthen 	unit_assert( is_pow2(1024*1024) );
170712b2f30Ssthen 	unit_assert( is_pow2(1024*1024*1024) );
171712b2f30Ssthen 	unit_assert( !is_pow2(3) );
172712b2f30Ssthen 	unit_assert( !is_pow2(5) );
173712b2f30Ssthen 	unit_assert( !is_pow2(6) );
174712b2f30Ssthen 	unit_assert( !is_pow2(7) );
175712b2f30Ssthen 	unit_assert( !is_pow2(9) );
176712b2f30Ssthen 	unit_assert( !is_pow2(10) );
177712b2f30Ssthen 	unit_assert( !is_pow2(11) );
178712b2f30Ssthen 	unit_assert( !is_pow2(17) );
179712b2f30Ssthen 	unit_assert( !is_pow2(23) );
180712b2f30Ssthen 	unit_assert( !is_pow2(257) );
181712b2f30Ssthen 	unit_assert( !is_pow2(259) );
182712b2f30Ssthen 
183712b2f30Ssthen 	/* test addr_mask */
184712b2f30Ssthen 	unit_show_func("util/net_help.c", "addr_mask");
185712b2f30Ssthen 	if(1) {
186712b2f30Ssthen 		struct sockaddr_in a4;
187712b2f30Ssthen 		struct sockaddr_in6 a6;
188712b2f30Ssthen 		socklen_t l4 = (socklen_t)sizeof(a4);
189712b2f30Ssthen 		socklen_t l6 = (socklen_t)sizeof(a6);
190712b2f30Ssthen 		int i;
191712b2f30Ssthen 		a4.sin_family = AF_INET;
192712b2f30Ssthen 		a6.sin6_family = AF_INET6;
193712b2f30Ssthen 		for(i=0; i<35; i++) {
194712b2f30Ssthen 			/* address 255.255.255.255 */
195712b2f30Ssthen 			memcpy(&a4.sin_addr, "\377\377\377\377", 4);
196712b2f30Ssthen 			addr_mask((struct sockaddr_storage*)&a4, l4, i);
197712b2f30Ssthen 			unit_assert(memcmp(&a4.sin_addr, t4[i], 4) == 0);
198712b2f30Ssthen 		}
199712b2f30Ssthen 		memcpy(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16);
200712b2f30Ssthen 		addr_mask((struct sockaddr_storage*)&a6, l6, 128);
201712b2f30Ssthen 		unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16) == 0);
202712b2f30Ssthen 		addr_mask((struct sockaddr_storage*)&a6, l6, 122);
203712b2f30Ssthen 		unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300", 16) == 0);
204712b2f30Ssthen 		addr_mask((struct sockaddr_storage*)&a6, l6, 120);
205712b2f30Ssthen 		unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\000", 16) == 0);
206712b2f30Ssthen 		addr_mask((struct sockaddr_storage*)&a6, l6, 64);
207712b2f30Ssthen 		unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000\000", 16) == 0);
208712b2f30Ssthen 		addr_mask((struct sockaddr_storage*)&a6, l6, 0);
209712b2f30Ssthen 		unit_assert(memcmp(&a6.sin6_addr, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16) == 0);
210712b2f30Ssthen 	}
211712b2f30Ssthen 
212712b2f30Ssthen 	/* test addr_in_common */
213712b2f30Ssthen 	unit_show_func("util/net_help.c", "addr_in_common");
214712b2f30Ssthen 	if(1) {
215712b2f30Ssthen 		struct sockaddr_in a4, b4;
216712b2f30Ssthen 		struct sockaddr_in6 a6, b6;
217712b2f30Ssthen 		socklen_t l4 = (socklen_t)sizeof(a4);
218712b2f30Ssthen 		socklen_t l6 = (socklen_t)sizeof(a6);
219712b2f30Ssthen 		int i;
220712b2f30Ssthen 		a4.sin_family = AF_INET;
221712b2f30Ssthen 		b4.sin_family = AF_INET;
222712b2f30Ssthen 		a6.sin6_family = AF_INET6;
223712b2f30Ssthen 		b6.sin6_family = AF_INET6;
224712b2f30Ssthen 		memcpy(&a4.sin_addr, "abcd", 4);
225712b2f30Ssthen 		memcpy(&b4.sin_addr, "abcd", 4);
226712b2f30Ssthen 		unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 32,
227712b2f30Ssthen 			(struct sockaddr_storage*)&b4, 32, l4) == 32);
228712b2f30Ssthen 		unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 34,
229712b2f30Ssthen 			(struct sockaddr_storage*)&b4, 32, l4) == 32);
230712b2f30Ssthen 		for(i=0; i<=32; i++) {
231712b2f30Ssthen 			unit_assert(addr_in_common(
232712b2f30Ssthen 				(struct sockaddr_storage*)&a4, 32,
233712b2f30Ssthen 				(struct sockaddr_storage*)&b4, i, l4) == i);
234712b2f30Ssthen 			unit_assert(addr_in_common(
235712b2f30Ssthen 				(struct sockaddr_storage*)&a4, i,
236712b2f30Ssthen 				(struct sockaddr_storage*)&b4, 32, l4) == i);
237712b2f30Ssthen 			unit_assert(addr_in_common(
238712b2f30Ssthen 				(struct sockaddr_storage*)&a4, i,
239712b2f30Ssthen 				(struct sockaddr_storage*)&b4, i, l4) == i);
240712b2f30Ssthen 		}
241712b2f30Ssthen 		for(i=0; i<=32; i++) {
242712b2f30Ssthen 			memcpy(&a4.sin_addr, "\377\377\377\377", 4);
243712b2f30Ssthen 			memcpy(&b4.sin_addr, t4[i], 4);
244712b2f30Ssthen 			unit_assert(addr_in_common(
245712b2f30Ssthen 				(struct sockaddr_storage*)&a4, 32,
246712b2f30Ssthen 				(struct sockaddr_storage*)&b4, 32, l4) == i);
247712b2f30Ssthen 			unit_assert(addr_in_common(
248712b2f30Ssthen 				(struct sockaddr_storage*)&b4, 32,
249712b2f30Ssthen 				(struct sockaddr_storage*)&a4, 32, l4) == i);
250712b2f30Ssthen 		}
251712b2f30Ssthen 		memcpy(&a6.sin6_addr, "abcdefghabcdefgh", 16);
252712b2f30Ssthen 		memcpy(&b6.sin6_addr, "abcdefghabcdefgh", 16);
253712b2f30Ssthen 		unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 128,
254712b2f30Ssthen 			(struct sockaddr_storage*)&b6, 128, l6) == 128);
255712b2f30Ssthen 		unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 129,
256712b2f30Ssthen 			(struct sockaddr_storage*)&b6, 128, l6) == 128);
257712b2f30Ssthen 		for(i=0; i<=128; i++) {
258712b2f30Ssthen 			unit_assert(addr_in_common(
259712b2f30Ssthen 				(struct sockaddr_storage*)&a6, 128,
260712b2f30Ssthen 				(struct sockaddr_storage*)&b6, i, l6) == i);
261712b2f30Ssthen 			unit_assert(addr_in_common(
262712b2f30Ssthen 				(struct sockaddr_storage*)&a6, i,
263712b2f30Ssthen 				(struct sockaddr_storage*)&b6, 128, l6) == i);
264712b2f30Ssthen 			unit_assert(addr_in_common(
265712b2f30Ssthen 				(struct sockaddr_storage*)&a6, i,
266712b2f30Ssthen 				(struct sockaddr_storage*)&b6, i, l6) == i);
267712b2f30Ssthen 		}
268712b2f30Ssthen 	}
269712b2f30Ssthen 	/* test sockaddr_cmp_addr */
270712b2f30Ssthen 	unit_show_func("util/net_help.c", "sockaddr_cmp_addr");
271712b2f30Ssthen 	if(1) {
272712b2f30Ssthen 		struct sockaddr_storage a, b;
273712b2f30Ssthen 		socklen_t alen = (socklen_t)sizeof(a);
274712b2f30Ssthen 		socklen_t blen = (socklen_t)sizeof(b);
275712b2f30Ssthen 		unit_assert(ipstrtoaddr("127.0.0.0", 53, &a, &alen));
276712b2f30Ssthen 		unit_assert(ipstrtoaddr("127.255.255.255", 53, &b, &blen));
277712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) < 0);
278712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) > 0);
279712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&a, alen, &a, alen) == 0);
280712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&b, blen, &b, blen) == 0);
281712b2f30Ssthen 		unit_assert(ipstrtoaddr("192.168.121.5", 53, &a, &alen));
282712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) > 0);
283712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) < 0);
284712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&a, alen, &a, alen) == 0);
285712b2f30Ssthen 		unit_assert(ipstrtoaddr("2001:3578:ffeb::99", 53, &b, &blen));
286712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&b, blen, &b, blen) == 0);
287712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) < 0);
288712b2f30Ssthen 		unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) > 0);
289712b2f30Ssthen 	}
290712b2f30Ssthen 	/* test addr_is_ip4mapped */
291712b2f30Ssthen 	unit_show_func("util/net_help.c", "addr_is_ip4mapped");
292712b2f30Ssthen 	if(1) {
293712b2f30Ssthen 		struct sockaddr_storage a;
294712b2f30Ssthen 		socklen_t l = (socklen_t)sizeof(a);
295712b2f30Ssthen 		unit_assert(ipstrtoaddr("12.13.14.15", 53, &a, &l));
296712b2f30Ssthen 		unit_assert(!addr_is_ip4mapped(&a, l));
297712b2f30Ssthen 		unit_assert(ipstrtoaddr("fe80::217:31ff:fe91:df", 53, &a, &l));
298712b2f30Ssthen 		unit_assert(!addr_is_ip4mapped(&a, l));
299712b2f30Ssthen 		unit_assert(ipstrtoaddr("ffff::217:31ff:fe91:df", 53, &a, &l));
300712b2f30Ssthen 		unit_assert(!addr_is_ip4mapped(&a, l));
301712b2f30Ssthen 		unit_assert(ipstrtoaddr("::ffff:31ff:fe91:df", 53, &a, &l));
302712b2f30Ssthen 		unit_assert(!addr_is_ip4mapped(&a, l));
303712b2f30Ssthen 		unit_assert(ipstrtoaddr("::fffe:fe91:df", 53, &a, &l));
304712b2f30Ssthen 		unit_assert(!addr_is_ip4mapped(&a, l));
305712b2f30Ssthen 		unit_assert(ipstrtoaddr("::ffff:127.0.0.1", 53, &a, &l));
306712b2f30Ssthen 		unit_assert(addr_is_ip4mapped(&a, l));
307712b2f30Ssthen 		unit_assert(ipstrtoaddr("::ffff:127.0.0.2", 53, &a, &l));
308712b2f30Ssthen 		unit_assert(addr_is_ip4mapped(&a, l));
309712b2f30Ssthen 		unit_assert(ipstrtoaddr("::ffff:192.168.0.2", 53, &a, &l));
310712b2f30Ssthen 		unit_assert(addr_is_ip4mapped(&a, l));
311712b2f30Ssthen 		unit_assert(ipstrtoaddr("2::ffff:192.168.0.2", 53, &a, &l));
312712b2f30Ssthen 		unit_assert(!addr_is_ip4mapped(&a, l));
313712b2f30Ssthen 	}
314712b2f30Ssthen 	/* test addr_is_any */
315712b2f30Ssthen 	unit_show_func("util/net_help.c", "addr_is_any");
316712b2f30Ssthen 	if(1) {
317712b2f30Ssthen 		struct sockaddr_storage a;
318712b2f30Ssthen 		socklen_t l = (socklen_t)sizeof(a);
319712b2f30Ssthen 		unit_assert(ipstrtoaddr("0.0.0.0", 53, &a, &l));
320712b2f30Ssthen 		unit_assert(addr_is_any(&a, l));
321712b2f30Ssthen 		unit_assert(ipstrtoaddr("0.0.0.0", 10053, &a, &l));
322712b2f30Ssthen 		unit_assert(addr_is_any(&a, l));
323712b2f30Ssthen 		unit_assert(ipstrtoaddr("0.0.0.0", 0, &a, &l));
324712b2f30Ssthen 		unit_assert(addr_is_any(&a, l));
325712b2f30Ssthen 		unit_assert(ipstrtoaddr("::0", 0, &a, &l));
326712b2f30Ssthen 		unit_assert(addr_is_any(&a, l));
327712b2f30Ssthen 		unit_assert(ipstrtoaddr("::0", 53, &a, &l));
328712b2f30Ssthen 		unit_assert(addr_is_any(&a, l));
329712b2f30Ssthen 		unit_assert(ipstrtoaddr("::1", 53, &a, &l));
330712b2f30Ssthen 		unit_assert(!addr_is_any(&a, l));
331712b2f30Ssthen 		unit_assert(ipstrtoaddr("2001:1667::1", 0, &a, &l));
332712b2f30Ssthen 		unit_assert(!addr_is_any(&a, l));
333712b2f30Ssthen 		unit_assert(ipstrtoaddr("2001::0", 0, &a, &l));
334712b2f30Ssthen 		unit_assert(!addr_is_any(&a, l));
335712b2f30Ssthen 		unit_assert(ipstrtoaddr("10.0.0.0", 0, &a, &l));
336712b2f30Ssthen 		unit_assert(!addr_is_any(&a, l));
337712b2f30Ssthen 		unit_assert(ipstrtoaddr("0.0.0.10", 0, &a, &l));
338712b2f30Ssthen 		unit_assert(!addr_is_any(&a, l));
339712b2f30Ssthen 		unit_assert(ipstrtoaddr("192.0.2.1", 0, &a, &l));
340712b2f30Ssthen 		unit_assert(!addr_is_any(&a, l));
341712b2f30Ssthen 	}
342712b2f30Ssthen }
343712b2f30Ssthen 
344712b2f30Ssthen #include "util/config_file.h"
345712b2f30Ssthen /** test config_file: cfg_parse_memsize */
346712b2f30Ssthen static void
347712b2f30Ssthen config_memsize_test(void)
348712b2f30Ssthen {
349712b2f30Ssthen 	size_t v = 0;
350712b2f30Ssthen 	unit_show_func("util/config_file.c", "cfg_parse_memsize");
351712b2f30Ssthen 	if(0) {
352712b2f30Ssthen 		/* these emit errors */
353712b2f30Ssthen 		unit_assert( cfg_parse_memsize("", &v) == 0);
354712b2f30Ssthen 		unit_assert( cfg_parse_memsize("bla", &v) == 0);
355712b2f30Ssthen 		unit_assert( cfg_parse_memsize("nop", &v) == 0);
356712b2f30Ssthen 		unit_assert( cfg_parse_memsize("n0b", &v) == 0);
357712b2f30Ssthen 		unit_assert( cfg_parse_memsize("gb", &v) == 0);
358712b2f30Ssthen 		unit_assert( cfg_parse_memsize("b", &v) == 0);
359712b2f30Ssthen 		unit_assert( cfg_parse_memsize("kb", &v) == 0);
360712b2f30Ssthen 		unit_assert( cfg_parse_memsize("kk kb", &v) == 0);
361712b2f30Ssthen 	}
362712b2f30Ssthen 	unit_assert( cfg_parse_memsize("0", &v) && v==0);
363712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1", &v) && v==1);
364712b2f30Ssthen 	unit_assert( cfg_parse_memsize("10", &v) && v==10);
365712b2f30Ssthen 	unit_assert( cfg_parse_memsize("10b", &v) && v==10);
366712b2f30Ssthen 	unit_assert( cfg_parse_memsize("5b", &v) && v==5);
367712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1024", &v) && v==1024);
368712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1k", &v) && v==1024);
369712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1K", &v) && v==1024);
370712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1Kb", &v) && v==1024);
371712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1kb", &v) && v==1024);
372712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1 kb", &v) && v==1024);
373712b2f30Ssthen 	unit_assert( cfg_parse_memsize("10 kb", &v) && v==10240);
374712b2f30Ssthen 	unit_assert( cfg_parse_memsize("2k", &v) && v==2048);
375712b2f30Ssthen 	unit_assert( cfg_parse_memsize("2m", &v) && v==2048*1024);
376712b2f30Ssthen 	unit_assert( cfg_parse_memsize("3M", &v) && v==3072*1024);
377712b2f30Ssthen 	unit_assert( cfg_parse_memsize("40m", &v) && v==40960*1024);
378712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1G", &v) && v==1024*1024*1024);
379712b2f30Ssthen 	unit_assert( cfg_parse_memsize("1 Gb", &v) && v==1024*1024*1024);
380712b2f30Ssthen 	unit_assert( cfg_parse_memsize("0 Gb", &v) && v==0*1024*1024);
381712b2f30Ssthen }
382712b2f30Ssthen 
383712b2f30Ssthen /** test config_file: test tag code */
384712b2f30Ssthen static void
385712b2f30Ssthen config_tag_test(void)
386712b2f30Ssthen {
387712b2f30Ssthen 	unit_show_func("util/config_file.c", "taglist_intersect");
388712b2f30Ssthen 	unit_assert( taglist_intersect(
389712b2f30Ssthen 		(uint8_t*)"\000\000\000", 3, (uint8_t*)"\001\000\001", 3
390712b2f30Ssthen 		) == 0);
391712b2f30Ssthen 	unit_assert( taglist_intersect(
392712b2f30Ssthen 		(uint8_t*)"\000\000\001", 3, (uint8_t*)"\001\000\001", 3
393712b2f30Ssthen 		) == 1);
394712b2f30Ssthen 	unit_assert( taglist_intersect(
395712b2f30Ssthen 		(uint8_t*)"\001\000\000", 3, (uint8_t*)"\001\000\001", 3
396712b2f30Ssthen 		) == 1);
397712b2f30Ssthen 	unit_assert( taglist_intersect(
398712b2f30Ssthen 		(uint8_t*)"\001", 1, (uint8_t*)"\001\000\001", 3
399712b2f30Ssthen 		) == 1);
400712b2f30Ssthen 	unit_assert( taglist_intersect(
401712b2f30Ssthen 		(uint8_t*)"\001\000\001", 3, (uint8_t*)"\001", 1
402712b2f30Ssthen 		) == 1);
403712b2f30Ssthen }
404712b2f30Ssthen 
405712b2f30Ssthen #include "util/rtt.h"
406712b2f30Ssthen #include "util/timehist.h"
4077bc20e6dSsthen #include "iterator/iterator.h"
408712b2f30Ssthen #include "libunbound/unbound.h"
409712b2f30Ssthen /** test RTT code */
410712b2f30Ssthen static void
411712b2f30Ssthen rtt_test(void)
412712b2f30Ssthen {
4137bc20e6dSsthen 	int init = UNKNOWN_SERVER_NICENESS;
414712b2f30Ssthen 	int i;
415712b2f30Ssthen 	struct rtt_info r;
416712b2f30Ssthen 	unit_show_func("util/rtt.c", "rtt_timeout");
417712b2f30Ssthen 	rtt_init(&r);
418712b2f30Ssthen 	/* initial value sensible */
419712b2f30Ssthen 	unit_assert( rtt_timeout(&r) == init );
420712b2f30Ssthen 	rtt_lost(&r, init);
421712b2f30Ssthen 	unit_assert( rtt_timeout(&r) == init*2 );
422712b2f30Ssthen 	rtt_lost(&r, init*2);
423712b2f30Ssthen 	unit_assert( rtt_timeout(&r) == init*4 );
424712b2f30Ssthen 	rtt_update(&r, 4000);
425712b2f30Ssthen 	unit_assert( rtt_timeout(&r) >= 2000 );
426712b2f30Ssthen 	rtt_lost(&r, rtt_timeout(&r) );
427712b2f30Ssthen 	for(i=0; i<100; i++) {
428712b2f30Ssthen 		rtt_lost(&r, rtt_timeout(&r) );
429712b2f30Ssthen 		unit_assert( rtt_timeout(&r) > RTT_MIN_TIMEOUT-1);
430712b2f30Ssthen 		unit_assert( rtt_timeout(&r) < RTT_MAX_TIMEOUT+1);
431712b2f30Ssthen 	}
432712b2f30Ssthen 	/* must be the same, timehist bucket is used in stats */
433712b2f30Ssthen 	unit_assert(UB_STATS_BUCKET_NUM == NUM_BUCKETS_HIST);
434712b2f30Ssthen }
435712b2f30Ssthen 
436712b2f30Ssthen #include "services/cache/infra.h"
437712b2f30Ssthen 
438712b2f30Ssthen /* lookup and get key and data structs easily */
439712b2f30Ssthen static struct infra_data* infra_lookup_host(struct infra_cache* infra,
440712b2f30Ssthen 	struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
441712b2f30Ssthen 	size_t zonelen, int wr, time_t now, struct infra_key** k)
442712b2f30Ssthen {
443712b2f30Ssthen 	struct infra_data* d;
444712b2f30Ssthen 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
445712b2f30Ssthen 		zone, zonelen, wr);
446712b2f30Ssthen 	if(!e) return NULL;
447712b2f30Ssthen 	d = (struct infra_data*)e->data;
448712b2f30Ssthen 	if(d->ttl < now) {
449712b2f30Ssthen 		lock_rw_unlock(&e->lock);
450712b2f30Ssthen 		return NULL;
451712b2f30Ssthen 	}
452712b2f30Ssthen 	*k = (struct infra_key*)e->key;
453712b2f30Ssthen 	return d;
454712b2f30Ssthen }
455712b2f30Ssthen 
456712b2f30Ssthen /** test host cache */
457712b2f30Ssthen static void
458712b2f30Ssthen infra_test(void)
459712b2f30Ssthen {
460712b2f30Ssthen 	struct sockaddr_storage one;
461712b2f30Ssthen 	socklen_t onelen;
462712b2f30Ssthen 	uint8_t* zone = (uint8_t*)"\007example\003com\000";
463712b2f30Ssthen 	size_t zonelen = 13;
464712b2f30Ssthen 	struct infra_cache* slab;
465712b2f30Ssthen 	struct config_file* cfg = config_create();
466712b2f30Ssthen 	time_t now = 0;
467712b2f30Ssthen 	uint8_t edns_lame;
468712b2f30Ssthen 	int vs, to;
469712b2f30Ssthen 	struct infra_key* k;
470712b2f30Ssthen 	struct infra_data* d;
471712b2f30Ssthen 	int init = 376;
472712b2f30Ssthen 
473712b2f30Ssthen 	unit_show_feature("infra cache");
474712b2f30Ssthen 	unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
475712b2f30Ssthen 
476712b2f30Ssthen 	slab = infra_create(cfg);
477712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
478712b2f30Ssthen 		&vs, &edns_lame, &to) );
479712b2f30Ssthen 	unit_assert( vs == 0 && to == init && edns_lame == 0 );
480712b2f30Ssthen 
481712b2f30Ssthen 	unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
482712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
483712b2f30Ssthen 			now, &vs, &edns_lame, &to) );
484712b2f30Ssthen 	unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
485712b2f30Ssthen 
486712b2f30Ssthen 	unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
487712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
488712b2f30Ssthen 			now, &vs, &edns_lame, &to) );
489712b2f30Ssthen 	unit_assert( vs == -1 && to == init*2  && edns_lame == 1);
490712b2f30Ssthen 
491712b2f30Ssthen 	now += cfg->host_ttl + 10;
492712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
493712b2f30Ssthen 			now, &vs, &edns_lame, &to) );
494712b2f30Ssthen 	unit_assert( vs == 0 && to == init && edns_lame == 0 );
495712b2f30Ssthen 
496712b2f30Ssthen 	unit_assert( infra_set_lame(slab, &one, onelen,
497712b2f30Ssthen 		zone, zonelen,  now, 0, 0, LDNS_RR_TYPE_A) );
498712b2f30Ssthen 	unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
499712b2f30Ssthen 	unit_assert( d->ttl == now+cfg->host_ttl );
500712b2f30Ssthen 	unit_assert( d->edns_version == 0 );
501712b2f30Ssthen 	unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
502712b2f30Ssthen 		!d->lame_other);
503712b2f30Ssthen 	lock_rw_unlock(&k->entry.lock);
504712b2f30Ssthen 
505712b2f30Ssthen 	/* test merge of data */
506712b2f30Ssthen 	unit_assert( infra_set_lame(slab, &one, onelen,
507712b2f30Ssthen 		zone, zonelen,  now, 0, 0, LDNS_RR_TYPE_AAAA) );
508712b2f30Ssthen 	unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
509712b2f30Ssthen 	unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
510712b2f30Ssthen 		d->lame_other);
511712b2f30Ssthen 	lock_rw_unlock(&k->entry.lock);
512712b2f30Ssthen 
513712b2f30Ssthen 	/* test that noEDNS cannot overwrite known-yesEDNS */
514712b2f30Ssthen 	now += cfg->host_ttl + 10;
515712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
516712b2f30Ssthen 			now, &vs, &edns_lame, &to) );
517712b2f30Ssthen 	unit_assert( vs == 0 && to == init && edns_lame == 0 );
518712b2f30Ssthen 
519712b2f30Ssthen 	unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
520712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
521712b2f30Ssthen 			now, &vs, &edns_lame, &to) );
522712b2f30Ssthen 	unit_assert( vs == 0 && to == init && edns_lame == 1 );
523712b2f30Ssthen 
524712b2f30Ssthen 	unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
525712b2f30Ssthen 	unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
526712b2f30Ssthen 			now, &vs, &edns_lame, &to) );
527712b2f30Ssthen 	unit_assert( vs == 0 && to == init && edns_lame == 1 );
528712b2f30Ssthen 
529712b2f30Ssthen 	infra_delete(slab);
530712b2f30Ssthen 	config_delete(cfg);
531712b2f30Ssthen }
532712b2f30Ssthen 
533437d2860Ssthen #include "util/edns.h"
534437d2860Ssthen /* Complete version-invalid client cookie; needs a new one.
535437d2860Ssthen  * Based on edns_cookie_rfc9018_a2 */
536437d2860Ssthen static void
537437d2860Ssthen edns_cookie_invalid_version(void)
538437d2860Ssthen {
539437d2860Ssthen 	uint32_t timestamp = 1559734385;
540437d2860Ssthen 	uint8_t client_cookie[] = {
541437d2860Ssthen 		0x24, 0x64, 0xc4, 0xab, 0xcf, 0x10, 0xc9, 0x57,
542437d2860Ssthen 		0x99, 0x00, 0x00, 0x00,
543437d2860Ssthen 		0x5c, 0xf7, 0x9f, 0x11,
544437d2860Ssthen 		0x1f, 0x81, 0x30, 0xc3, 0xee, 0xe2, 0x94, 0x80 };
545437d2860Ssthen 	uint8_t server_cookie[] = {
546437d2860Ssthen 		0x24, 0x64, 0xc4, 0xab, 0xcf, 0x10, 0xc9, 0x57,
547437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
548437d2860Ssthen 		0x5c, 0xf7, 0xa8, 0x71,
549437d2860Ssthen 		0xd4, 0xa5, 0x64, 0xa1, 0x44, 0x2a, 0xca, 0x77 };
550437d2860Ssthen 	uint8_t server_secret[] = {
551437d2860Ssthen 		0xe5, 0xe9, 0x73, 0xe5, 0xa6, 0xb2, 0xa4, 0x3f,
552437d2860Ssthen 		0x48, 0xe7, 0xdc, 0x84, 0x9e, 0x37, 0xbf, 0xcf };
553437d2860Ssthen 	uint8_t buf[32];
554437d2860Ssthen 	/* copy client cookie|version|reserved|timestamp */
555437d2860Ssthen 	memcpy(buf, client_cookie, 8 + 4 + 4);
556437d2860Ssthen 	/* copy ip 198.51.100.100 */
557437d2860Ssthen 	memcpy(buf + 16, "\306\063\144\144", 4);
558437d2860Ssthen 	unit_assert(edns_cookie_server_validate(client_cookie,
559437d2860Ssthen 		sizeof(client_cookie), server_secret, sizeof(server_secret), 1,
560437d2860Ssthen 		buf, timestamp) == COOKIE_STATUS_INVALID);
561437d2860Ssthen 	edns_cookie_server_write(buf, server_secret, 1, timestamp);
562437d2860Ssthen 	unit_assert(memcmp(server_cookie, buf, 24) == 0);
563437d2860Ssthen }
564437d2860Ssthen 
565437d2860Ssthen /* Complete hash-invalid client cookie; needs a new one. */
566437d2860Ssthen static void
567437d2860Ssthen edns_cookie_invalid_hash(void)
568437d2860Ssthen {
569437d2860Ssthen 	uint32_t timestamp = 0;
570437d2860Ssthen 	uint8_t client_cookie[] = {
571437d2860Ssthen 		0xfc, 0x93, 0xfc, 0x62, 0x80, 0x7d, 0xdb, 0x86,
572437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
573437d2860Ssthen 		0x00, 0x00, 0x00, 0x00,
574437d2860Ssthen 		0x32, 0xF2, 0x43, 0xB9, 0xBC, 0xFE, 0xC4, 0x06 };
575437d2860Ssthen 	uint8_t server_cookie[] = {
576437d2860Ssthen 		0xfc, 0x93, 0xfc, 0x62, 0x80, 0x7d, 0xdb, 0x86,
577437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
578437d2860Ssthen 		0x00, 0x00, 0x00, 0x00,
579437d2860Ssthen 		0xBA, 0x0D, 0x82, 0x90, 0x8F, 0xAA, 0xEB, 0xBD };
580437d2860Ssthen 	uint8_t server_secret[] = {
581437d2860Ssthen 		0xe5, 0xe9, 0x73, 0xe5, 0xa6, 0xb2, 0xa4, 0x3f,
582437d2860Ssthen 		0x48, 0xe7, 0xdc, 0x84, 0x9e, 0x37, 0xbf, 0xcf };
583437d2860Ssthen 	uint8_t buf[32];
584437d2860Ssthen 	/* copy client cookie|version|reserved|timestamp */
585437d2860Ssthen 	memcpy(buf, client_cookie, 8 + 4 + 4);
586437d2860Ssthen 	/* copy ip 203.0.113.203 */
587437d2860Ssthen 	memcpy(buf + 16, "\313\000\161\313", 4);
588437d2860Ssthen 	unit_assert(edns_cookie_server_validate(client_cookie,
589437d2860Ssthen 		sizeof(client_cookie), server_secret, sizeof(server_secret), 1,
590437d2860Ssthen 		buf, timestamp) == COOKIE_STATUS_INVALID);
591437d2860Ssthen 	edns_cookie_server_write(buf, server_secret, 1, timestamp);
592437d2860Ssthen 	unit_assert(memcmp(server_cookie, buf, 24) == 0);
593437d2860Ssthen }
594437d2860Ssthen 
595437d2860Ssthen /* Complete hash-valid client cookie; more than 30 minutes old; needs a
596437d2860Ssthen  * refreshed server cookie.
597437d2860Ssthen  * A slightly better variation of edns_cookie_rfc9018_a3 for Unbound to check
598437d2860Ssthen  * that RESERVED bits do not influence cookie validation. */
599437d2860Ssthen static void
600437d2860Ssthen edns_cookie_rfc9018_a3_better(void)
601437d2860Ssthen {
602437d2860Ssthen 	uint32_t timestamp = 1800 + 1;
603437d2860Ssthen 	uint8_t client_cookie[] = {
604437d2860Ssthen 		0xfc, 0x93, 0xfc, 0x62, 0x80, 0x7d, 0xdb, 0x86,
605437d2860Ssthen 		0x01, 0xab, 0xcd, 0xef,
606437d2860Ssthen 		0x00, 0x00, 0x00, 0x00,
607437d2860Ssthen 		0x32, 0xF2, 0x43, 0xB9, 0xBC, 0xFE, 0xC4, 0x06 };
608437d2860Ssthen 	uint8_t server_cookie[] = {
609437d2860Ssthen 		0xfc, 0x93, 0xfc, 0x62, 0x80, 0x7d, 0xdb, 0x86,
610437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
611437d2860Ssthen 		0x00, 0x00, 0x07, 0x09,
612437d2860Ssthen 		0x62, 0xD5, 0x93, 0x09, 0x14, 0x5C, 0x23, 0x9D };
613437d2860Ssthen 	uint8_t server_secret[] = {
614437d2860Ssthen 		0xe5, 0xe9, 0x73, 0xe5, 0xa6, 0xb2, 0xa4, 0x3f,
615437d2860Ssthen 		0x48, 0xe7, 0xdc, 0x84, 0x9e, 0x37, 0xbf, 0xcf };
616437d2860Ssthen 	uint8_t buf[32];
617437d2860Ssthen 	/* copy client cookie|version|reserved|timestamp */
618437d2860Ssthen 	memcpy(buf, client_cookie, 8 + 4 + 4);
619437d2860Ssthen 	/* copy ip 203.0.113.203 */
620437d2860Ssthen 	memcpy(buf + 16, "\313\000\161\313", 4);
621437d2860Ssthen 	unit_assert(edns_cookie_server_validate(client_cookie,
622437d2860Ssthen 		sizeof(client_cookie), server_secret, sizeof(server_secret), 1,
623437d2860Ssthen 		buf, timestamp) == COOKIE_STATUS_VALID_RENEW);
624437d2860Ssthen 	edns_cookie_server_write(buf, server_secret, 1, timestamp);
625437d2860Ssthen 	unit_assert(memcmp(server_cookie, buf, 24) == 0);
626437d2860Ssthen }
627437d2860Ssthen 
628437d2860Ssthen /* Complete hash-valid client cookie; more than 60 minutes old (expired);
629437d2860Ssthen  * needs a refreshed server cookie. */
630437d2860Ssthen static void
631437d2860Ssthen edns_cookie_rfc9018_a3(void)
632437d2860Ssthen {
633437d2860Ssthen 	uint32_t timestamp = 1559734700;
634437d2860Ssthen 	uint8_t client_cookie[] = {
635437d2860Ssthen 		0xfc, 0x93, 0xfc, 0x62, 0x80, 0x7d, 0xdb, 0x86,
636437d2860Ssthen 		0x01, 0xab, 0xcd, 0xef,
637437d2860Ssthen 		0x5c, 0xf7, 0x8f, 0x71,
638437d2860Ssthen 		0xa3, 0x14, 0x22, 0x7b, 0x66, 0x79, 0xeb, 0xf5 };
639437d2860Ssthen 	uint8_t server_cookie[] = {
640437d2860Ssthen 		0xfc, 0x93, 0xfc, 0x62, 0x80, 0x7d, 0xdb, 0x86,
641437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
642437d2860Ssthen 		0x5c, 0xf7, 0xa9, 0xac,
643437d2860Ssthen 		0xf7, 0x3a, 0x78, 0x10, 0xac, 0xa2, 0x38, 0x1e };
644437d2860Ssthen 	uint8_t server_secret[] = {
645437d2860Ssthen 		0xe5, 0xe9, 0x73, 0xe5, 0xa6, 0xb2, 0xa4, 0x3f,
646437d2860Ssthen 		0x48, 0xe7, 0xdc, 0x84, 0x9e, 0x37, 0xbf, 0xcf };
647437d2860Ssthen 	uint8_t buf[32];
648437d2860Ssthen 	/* copy client cookie|version|reserved|timestamp */
649437d2860Ssthen 	memcpy(buf, client_cookie, 8 + 4 + 4);
650437d2860Ssthen 	/* copy ip 203.0.113.203 */
651437d2860Ssthen 	memcpy(buf + 16, "\313\000\161\313", 4);
652437d2860Ssthen 	unit_assert(edns_cookie_server_validate(client_cookie,
653437d2860Ssthen 		sizeof(client_cookie), server_secret, sizeof(server_secret), 1,
654437d2860Ssthen 		buf, timestamp) == COOKIE_STATUS_EXPIRED);
655437d2860Ssthen 	edns_cookie_server_write(buf, server_secret, 1, timestamp);
656437d2860Ssthen 	unit_assert(memcmp(server_cookie, buf, 24) == 0);
657437d2860Ssthen }
658437d2860Ssthen 
659437d2860Ssthen /* Complete hash-valid client cookie; more than 30 minutes old; needs a
660437d2860Ssthen  * refreshed server cookie. */
661437d2860Ssthen static void
662437d2860Ssthen edns_cookie_rfc9018_a2(void)
663437d2860Ssthen {
664437d2860Ssthen 	uint32_t timestamp = 1559734385;
665437d2860Ssthen 	uint8_t client_cookie[] = {
666437d2860Ssthen 		0x24, 0x64, 0xc4, 0xab, 0xcf, 0x10, 0xc9, 0x57,
667437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
668437d2860Ssthen 		0x5c, 0xf7, 0x9f, 0x11,
669437d2860Ssthen 		0x1f, 0x81, 0x30, 0xc3, 0xee, 0xe2, 0x94, 0x80 };
670437d2860Ssthen 	uint8_t server_cookie[] = {
671437d2860Ssthen 		0x24, 0x64, 0xc4, 0xab, 0xcf, 0x10, 0xc9, 0x57,
672437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
673437d2860Ssthen 		0x5c, 0xf7, 0xa8, 0x71,
674437d2860Ssthen 		0xd4, 0xa5, 0x64, 0xa1, 0x44, 0x2a, 0xca, 0x77 };
675437d2860Ssthen 	uint8_t server_secret[] = {
676437d2860Ssthen 		0xe5, 0xe9, 0x73, 0xe5, 0xa6, 0xb2, 0xa4, 0x3f,
677437d2860Ssthen 		0x48, 0xe7, 0xdc, 0x84, 0x9e, 0x37, 0xbf, 0xcf };
678437d2860Ssthen 	uint8_t buf[32];
679437d2860Ssthen 	/* copy client cookie|version|reserved|timestamp */
680437d2860Ssthen 	memcpy(buf, client_cookie, 8 + 4 + 4);
681437d2860Ssthen 	/* copy ip 198.51.100.100 */
682437d2860Ssthen 	memcpy(buf + 16, "\306\063\144\144", 4);
683437d2860Ssthen 	unit_assert(edns_cookie_server_validate(client_cookie,
684437d2860Ssthen 		sizeof(client_cookie), server_secret, sizeof(server_secret), 1,
685437d2860Ssthen 		buf, timestamp) == COOKIE_STATUS_VALID_RENEW);
686437d2860Ssthen 	edns_cookie_server_write(buf, server_secret, 1, timestamp);
687437d2860Ssthen 	unit_assert(memcmp(server_cookie, buf, 24) == 0);
688437d2860Ssthen }
689437d2860Ssthen 
690437d2860Ssthen /* Only client cookie; needs a complete server cookie. */
691437d2860Ssthen static void
692437d2860Ssthen edns_cookie_rfc9018_a1(void)
693437d2860Ssthen {
694437d2860Ssthen 	uint32_t timestamp = 1559731985;
695437d2860Ssthen 	uint8_t client_cookie[] = {
696437d2860Ssthen 		0x24, 0x64, 0xc4, 0xab, 0xcf, 0x10, 0xc9, 0x57 };
697437d2860Ssthen 	uint8_t server_cookie[] = {
698437d2860Ssthen 		0x24, 0x64, 0xc4, 0xab, 0xcf, 0x10, 0xc9, 0x57,
699437d2860Ssthen 		0x01, 0x00, 0x00, 0x00,
700437d2860Ssthen 		0x5c, 0xf7, 0x9f, 0x11,
701437d2860Ssthen 		0x1f, 0x81, 0x30, 0xc3, 0xee, 0xe2, 0x94, 0x80 };
702437d2860Ssthen 	uint8_t server_secret[] = {
703437d2860Ssthen 		0xe5, 0xe9, 0x73, 0xe5, 0xa6, 0xb2, 0xa4, 0x3f,
704437d2860Ssthen 		0x48, 0xe7, 0xdc, 0x84, 0x9e, 0x37, 0xbf, 0xcf };
705437d2860Ssthen 	uint8_t buf[32];
706437d2860Ssthen 	/* copy client cookie|version|reserved|timestamp */
707437d2860Ssthen 	memcpy(buf, server_cookie, 8 + 4 + 4);
708437d2860Ssthen 	/* copy ip 198.51.100.100 */
709437d2860Ssthen 	memcpy(buf + 16, "\306\063\144\144", 4);
710437d2860Ssthen 	unit_assert(edns_cookie_server_validate(client_cookie,
711437d2860Ssthen 		sizeof(client_cookie),
712437d2860Ssthen 		/* these will not be used; it will return invalid
713437d2860Ssthen 		 * because of the size. */
714437d2860Ssthen 		NULL, 0, 1, NULL, 0) == COOKIE_STATUS_CLIENT_ONLY);
715437d2860Ssthen 	edns_cookie_server_write(buf, server_secret, 1, timestamp);
716437d2860Ssthen 	unit_assert(memcmp(server_cookie, buf, 24) == 0);
717437d2860Ssthen }
718437d2860Ssthen 
719437d2860Ssthen /** test interoperable DNS cookies (RFC9018) */
720437d2860Ssthen static void
721437d2860Ssthen edns_cookie_test(void)
722437d2860Ssthen {
723437d2860Ssthen 	unit_show_feature("interoperable dns cookies");
724437d2860Ssthen 	/* Check RFC9018 appendix test vectors */
725437d2860Ssthen 	edns_cookie_rfc9018_a1();
726437d2860Ssthen 	edns_cookie_rfc9018_a2();
727437d2860Ssthen 	edns_cookie_rfc9018_a3();
728437d2860Ssthen 	/* More tests */
729437d2860Ssthen 	edns_cookie_rfc9018_a3_better();
730437d2860Ssthen 	edns_cookie_invalid_hash();
731437d2860Ssthen 	edns_cookie_invalid_version();
732437d2860Ssthen }
733437d2860Ssthen 
734712b2f30Ssthen #include "util/random.h"
735712b2f30Ssthen /** test randomness */
736712b2f30Ssthen static void
737712b2f30Ssthen rnd_test(void)
738712b2f30Ssthen {
739712b2f30Ssthen 	struct ub_randstate* r;
740712b2f30Ssthen 	int num = 1000, i;
741712b2f30Ssthen 	long int a[1000];
742712b2f30Ssthen 	unit_show_feature("ub_random");
743b0dfc31bSsthen 	unit_assert( (r = ub_initstate(NULL)) );
744712b2f30Ssthen 	for(i=0; i<num; i++) {
745712b2f30Ssthen 		a[i] = ub_random(r);
746712b2f30Ssthen 		unit_assert(a[i] >= 0);
747712b2f30Ssthen 		unit_assert((size_t)a[i] <= (size_t)0x7fffffff);
748712b2f30Ssthen 		if(i > 5)
749712b2f30Ssthen 			unit_assert(a[i] != a[i-1] || a[i] != a[i-2] ||
750712b2f30Ssthen 				a[i] != a[i-3] || a[i] != a[i-4] ||
751712b2f30Ssthen 				a[i] != a[i-5] || a[i] != a[i-6]);
752712b2f30Ssthen 	}
753712b2f30Ssthen 	a[0] = ub_random_max(r, 1);
754712b2f30Ssthen 	unit_assert(a[0] >= 0 && a[0] < 1);
755712b2f30Ssthen 	a[0] = ub_random_max(r, 10000);
756712b2f30Ssthen 	unit_assert(a[0] >= 0 && a[0] < 10000);
757712b2f30Ssthen 	for(i=0; i<num; i++) {
758712b2f30Ssthen 		a[i] = ub_random_max(r, 10);
759712b2f30Ssthen 		unit_assert(a[i] >= 0 && a[i] < 10);
760712b2f30Ssthen 	}
761712b2f30Ssthen 	ub_randfree(r);
762712b2f30Ssthen }
763712b2f30Ssthen 
764712b2f30Ssthen #include "respip/respip.h"
765712b2f30Ssthen #include "services/localzone.h"
766712b2f30Ssthen #include "util/data/packed_rrset.h"
767712b2f30Ssthen typedef struct addr_action {char* ip; char* sact; enum respip_action act;}
768712b2f30Ssthen 	addr_action_t;
769712b2f30Ssthen 
770712b2f30Ssthen /** Utility function that verifies that the respip set has actions as expected */
771712b2f30Ssthen static void
772712b2f30Ssthen verify_respip_set_actions(struct respip_set* set, addr_action_t actions[],
773712b2f30Ssthen 	int actions_len)
774712b2f30Ssthen {
775712b2f30Ssthen 	int i = 0;
776712b2f30Ssthen 	struct rbtree_type* tree = respip_set_get_tree(set);
777712b2f30Ssthen 	for (i=0; i<actions_len; i++) {
778712b2f30Ssthen 		struct sockaddr_storage addr;
779712b2f30Ssthen 		int net;
780712b2f30Ssthen 		socklen_t addrlen;
781712b2f30Ssthen 		struct resp_addr* node;
782712b2f30Ssthen 		netblockstrtoaddr(actions[i].ip, UNBOUND_DNS_PORT, &addr,
783712b2f30Ssthen 			&addrlen, &net);
784712b2f30Ssthen 		node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
785712b2f30Ssthen 
786712b2f30Ssthen 		/** we have the node and the node has the correct action
787712b2f30Ssthen 		  * and has no data */
788712b2f30Ssthen 		unit_assert(node);
789712b2f30Ssthen 		unit_assert(actions[i].act ==
790712b2f30Ssthen 			resp_addr_get_action(node));
791712b2f30Ssthen 		unit_assert(resp_addr_get_rrset(node) == NULL);
792712b2f30Ssthen 	}
793712b2f30Ssthen 	unit_assert(actions_len && i == actions_len);
794712b2f30Ssthen 	unit_assert(actions_len == (int)tree->count);
795712b2f30Ssthen }
796712b2f30Ssthen 
797712b2f30Ssthen /** Global respip actions test; apply raw config data and verify that
798712b2f30Ssthen   * all the nodes in the respip set, looked up by address, have expected
799712b2f30Ssthen   * actions */
800712b2f30Ssthen static void
801712b2f30Ssthen respip_conf_actions_test(void)
802712b2f30Ssthen {
803712b2f30Ssthen 	addr_action_t config_response_ip[] = {
804712b2f30Ssthen 		{"192.0.1.0/24", "deny", respip_deny},
805712b2f30Ssthen 		{"192.0.2.0/24", "redirect", respip_redirect},
806712b2f30Ssthen 		{"192.0.3.0/26", "inform", respip_inform},
807712b2f30Ssthen 		{"192.0.4.0/27", "inform_deny", respip_inform_deny},
808712b2f30Ssthen 		{"2001:db8:1::/48", "always_transparent", respip_always_transparent},
809712b2f30Ssthen 		{"2001:db8:2::/49", "always_refuse", respip_always_refuse},
810712b2f30Ssthen 		{"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
811712b2f30Ssthen 	};
812712b2f30Ssthen 	int i;
813712b2f30Ssthen 	struct respip_set* set = respip_set_create();
814712b2f30Ssthen 	struct config_file cfg;
815712b2f30Ssthen 	int clen = (int)(sizeof(config_response_ip) / sizeof(addr_action_t));
816712b2f30Ssthen 
817712b2f30Ssthen 	unit_assert(set);
818712b2f30Ssthen 	unit_show_feature("global respip config actions apply");
819712b2f30Ssthen 	memset(&cfg, 0, sizeof(cfg));
820712b2f30Ssthen 	for(i=0; i<clen; i++) {
821712b2f30Ssthen 		char* ip = strdup(config_response_ip[i].ip);
822712b2f30Ssthen 		char* sact = strdup(config_response_ip[i].sact);
823712b2f30Ssthen 		unit_assert(ip && sact);
824712b2f30Ssthen 		if(!cfg_str2list_insert(&cfg.respip_actions, ip, sact))
825712b2f30Ssthen 			unit_assert(0);
826712b2f30Ssthen 	}
827712b2f30Ssthen 	unit_assert(respip_global_apply_cfg(set, &cfg));
828712b2f30Ssthen 	verify_respip_set_actions(set, config_response_ip, clen);
829712b2f30Ssthen 
830712b2f30Ssthen 	respip_set_delete(set);
831712b2f30Ssthen 	config_deldblstrlist(cfg.respip_actions);
832712b2f30Ssthen }
833712b2f30Ssthen 
834712b2f30Ssthen /** Per-view respip actions test; apply raw configuration with two views
835712b2f30Ssthen   * and verify that actions are as expected in respip sets of both views */
836712b2f30Ssthen static void
837712b2f30Ssthen respip_view_conf_actions_test(void)
838712b2f30Ssthen {
839712b2f30Ssthen 	addr_action_t config_response_ip_view1[] = {
840712b2f30Ssthen 		{"192.0.1.0/24", "deny", respip_deny},
841712b2f30Ssthen 		{"192.0.2.0/24", "redirect", respip_redirect},
842712b2f30Ssthen 		{"192.0.3.0/26", "inform", respip_inform},
843712b2f30Ssthen 		{"192.0.4.0/27", "inform_deny", respip_inform_deny},
844712b2f30Ssthen 	};
845712b2f30Ssthen 	addr_action_t config_response_ip_view2[] = {
846712b2f30Ssthen 		{"2001:db8:1::/48", "always_transparent", respip_always_transparent},
847712b2f30Ssthen 		{"2001:db8:2::/49", "always_refuse", respip_always_refuse},
848712b2f30Ssthen 		{"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
849712b2f30Ssthen 	};
850712b2f30Ssthen 	int i;
851712b2f30Ssthen 	struct config_file cfg;
852712b2f30Ssthen 	int clen1 = (int)(sizeof(config_response_ip_view1) / sizeof(addr_action_t));
853712b2f30Ssthen 	int clen2 = (int)(sizeof(config_response_ip_view2) / sizeof(addr_action_t));
854712b2f30Ssthen 	struct config_view* cv1;
855712b2f30Ssthen 	struct config_view* cv2;
856712b2f30Ssthen 	int have_respip_cfg = 0;
857712b2f30Ssthen 	struct views* views = NULL;
858712b2f30Ssthen 	struct view* v = NULL;
859712b2f30Ssthen 
860712b2f30Ssthen 	unit_show_feature("per-view respip config actions apply");
861712b2f30Ssthen 	memset(&cfg, 0, sizeof(cfg));
862712b2f30Ssthen 	cv1 = (struct config_view*)calloc(1, sizeof(struct config_view));
863712b2f30Ssthen 	cv2 = (struct config_view*)calloc(1, sizeof(struct config_view));
864712b2f30Ssthen 	unit_assert(cv1 && cv2);
865712b2f30Ssthen 	cv1->name = strdup("view1");
866712b2f30Ssthen 	cv2->name = strdup("view2");
867712b2f30Ssthen 	unit_assert(cv1->name && cv2->name);
868712b2f30Ssthen 	cv1->next = cv2;
869712b2f30Ssthen 	cfg.views = cv1;
870712b2f30Ssthen 
871712b2f30Ssthen 	for(i=0; i<clen1; i++) {
872712b2f30Ssthen 		char* ip = strdup(config_response_ip_view1[i].ip);
873712b2f30Ssthen 		char* sact = strdup(config_response_ip_view1[i].sact);
874712b2f30Ssthen 		unit_assert(ip && sact);
875712b2f30Ssthen 		if(!cfg_str2list_insert(&cv1->respip_actions, ip, sact))
876712b2f30Ssthen 			unit_assert(0);
877712b2f30Ssthen 	}
878712b2f30Ssthen 	for(i=0; i<clen2; i++) {
879712b2f30Ssthen 		char* ip = strdup(config_response_ip_view2[i].ip);
880712b2f30Ssthen 		char* sact = strdup(config_response_ip_view2[i].sact);
881712b2f30Ssthen 		unit_assert(ip && sact);
882712b2f30Ssthen 		if(!cfg_str2list_insert(&cv2->respip_actions, ip, sact))
883712b2f30Ssthen 			unit_assert(0);
884712b2f30Ssthen 	}
885712b2f30Ssthen 	views = views_create();
886712b2f30Ssthen 	unit_assert(views);
887712b2f30Ssthen 	unit_assert(views_apply_cfg(views, &cfg));
888712b2f30Ssthen 	unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
889712b2f30Ssthen 
890712b2f30Ssthen 	/* now verify the respip sets in each view */
891712b2f30Ssthen 	v = views_find_view(views, "view1", 0);
892712b2f30Ssthen 	unit_assert(v);
893712b2f30Ssthen 	verify_respip_set_actions(v->respip_set, config_response_ip_view1, clen1);
894712b2f30Ssthen 	lock_rw_unlock(&v->lock);
895712b2f30Ssthen 	v = views_find_view(views, "view2", 0);
896712b2f30Ssthen 	unit_assert(v);
897712b2f30Ssthen 	verify_respip_set_actions(v->respip_set, config_response_ip_view2, clen2);
898712b2f30Ssthen 	lock_rw_unlock(&v->lock);
899712b2f30Ssthen 
900712b2f30Ssthen 	views_delete(views);
901712b2f30Ssthen 	free(cv1->name);
902712b2f30Ssthen 	free(cv1);
903712b2f30Ssthen 	free(cv2->name);
904712b2f30Ssthen 	free(cv2);
905712b2f30Ssthen }
906712b2f30Ssthen 
907712b2f30Ssthen typedef struct addr_data {char* ip; char* data;} addr_data_t;
908712b2f30Ssthen 
909712b2f30Ssthen /** find the respip address node in the specified tree (by address lookup)
910712b2f30Ssthen   * and verify type and address of the specified rdata (by index) in this
911712b2f30Ssthen   * node's rrset */
912712b2f30Ssthen static void
913712b2f30Ssthen verify_rrset(struct respip_set* set, const char* ipstr,
914712b2f30Ssthen 	const char* rdatastr, size_t rdi, uint16_t type)
915712b2f30Ssthen {
916712b2f30Ssthen 	struct sockaddr_storage addr;
917712b2f30Ssthen 	int net;
918712b2f30Ssthen 	char buf[65536];
919712b2f30Ssthen 	socklen_t addrlen;
920712b2f30Ssthen 	struct rbtree_type* tree;
921712b2f30Ssthen 	struct resp_addr* node;
922712b2f30Ssthen 	const struct ub_packed_rrset_key* rrs;
923712b2f30Ssthen 
924712b2f30Ssthen 	netblockstrtoaddr(ipstr, UNBOUND_DNS_PORT, &addr, &addrlen, &net);
925712b2f30Ssthen 	tree = respip_set_get_tree(set);
926712b2f30Ssthen 	node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
927712b2f30Ssthen 	unit_assert(node);
928712b2f30Ssthen 	unit_assert((rrs = resp_addr_get_rrset(node)));
929712b2f30Ssthen 	unit_assert(ntohs(rrs->rk.type) == type);
930712b2f30Ssthen 	packed_rr_to_string((struct ub_packed_rrset_key*)rrs,
931712b2f30Ssthen 		rdi, 0, buf, sizeof(buf));
932712b2f30Ssthen 	unit_assert(strstr(buf, rdatastr));
933712b2f30Ssthen }
934712b2f30Ssthen 
935712b2f30Ssthen /** Dataset used to test redirect rrset initialization for both
936712b2f30Ssthen   * global and per-view respip redirect configuration */
937712b2f30Ssthen static addr_data_t config_response_ip_data[] = {
938712b2f30Ssthen 	{"192.0.1.0/24", "A 1.2.3.4"},
939712b2f30Ssthen 	{"192.0.1.0/24", "A 11.12.13.14"},
940712b2f30Ssthen 	{"192.0.2.0/24", "CNAME www.example.com."},
941712b2f30Ssthen 	{"2001:db8:1::/48", "AAAA 2001:db8:1::2:1"},
942712b2f30Ssthen };
943712b2f30Ssthen 
944712b2f30Ssthen /** Populate raw respip redirect config data, used for both global and
945712b2f30Ssthen   * view-based respip redirect test case */
946712b2f30Ssthen static void
947712b2f30Ssthen cfg_insert_respip_data(struct config_str2list** respip_actions,
948712b2f30Ssthen 	struct config_str2list** respip_data)
949712b2f30Ssthen {
950712b2f30Ssthen 	int clen = (int)(sizeof(config_response_ip_data) / sizeof(addr_data_t));
951712b2f30Ssthen 	int i = 0;
952712b2f30Ssthen 
953712b2f30Ssthen 	/* insert actions (duplicate netblocks don't matter) */
954712b2f30Ssthen 	for(i=0; i<clen; i++) {
955712b2f30Ssthen 		char* ip = strdup(config_response_ip_data[i].ip);
956712b2f30Ssthen 		char* sact = strdup("redirect");
957712b2f30Ssthen 		unit_assert(ip && sact);
958712b2f30Ssthen 		if(!cfg_str2list_insert(respip_actions, ip, sact))
959712b2f30Ssthen 			unit_assert(0);
960712b2f30Ssthen 	}
961712b2f30Ssthen 	/* insert data */
962712b2f30Ssthen 	for(i=0; i<clen; i++) {
963712b2f30Ssthen 		char* ip = strdup(config_response_ip_data[i].ip);
964712b2f30Ssthen 		char* data = strdup(config_response_ip_data[i].data);
965712b2f30Ssthen 		unit_assert(ip && data);
966712b2f30Ssthen 		if(!cfg_str2list_insert(respip_data, ip, data))
967712b2f30Ssthen 			unit_assert(0);
968712b2f30Ssthen 	}
969712b2f30Ssthen }
970712b2f30Ssthen 
971712b2f30Ssthen /** Test global respip redirect w/ data directives */
972712b2f30Ssthen static void
973712b2f30Ssthen respip_conf_data_test(void)
974712b2f30Ssthen {
975712b2f30Ssthen 	struct respip_set* set = respip_set_create();
976712b2f30Ssthen 	struct config_file cfg;
977712b2f30Ssthen 
978712b2f30Ssthen 	unit_show_feature("global respip config data apply");
979712b2f30Ssthen 	memset(&cfg, 0, sizeof(cfg));
980712b2f30Ssthen 
981712b2f30Ssthen 	cfg_insert_respip_data(&cfg.respip_actions, &cfg.respip_data);
982712b2f30Ssthen 
983712b2f30Ssthen 	/* apply configuration and verify rrsets */
984712b2f30Ssthen 	unit_assert(respip_global_apply_cfg(set, &cfg));
985712b2f30Ssthen 	verify_rrset(set, "192.0.1.0/24", "1.2.3.4", 0, LDNS_RR_TYPE_A);
986712b2f30Ssthen 	verify_rrset(set, "192.0.1.0/24", "11.12.13.14", 1, LDNS_RR_TYPE_A);
987712b2f30Ssthen 	verify_rrset(set, "192.0.2.0/24", "www.example.com", 0, LDNS_RR_TYPE_CNAME);
988712b2f30Ssthen 	verify_rrset(set, "2001:db8:1::/48", "2001:db8:1::2:1", 0, LDNS_RR_TYPE_AAAA);
989712b2f30Ssthen 
990712b2f30Ssthen 	respip_set_delete(set);
991712b2f30Ssthen }
992712b2f30Ssthen 
993712b2f30Ssthen /** Test per-view respip redirect w/ data directives */
994712b2f30Ssthen static void
995712b2f30Ssthen respip_view_conf_data_test(void)
996712b2f30Ssthen {
997712b2f30Ssthen 	struct config_file cfg;
998712b2f30Ssthen 	struct config_view* cv;
999712b2f30Ssthen 	int have_respip_cfg = 0;
1000712b2f30Ssthen 	struct views* views = NULL;
1001712b2f30Ssthen 	struct view* v = NULL;
1002712b2f30Ssthen 
1003712b2f30Ssthen 	unit_show_feature("per-view respip config data apply");
1004712b2f30Ssthen 	memset(&cfg, 0, sizeof(cfg));
1005712b2f30Ssthen 	cv = (struct config_view*)calloc(1, sizeof(struct config_view));
1006712b2f30Ssthen 	unit_assert(cv);
1007712b2f30Ssthen 	cv->name = strdup("view1");
1008712b2f30Ssthen 	unit_assert(cv->name);
1009712b2f30Ssthen 	cfg.views = cv;
1010712b2f30Ssthen 	cfg_insert_respip_data(&cv->respip_actions, &cv->respip_data);
1011712b2f30Ssthen 	views = views_create();
1012712b2f30Ssthen 	unit_assert(views);
1013712b2f30Ssthen 	unit_assert(views_apply_cfg(views, &cfg));
1014712b2f30Ssthen 
1015712b2f30Ssthen 	/* apply configuration and verify rrsets */
1016712b2f30Ssthen 	unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
1017712b2f30Ssthen 	v = views_find_view(views, "view1", 0);
1018712b2f30Ssthen 	unit_assert(v);
1019712b2f30Ssthen 	verify_rrset(v->respip_set, "192.0.1.0/24", "1.2.3.4",
1020712b2f30Ssthen 		0, LDNS_RR_TYPE_A);
1021712b2f30Ssthen 	verify_rrset(v->respip_set, "192.0.1.0/24", "11.12.13.14",
1022712b2f30Ssthen 		1, LDNS_RR_TYPE_A);
1023712b2f30Ssthen 	verify_rrset(v->respip_set, "192.0.2.0/24", "www.example.com",
1024712b2f30Ssthen 		0, LDNS_RR_TYPE_CNAME);
1025712b2f30Ssthen 	verify_rrset(v->respip_set, "2001:db8:1::/48", "2001:db8:1::2:1",
1026712b2f30Ssthen 		0, LDNS_RR_TYPE_AAAA);
1027712b2f30Ssthen 	lock_rw_unlock(&v->lock);
1028712b2f30Ssthen 
1029712b2f30Ssthen 	views_delete(views);
1030712b2f30Ssthen 	free(cv->name);
1031712b2f30Ssthen 	free(cv);
1032712b2f30Ssthen }
1033712b2f30Ssthen 
1034712b2f30Ssthen /** respip unit tests */
1035712b2f30Ssthen static void respip_test(void)
1036712b2f30Ssthen {
1037712b2f30Ssthen 	respip_view_conf_data_test();
1038712b2f30Ssthen 	respip_conf_data_test();
1039712b2f30Ssthen 	respip_view_conf_actions_test();
1040712b2f30Ssthen 	respip_conf_actions_test();
1041712b2f30Ssthen }
1042712b2f30Ssthen 
1043437d2860Ssthen #include "util/regional.h"
1044437d2860Ssthen #include "sldns/sbuffer.h"
1045437d2860Ssthen #include "util/data/dname.h"
1046437d2860Ssthen #include "util/data/msgreply.h"
1047437d2860Ssthen #include "util/data/msgencode.h"
1048437d2860Ssthen #include "sldns/str2wire.h"
1049437d2860Ssthen 
1050437d2860Ssthen static void edns_ede_encode_setup(struct edns_data* edns,
1051437d2860Ssthen 	struct regional* region)
1052437d2860Ssthen {
1053437d2860Ssthen 	memset(edns, 0, sizeof(*edns));
1054437d2860Ssthen 	edns->edns_present = 1;
1055437d2860Ssthen 	edns->edns_version = EDNS_ADVERTISED_VERSION;
1056437d2860Ssthen 	edns->udp_size = EDNS_ADVERTISED_SIZE;
1057437d2860Ssthen 	edns->bits &= EDNS_DO;
1058437d2860Ssthen 	/* Fill up opt_list_out with EDEs */
1059437d2860Ssthen 	unit_assert(
1060437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_out, region,
1061437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1062437d2860Ssthen 	unit_assert(
1063437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_out, region,
1064437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1065437d2860Ssthen 	unit_assert(
1066437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_out, region,
1067437d2860Ssthen 		LDNS_EDE_BLOCKED, "Too long blocked text"));
1068437d2860Ssthen 	unit_assert(
1069437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_out, region,
1070437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1071437d2860Ssthen 	unit_assert(
1072437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_out, region,
1073437d2860Ssthen 		LDNS_EDE_BLOCKED, "Too long blocked text"));
1074437d2860Ssthen 	/* Fill up opt_list_inplace_cb_out with EDEs */
1075437d2860Ssthen 	unit_assert(
1076437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_inplace_cb_out, region,
1077437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1078437d2860Ssthen 	unit_assert(
1079437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_inplace_cb_out, region,
1080437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1081437d2860Ssthen 	unit_assert(
1082437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_inplace_cb_out, region,
1083437d2860Ssthen 		LDNS_EDE_BLOCKED, "Too long blocked text"));
1084437d2860Ssthen 	unit_assert(
1085437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_inplace_cb_out, region,
1086437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1087437d2860Ssthen 	unit_assert(
1088437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_inplace_cb_out, region,
1089437d2860Ssthen 		LDNS_EDE_BLOCKED, "Too long blocked text"));
1090437d2860Ssthen 	/* append another EDNS option to both lists */
1091437d2860Ssthen 	unit_assert(
1092437d2860Ssthen 		edns_opt_list_append(&edns->opt_list_out,
1093437d2860Ssthen 		LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST, 0, NULL, region));
1094437d2860Ssthen 	unit_assert(
1095437d2860Ssthen 		edns_opt_list_append(&edns->opt_list_inplace_cb_out,
1096437d2860Ssthen 		LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST, 0, NULL, region));
1097437d2860Ssthen 	/* append LDNS_EDE_OTHER at the end of both lists */
1098437d2860Ssthen 	unit_assert(
1099437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_out, region,
1100437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1101437d2860Ssthen 	unit_assert(
1102437d2860Ssthen 		edns_opt_list_append_ede(&edns->opt_list_inplace_cb_out, region,
1103437d2860Ssthen 		LDNS_EDE_OTHER, "Too long other text"));
1104437d2860Ssthen }
1105437d2860Ssthen 
1106437d2860Ssthen static void edns_ede_encode_encodedecode(struct query_info* qinfo,
1107437d2860Ssthen 	struct reply_info* rep, struct regional* region,
1108437d2860Ssthen 	struct edns_data* edns, sldns_buffer* pkt)
1109437d2860Ssthen {
1110437d2860Ssthen 	/* encode */
1111437d2860Ssthen 	unit_assert(
1112437d2860Ssthen 		reply_info_answer_encode(qinfo, rep, 1, rep->flags, pkt,
1113437d2860Ssthen 		0, 0, region, 65535, edns, 0, 0));
1114437d2860Ssthen 	/* buffer ready for reading; skip after the question section */
1115437d2860Ssthen 	sldns_buffer_skip(pkt, LDNS_HEADER_SIZE);
1116437d2860Ssthen 	(void)query_dname_len(pkt);
1117437d2860Ssthen 	sldns_buffer_skip(pkt, 2 + 2);
1118437d2860Ssthen 	/* decode */
1119437d2860Ssthen 	unit_assert(parse_edns_from_query_pkt(pkt, edns, NULL, NULL, NULL, 0,
1120*a43524d9Ssthen 		region, NULL) == 0);
1121437d2860Ssthen }
1122437d2860Ssthen 
1123437d2860Ssthen static void edns_ede_encode_check(struct edns_data* edns, int* found_ede,
1124437d2860Ssthen 	int* found_ede_other, int* found_ede_txt, int* found_other_edns)
1125437d2860Ssthen {
1126437d2860Ssthen 	struct edns_option* opt;
1127437d2860Ssthen 	for(opt = edns->opt_list_in; opt; opt = opt->next) {
1128437d2860Ssthen 		if(opt->opt_code == LDNS_EDNS_EDE) {
1129437d2860Ssthen 			(*found_ede)++;
1130437d2860Ssthen 			if(opt->opt_len > 2)
1131437d2860Ssthen 				(*found_ede_txt)++;
1132437d2860Ssthen 			if(opt->opt_len >= 2 && sldns_read_uint16(
1133437d2860Ssthen 				opt->opt_data) == LDNS_EDE_OTHER)
1134437d2860Ssthen 				(*found_ede_other)++;
1135437d2860Ssthen 		} else {
1136437d2860Ssthen 			(*found_other_edns)++;
1137437d2860Ssthen 		}
1138437d2860Ssthen 	}
1139437d2860Ssthen 
1140437d2860Ssthen }
1141437d2860Ssthen 
1142437d2860Ssthen static void edns_ede_encode_fit_test(struct query_info* qinfo,
1143437d2860Ssthen 	struct reply_info* rep, struct regional* region)
1144437d2860Ssthen {
1145437d2860Ssthen 	struct edns_data edns;
1146437d2860Ssthen 	int found_ede = 0, found_ede_other = 0, found_ede_txt = 0;
1147437d2860Ssthen 	int found_other_edns = 0;
1148437d2860Ssthen 	sldns_buffer* pkt = sldns_buffer_new(65535);
1149437d2860Ssthen 	unit_assert(pkt);
1150437d2860Ssthen 	edns_ede_encode_setup(&edns, region);
1151437d2860Ssthen 	/* leave the pkt buffer as is; everything should fit */
1152437d2860Ssthen 	edns_ede_encode_encodedecode(qinfo, rep, region, &edns, pkt);
1153437d2860Ssthen 	edns_ede_encode_check(&edns, &found_ede, &found_ede_other,
1154437d2860Ssthen 		&found_ede_txt, &found_other_edns);
1155437d2860Ssthen 	unit_assert(found_ede == 12);
1156437d2860Ssthen 	unit_assert(found_ede_other == 8);
1157437d2860Ssthen 	unit_assert(found_ede_txt == 12);
1158437d2860Ssthen 	unit_assert(found_other_edns == 2);
1159437d2860Ssthen 	/* cleanup */
1160437d2860Ssthen 	sldns_buffer_free(pkt);
1161437d2860Ssthen }
1162437d2860Ssthen 
1163437d2860Ssthen static void edns_ede_encode_notxt_fit_test( struct query_info* qinfo,
1164437d2860Ssthen 	struct reply_info* rep, struct regional* region)
1165437d2860Ssthen {
1166437d2860Ssthen 	struct edns_data edns;
1167437d2860Ssthen 	sldns_buffer* pkt;
1168437d2860Ssthen 	uint16_t edns_field_size, ede_txt_size;
1169437d2860Ssthen 	int found_ede = 0, found_ede_other = 0, found_ede_txt = 0;
1170437d2860Ssthen 	int found_other_edns = 0;
1171437d2860Ssthen 	edns_ede_encode_setup(&edns, region);
1172437d2860Ssthen 	/* pkt buffer should fit everything if the ede txt is cropped.
1173437d2860Ssthen 	 * OTHER EDE should not be there since it is useless without text. */
1174437d2860Ssthen 	edns_field_size = calc_edns_field_size(&edns);
1175437d2860Ssthen 	(void)calc_ede_option_size(&edns, &ede_txt_size);
1176437d2860Ssthen 	pkt = sldns_buffer_new(LDNS_HEADER_SIZE
1177437d2860Ssthen 		+ qinfo->qname_len
1178437d2860Ssthen 		+ 2 + 2 /* qtype + qclass */
1179437d2860Ssthen 		+ 11 /* opt record */
1180437d2860Ssthen 		+ edns_field_size
1181437d2860Ssthen 		- ede_txt_size);
1182437d2860Ssthen 	unit_assert(pkt);
1183437d2860Ssthen 	edns_ede_encode_encodedecode(qinfo, rep, region, &edns, pkt);
1184437d2860Ssthen 	edns_ede_encode_check(&edns, &found_ede, &found_ede_other,
1185437d2860Ssthen 		&found_ede_txt, &found_other_edns);
1186437d2860Ssthen 	unit_assert(found_ede == 4);
1187437d2860Ssthen 	unit_assert(found_ede_other == 0);
1188437d2860Ssthen 	unit_assert(found_ede_txt == 0);
1189437d2860Ssthen 	unit_assert(found_other_edns == 2);
1190437d2860Ssthen 	/* cleanup */
1191437d2860Ssthen 	sldns_buffer_free(pkt);
1192437d2860Ssthen }
1193437d2860Ssthen 
1194437d2860Ssthen static void edns_ede_encode_no_fit_test( struct query_info* qinfo,
1195437d2860Ssthen 	struct reply_info* rep, struct regional* region)
1196437d2860Ssthen {
1197437d2860Ssthen 	struct edns_data edns;
1198437d2860Ssthen 	sldns_buffer* pkt;
1199437d2860Ssthen 	uint16_t edns_field_size, ede_size, ede_txt_size;
1200437d2860Ssthen 	int found_ede = 0, found_ede_other = 0, found_ede_txt = 0;
1201437d2860Ssthen 	int found_other_edns = 0;
1202437d2860Ssthen 	edns_ede_encode_setup(&edns, region);
1203437d2860Ssthen 	/* pkt buffer should fit only non-EDE options. */
1204437d2860Ssthen 	edns_field_size = calc_edns_field_size(&edns);
1205437d2860Ssthen 	ede_size = calc_ede_option_size(&edns, &ede_txt_size);
1206437d2860Ssthen 	pkt = sldns_buffer_new(LDNS_HEADER_SIZE
1207437d2860Ssthen 		+ qinfo->qname_len
1208437d2860Ssthen 		+ 2 + 2 /* qtype + qclass */
1209437d2860Ssthen 		+ 11 /* opt record */
1210437d2860Ssthen 		+ edns_field_size
1211437d2860Ssthen 		- ede_size);
1212437d2860Ssthen 	unit_assert(pkt);
1213437d2860Ssthen 	edns_ede_encode_encodedecode(qinfo, rep, region, &edns, pkt);
1214437d2860Ssthen 	edns_ede_encode_check(&edns, &found_ede, &found_ede_other,
1215437d2860Ssthen 		&found_ede_txt, &found_other_edns);
1216437d2860Ssthen 	unit_assert(found_ede == 0);
1217437d2860Ssthen 	unit_assert(found_ede_other == 0);
1218437d2860Ssthen 	unit_assert(found_ede_txt == 0);
1219437d2860Ssthen 	unit_assert(found_other_edns == 2);
1220437d2860Ssthen 	/* cleanup */
1221437d2860Ssthen 	sldns_buffer_free(pkt);
1222437d2860Ssthen }
1223437d2860Ssthen 
1224437d2860Ssthen /** test optional EDE encoding with various buffer
1225437d2860Ssthen  *  available sizes */
1226437d2860Ssthen static void edns_ede_answer_encode_test(void)
1227437d2860Ssthen {
1228437d2860Ssthen 	struct regional* region = regional_create();
1229437d2860Ssthen 	struct reply_info* rep;
1230437d2860Ssthen 	struct query_info qinfo;
1231437d2860Ssthen 	unit_show_feature("edns ede optional encoding");
1232437d2860Ssthen 	unit_assert(region);
1233437d2860Ssthen 	rep = construct_reply_info_base(region,
1234437d2860Ssthen 		LDNS_RCODE_NOERROR | BIT_QR, 1,
1235437d2860Ssthen 		3600, 3600, 3600,
1236437d2860Ssthen 		0, 0, 0, 0,
1237437d2860Ssthen 		sec_status_unchecked, LDNS_EDE_NONE);
1238437d2860Ssthen 	unit_assert(rep);
1239437d2860Ssthen 	memset(&qinfo, 0, sizeof(qinfo));
1240437d2860Ssthen 	qinfo.qname = sldns_str2wire_dname("encode.ede.", &qinfo.qname_len);
1241437d2860Ssthen 	unit_assert(qinfo.qname);
1242437d2860Ssthen 	qinfo.qtype = LDNS_RR_TYPE_TXT;
1243437d2860Ssthen 	qinfo.qclass = LDNS_RR_CLASS_IN;
1244437d2860Ssthen 
1245437d2860Ssthen 	edns_ede_encode_fit_test(&qinfo, rep, region);
1246437d2860Ssthen 	edns_ede_encode_notxt_fit_test(&qinfo, rep, region);
1247437d2860Ssthen 	edns_ede_encode_no_fit_test(&qinfo, rep, region);
1248437d2860Ssthen 
1249437d2860Ssthen 	/* cleanup */
1250437d2860Ssthen 	free(qinfo.qname);
1251437d2860Ssthen 	regional_free_all(region);
1252437d2860Ssthen 	regional_destroy(region);
1253437d2860Ssthen }
1254437d2860Ssthen 
1255*a43524d9Ssthen #include "services/localzone.h"
1256*a43524d9Ssthen /* Utility function that compares two localzone trees */
1257*a43524d9Ssthen static void compare_localzone_trees(struct local_zones* z1,
1258*a43524d9Ssthen 	struct local_zones* z2)
1259*a43524d9Ssthen {
1260*a43524d9Ssthen 	struct local_zone *node1, *node2;
1261*a43524d9Ssthen 	lock_rw_rdlock(&z1->lock);
1262*a43524d9Ssthen 	lock_rw_rdlock(&z2->lock);
1263*a43524d9Ssthen 	/* size should be the same */
1264*a43524d9Ssthen 	unit_assert(z1->ztree.count == z2->ztree.count);
1265*a43524d9Ssthen 	for(node1=(struct local_zone*)rbtree_first(&z1->ztree),
1266*a43524d9Ssthen 		node2=(struct local_zone*)rbtree_first(&z2->ztree);
1267*a43524d9Ssthen 		(rbnode_type*)node1 != RBTREE_NULL &&
1268*a43524d9Ssthen 		(rbnode_type*)node2 != RBTREE_NULL;
1269*a43524d9Ssthen 		node1=(struct local_zone*)rbtree_next((rbnode_type*)node1),
1270*a43524d9Ssthen 		node2=(struct local_zone*)rbtree_next((rbnode_type*)node2)) {
1271*a43524d9Ssthen 		int labs;
1272*a43524d9Ssthen 		/* the same zone should be at the same nodes */
1273*a43524d9Ssthen 		unit_assert(!dname_lab_cmp(
1274*a43524d9Ssthen 			node1->name, node1->namelabs,
1275*a43524d9Ssthen 			node2->name, node2->namelabs,
1276*a43524d9Ssthen 			&labs));
1277*a43524d9Ssthen 		/* the zone's parent should be the same on both nodes */
1278*a43524d9Ssthen 		unit_assert(
1279*a43524d9Ssthen 			(node1->parent == NULL && node2->parent == NULL) ||
1280*a43524d9Ssthen 			(node1->parent != NULL && node2->parent != NULL));
1281*a43524d9Ssthen 		if(node1->parent) {
1282*a43524d9Ssthen 			unit_assert(!dname_lab_cmp(
1283*a43524d9Ssthen 				node1->parent->name, node1->parent->namelabs,
1284*a43524d9Ssthen 				node2->parent->name, node2->parent->namelabs,
1285*a43524d9Ssthen 				&labs));
1286*a43524d9Ssthen 		}
1287*a43524d9Ssthen 	}
1288*a43524d9Ssthen 	lock_rw_unlock(&z1->lock);
1289*a43524d9Ssthen 	lock_rw_unlock(&z2->lock);
1290*a43524d9Ssthen }
1291*a43524d9Ssthen 
1292*a43524d9Ssthen /* test that zone addition results in the same tree from both the configuration
1293*a43524d9Ssthen  * file and the unbound-control commands */
1294*a43524d9Ssthen static void localzone_parents_test(void)
1295*a43524d9Ssthen {
1296*a43524d9Ssthen 	struct local_zones *z1, *z2;
1297*a43524d9Ssthen 	size_t i;
1298*a43524d9Ssthen 	char* zone_data[] = {
1299*a43524d9Ssthen 		"one",
1300*a43524d9Ssthen 		"a.b.c.one",
1301*a43524d9Ssthen 		"b.c.one",
1302*a43524d9Ssthen 		"c.one",
1303*a43524d9Ssthen 		"two",
1304*a43524d9Ssthen 		"c.two",
1305*a43524d9Ssthen 		"b.c.two",
1306*a43524d9Ssthen 		"a.b.c.two",
1307*a43524d9Ssthen 		"a.b.c.three",
1308*a43524d9Ssthen 		"b.c.three",
1309*a43524d9Ssthen 		"c.three",
1310*a43524d9Ssthen 		"three",
1311*a43524d9Ssthen 		"c.four",
1312*a43524d9Ssthen 		"b.c.four",
1313*a43524d9Ssthen 		"a.b.c.four",
1314*a43524d9Ssthen 		"four",
1315*a43524d9Ssthen 		"."
1316*a43524d9Ssthen 	};
1317*a43524d9Ssthen 	unit_show_feature("localzones parent calculation");
1318*a43524d9Ssthen 	z1 = local_zones_create();
1319*a43524d9Ssthen 	z2 = local_zones_create();
1320*a43524d9Ssthen 	/* parse test data */
1321*a43524d9Ssthen 	for(i=0; i<sizeof(zone_data)/sizeof(zone_data[0]); i++) {
1322*a43524d9Ssthen 		uint8_t* nm;
1323*a43524d9Ssthen 		int nmlabs;
1324*a43524d9Ssthen 		size_t nmlen;
1325*a43524d9Ssthen 		struct local_zone* z;
1326*a43524d9Ssthen 
1327*a43524d9Ssthen 		/* This is the config way */
1328*a43524d9Ssthen 		z = lz_enter_zone(z1, zone_data[i], "always_nxdomain",
1329*a43524d9Ssthen 			LDNS_RR_CLASS_IN);
1330*a43524d9Ssthen 		(void)z;  /* please compiler when no threading and no lock
1331*a43524d9Ssthen 		code; the following line disappears and z stays unused */
1332*a43524d9Ssthen 		lock_rw_unlock(&z->lock);
1333*a43524d9Ssthen 		lz_init_parents(z1);
1334*a43524d9Ssthen 
1335*a43524d9Ssthen 		/* This is the unbound-control way */
1336*a43524d9Ssthen 		nm = sldns_str2wire_dname(zone_data[i], &nmlen);
1337*a43524d9Ssthen 		if(!nm) unit_assert(0);
1338*a43524d9Ssthen 		nmlabs = dname_count_size_labels(nm, &nmlen);
1339*a43524d9Ssthen 		lock_rw_wrlock(&z2->lock);
1340*a43524d9Ssthen 		local_zones_add_zone(z2, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN,
1341*a43524d9Ssthen 			local_zone_always_nxdomain);
1342*a43524d9Ssthen 		lock_rw_unlock(&z2->lock);
1343*a43524d9Ssthen 	}
1344*a43524d9Ssthen 	/* The trees should be the same, iterate and check the nodes */
1345*a43524d9Ssthen 	compare_localzone_trees(z1, z2);
1346*a43524d9Ssthen 
1347*a43524d9Ssthen 	/* cleanup */
1348*a43524d9Ssthen 	local_zones_delete(z1);
1349*a43524d9Ssthen 	local_zones_delete(z2);
1350*a43524d9Ssthen }
1351*a43524d9Ssthen 
1352*a43524d9Ssthen /** localzone unit tests */
1353*a43524d9Ssthen static void localzone_test(void)
1354*a43524d9Ssthen {
1355*a43524d9Ssthen 	localzone_parents_test();
1356*a43524d9Ssthen }
1357*a43524d9Ssthen 
1358712b2f30Ssthen void unit_show_func(const char* file, const char* func)
1359712b2f30Ssthen {
1360712b2f30Ssthen 	printf("test %s:%s\n", file, func);
1361712b2f30Ssthen }
1362712b2f30Ssthen 
1363712b2f30Ssthen void unit_show_feature(const char* feature)
1364712b2f30Ssthen {
1365712b2f30Ssthen 	printf("test %s functions\n", feature);
1366712b2f30Ssthen }
1367712b2f30Ssthen 
1368712b2f30Ssthen #ifdef USE_ECDSA_EVP_WORKAROUND
1369712b2f30Ssthen void ecdsa_evp_workaround_init(void);
1370712b2f30Ssthen #endif
1371437d2860Ssthen 
1372712b2f30Ssthen /**
1373712b2f30Ssthen  * Main unit test program. Setup, teardown and report errors.
1374712b2f30Ssthen  * @param argc: arg count.
1375712b2f30Ssthen  * @param argv: array of commandline arguments.
1376712b2f30Ssthen  * @return program failure if test fails.
1377712b2f30Ssthen  */
1378712b2f30Ssthen int
1379712b2f30Ssthen main(int argc, char* argv[])
1380712b2f30Ssthen {
138183152a15Ssthen 	checklock_start();
1382712b2f30Ssthen 	log_init(NULL, 0, NULL);
1383712b2f30Ssthen 	if(argc != 1) {
1384712b2f30Ssthen 		printf("usage: %s\n", argv[0]);
1385712b2f30Ssthen 		printf("\tperforms unit tests.\n");
1386712b2f30Ssthen 		return 1;
1387712b2f30Ssthen 	}
1388d7b4a113Ssthen 	/* Disable roundrobin for the unit tests */
1389d7b4a113Ssthen 	RRSET_ROUNDROBIN = 0;
1390d7b4a113Ssthen #ifdef USE_LIBEVENT
1391d7b4a113Ssthen 	printf("Start of %s+libevent unit test.\n", PACKAGE_STRING);
1392d7b4a113Ssthen #else
1393712b2f30Ssthen 	printf("Start of %s unit test.\n", PACKAGE_STRING);
1394d7b4a113Ssthen #endif
1395712b2f30Ssthen #ifdef HAVE_SSL
1396712b2f30Ssthen #  ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
1397712b2f30Ssthen 	ERR_load_crypto_strings();
1398712b2f30Ssthen #  endif
1399712b2f30Ssthen #  ifdef USE_GOST
1400712b2f30Ssthen 	(void)sldns_key_EVP_load_gost_id();
1401712b2f30Ssthen #  endif
1402712b2f30Ssthen #  ifdef USE_ECDSA_EVP_WORKAROUND
1403712b2f30Ssthen 	ecdsa_evp_workaround_init();
1404712b2f30Ssthen #  endif
1405712b2f30Ssthen #elif defined(HAVE_NSS)
1406712b2f30Ssthen 	if(NSS_NoDB_Init(".") != SECSuccess)
1407712b2f30Ssthen 		fatal_exit("could not init NSS");
1408712b2f30Ssthen #endif /* HAVE_SSL or HAVE_NSS*/
1409712b2f30Ssthen 	authzone_test();
1410712b2f30Ssthen 	neg_test();
1411712b2f30Ssthen 	rnd_test();
1412712b2f30Ssthen 	respip_test();
1413712b2f30Ssthen 	verify_test();
1414712b2f30Ssthen 	net_test();
1415712b2f30Ssthen 	config_memsize_test();
1416712b2f30Ssthen 	config_tag_test();
1417712b2f30Ssthen 	dname_test();
1418712b2f30Ssthen 	rtt_test();
1419712b2f30Ssthen 	anchors_test();
1420712b2f30Ssthen 	alloc_test();
1421712b2f30Ssthen 	regional_test();
1422712b2f30Ssthen 	lruhash_test();
1423712b2f30Ssthen 	slabhash_test();
1424712b2f30Ssthen 	infra_test();
1425712b2f30Ssthen 	ldns_test();
1426437d2860Ssthen 	edns_cookie_test();
1427a6cc1574Ssthen 	zonemd_test();
1428a6cc1574Ssthen 	tcpreuse_test();
1429712b2f30Ssthen 	msgparse_test();
1430437d2860Ssthen 	edns_ede_answer_encode_test();
1431*a43524d9Ssthen 	localzone_test();
1432712b2f30Ssthen #ifdef CLIENT_SUBNET
1433712b2f30Ssthen 	ecs_test();
1434712b2f30Ssthen #endif /* CLIENT_SUBNET */
1435712b2f30Ssthen 	if(log_get_lock()) {
1436b0dfc31bSsthen 		lock_basic_destroy((lock_basic_type*)log_get_lock());
1437712b2f30Ssthen 	}
1438712b2f30Ssthen 	checklock_stop();
1439712b2f30Ssthen 	printf("%d checks ok.\n", testcount);
1440712b2f30Ssthen #ifdef HAVE_SSL
14411996a427Ssthen #  if defined(USE_GOST)
1442712b2f30Ssthen 	sldns_key_EVP_unload_gost();
1443712b2f30Ssthen #  endif
1444712b2f30Ssthen #  ifdef HAVE_OPENSSL_CONFIG
1445712b2f30Ssthen #  ifdef HAVE_EVP_CLEANUP
1446712b2f30Ssthen 	EVP_cleanup();
1447712b2f30Ssthen #  endif
1448d7b4a113Ssthen #  if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE) && defined(HAVE_ENGINE_CLEANUP)
1449712b2f30Ssthen 	ENGINE_cleanup();
1450d7b4a113Ssthen #  endif
1451712b2f30Ssthen 	CONF_modules_free();
1452712b2f30Ssthen #  endif
1453712b2f30Ssthen #  ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
1454712b2f30Ssthen 	CRYPTO_cleanup_all_ex_data();
1455712b2f30Ssthen #  endif
1456712b2f30Ssthen #  ifdef HAVE_ERR_FREE_STRINGS
1457712b2f30Ssthen 	ERR_free_strings();
1458712b2f30Ssthen #  endif
1459712b2f30Ssthen #  ifdef HAVE_RAND_CLEANUP
1460712b2f30Ssthen 	RAND_cleanup();
1461712b2f30Ssthen #  endif
1462712b2f30Ssthen #elif defined(HAVE_NSS)
1463712b2f30Ssthen 	if(NSS_Shutdown() != SECSuccess)
1464712b2f30Ssthen 		fatal_exit("could not shutdown NSS");
1465712b2f30Ssthen #endif /* HAVE_SSL or HAVE_NSS */
1466712b2f30Ssthen #ifdef HAVE_PTHREAD
1467712b2f30Ssthen 	/* dlopen frees its thread specific state */
1468712b2f30Ssthen 	pthread_exit(NULL);
1469712b2f30Ssthen #endif
1470712b2f30Ssthen 	return 0;
1471712b2f30Ssthen }
1472