Home | History | Annotate | Line # | Download | only in dns
dbversion_test.c revision 1.2.4.2
      1 /*	$NetBSD: dbversion_test.c,v 1.2.4.2 2024/02/29 12:35:38 martin 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 <stddef.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <unistd.h>
     24 
     25 #define UNIT_TESTING
     26 #include <cmocka.h>
     27 
     28 #include <isc/file.h>
     29 #include <isc/result.h>
     30 #include <isc/serial.h>
     31 #include <isc/stdtime.h>
     32 #include <isc/string.h>
     33 #include <isc/util.h>
     34 
     35 #include <dns/db.h>
     36 #include <dns/nsec3.h>
     37 #include <dns/rdatalist.h>
     38 #include <dns/rdataset.h>
     39 #include <dns/rdatasetiter.h>
     40 
     41 #include <tests/dns.h>
     42 
     43 static char tempname[11] = "dtXXXXXXXX";
     44 static dns_db_t *db1 = NULL, *db2 = NULL;
     45 static dns_dbversion_t *v1 = NULL, *v2 = NULL;
     46 
     47 /*
     48  * The code below enables us to trap assertion failures for testing
     49  * purposes. local_callback() is set as the callback function for
     50  * isc_assertion_failed(). It calls mock_assert() so that CMOCKA
     51  * will be able to see it, then returns to the calling function via
     52  * longjmp() so that the abort() call in isc_assertion_failed() will
     53  * never be reached. Use check_assertion() to check for assertions
     54  * instead of expect_assert_failure().
     55  */
     56 jmp_buf assertion;
     57 
     58 #define check_assertion(function_call)                        \
     59 	do {                                                  \
     60 		const int r = setjmp(assertion);              \
     61 		if (r == 0) {                                 \
     62 			expect_assert_failure(function_call); \
     63 		}                                             \
     64 	} while (false);
     65 
     66 static void
     67 local_callback(const char *file, int line, isc_assertiontype_t type,
     68 	       const char *cond) {
     69 	UNUSED(type);
     70 
     71 	mock_assert(1, cond, file, line);
     72 	longjmp(assertion, 1);
     73 }
     74 
     75 static int
     76 setup_test(void **state) {
     77 	isc_result_t res;
     78 
     79 	UNUSED(state);
     80 
     81 	isc_assertion_setcallback(local_callback);
     82 
     83 	res = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
     84 			    dns_rdataclass_in, 0, NULL, &db1);
     85 	assert_int_equal(res, ISC_R_SUCCESS);
     86 	dns_db_newversion(db1, &v1);
     87 	assert_non_null(v1);
     88 
     89 	res = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
     90 			    dns_rdataclass_in, 0, NULL, &db2);
     91 	assert_int_equal(res, ISC_R_SUCCESS);
     92 	dns_db_newversion(db2, &v2);
     93 	assert_non_null(v1);
     94 
     95 	return (0);
     96 }
     97 
     98 static int
     99 teardown_test(void **state) {
    100 	UNUSED(state);
    101 
    102 	if (strcmp(tempname, "dtXXXXXXXX") != 0) {
    103 		unlink(tempname);
    104 	}
    105 
    106 	if (v1 != NULL) {
    107 		dns_db_closeversion(db1, &v1, false);
    108 		assert_null(v1);
    109 	}
    110 	if (db1 != NULL) {
    111 		dns_db_detach(&db1);
    112 		assert_null(db1);
    113 	}
    114 
    115 	if (v2 != NULL) {
    116 		dns_db_closeversion(db2, &v2, false);
    117 		assert_null(v2);
    118 	}
    119 	if (db2 != NULL) {
    120 		dns_db_detach(&db2);
    121 		assert_null(db2);
    122 	}
    123 
    124 	return (0);
    125 }
    126 
    127 /*
    128  * Check dns_db_attachversion() passes with matching db and version, and
    129  * asserts with mis-matching db and version.
    130  */
    131 ISC_RUN_TEST_IMPL(attachversion) {
    132 	dns_dbversion_t *v = NULL;
    133 
    134 	UNUSED(state);
    135 
    136 	dns_db_attachversion(db1, v1, &v);
    137 	assert_ptr_equal(v, v1);
    138 	dns_db_closeversion(db1, &v, false);
    139 	assert_null(v);
    140 
    141 	check_assertion(dns_db_attachversion(db1, v2, &v));
    142 }
    143 
    144 /*
    145  * Check dns_db_closeversion() passes with matching db and version, and
    146  * asserts with mis-matching db and version.
    147  */
    148 ISC_RUN_TEST_IMPL(closeversion) {
    149 	UNUSED(state);
    150 
    151 	assert_non_null(v1);
    152 	dns_db_closeversion(db1, &v1, false);
    153 	assert_null(v1);
    154 
    155 	check_assertion(dns_db_closeversion(db1, &v2, false));
    156 }
    157 
    158 /*
    159  * Check dns_db_find() passes with matching db and version, and
    160  * asserts with mis-matching db and version.
    161  */
    162 ISC_RUN_TEST_IMPL(find) {
    163 	isc_result_t res;
    164 	dns_rdataset_t rdataset;
    165 	dns_fixedname_t fixed;
    166 	dns_name_t *name = NULL;
    167 
    168 	UNUSED(state);
    169 
    170 	name = dns_fixedname_initname(&fixed);
    171 
    172 	dns_rdataset_init(&rdataset);
    173 	res = dns_db_find(db1, dns_rootname, v1, dns_rdatatype_soa, 0, 0, NULL,
    174 			  name, &rdataset, NULL);
    175 	assert_int_equal(res, DNS_R_NXDOMAIN);
    176 
    177 	if (dns_rdataset_isassociated(&rdataset)) {
    178 		dns_rdataset_disassociate(&rdataset);
    179 	}
    180 
    181 	dns_rdataset_init(&rdataset);
    182 	check_assertion((void)dns_db_find(db1, dns_rootname, v2,
    183 					  dns_rdatatype_soa, 0, 0, NULL, name,
    184 					  &rdataset, NULL));
    185 }
    186 
    187 /*
    188  * Check dns_db_allrdatasets() passes with matching db and version, and
    189  * asserts with mis-matching db and version.
    190  */
    191 ISC_RUN_TEST_IMPL(allrdatasets) {
    192 	isc_result_t res;
    193 	dns_dbnode_t *node = NULL;
    194 	dns_rdatasetiter_t *iterator = NULL;
    195 
    196 	UNUSED(state);
    197 
    198 	res = dns_db_findnode(db1, dns_rootname, false, &node);
    199 	assert_int_equal(res, ISC_R_SUCCESS);
    200 
    201 	res = dns_db_allrdatasets(db1, node, v1, 0, 0, &iterator);
    202 	assert_int_equal(res, ISC_R_SUCCESS);
    203 
    204 	check_assertion(dns_db_allrdatasets(db1, node, v2, 0, 0, &iterator));
    205 
    206 	dns_rdatasetiter_destroy(&iterator);
    207 	assert_null(iterator);
    208 
    209 	dns_db_detachnode(db1, &node);
    210 	assert_null(node);
    211 }
    212 
    213 /*
    214  * Check dns_db_findrdataset() passes with matching db and version, and
    215  * asserts with mis-matching db and version.
    216  */
    217 ISC_RUN_TEST_IMPL(findrdataset) {
    218 	isc_result_t res;
    219 	dns_rdataset_t rdataset;
    220 	dns_dbnode_t *node = NULL;
    221 
    222 	UNUSED(state);
    223 
    224 	res = dns_db_findnode(db1, dns_rootname, false, &node);
    225 	assert_int_equal(res, ISC_R_SUCCESS);
    226 
    227 	dns_rdataset_init(&rdataset);
    228 	res = dns_db_findrdataset(db1, node, v1, dns_rdatatype_soa, 0, 0,
    229 				  &rdataset, NULL);
    230 	assert_int_equal(res, ISC_R_NOTFOUND);
    231 
    232 	if (dns_rdataset_isassociated(&rdataset)) {
    233 		dns_rdataset_disassociate(&rdataset);
    234 	}
    235 
    236 	dns_rdataset_init(&rdataset);
    237 	check_assertion(dns_db_findrdataset(db1, node, v2, dns_rdatatype_soa, 0,
    238 					    0, &rdataset, NULL));
    239 
    240 	dns_db_detachnode(db1, &node);
    241 	assert_null(node);
    242 }
    243 
    244 /*
    245  * Check dns_db_deleterdataset() passes with matching db and version, and
    246  * asserts with mis-matching db and version.
    247  */
    248 ISC_RUN_TEST_IMPL(deleterdataset) {
    249 	isc_result_t res;
    250 	dns_dbnode_t *node = NULL;
    251 
    252 	UNUSED(state);
    253 
    254 	res = dns_db_findnode(db1, dns_rootname, false, &node);
    255 	assert_int_equal(res, ISC_R_SUCCESS);
    256 
    257 	res = dns_db_deleterdataset(db1, node, v1, dns_rdatatype_soa, 0);
    258 	assert_int_equal(res, DNS_R_UNCHANGED);
    259 
    260 	check_assertion(
    261 		dns_db_deleterdataset(db1, node, v2, dns_rdatatype_soa, 0));
    262 	dns_db_detachnode(db1, &node);
    263 	assert_null(node);
    264 }
    265 
    266 /*
    267  * Check dns_db_subtractrdataset() passes with matching db and version, and
    268  * asserts with mis-matching db and version.
    269  */
    270 ISC_RUN_TEST_IMPL(subtract) {
    271 	isc_result_t res;
    272 	dns_rdataset_t rdataset;
    273 	dns_rdatalist_t rdatalist;
    274 	dns_dbnode_t *node = NULL;
    275 
    276 	UNUSED(state);
    277 
    278 	dns_rdataset_init(&rdataset);
    279 	dns_rdatalist_init(&rdatalist);
    280 
    281 	rdatalist.rdclass = dns_rdataclass_in;
    282 
    283 	res = dns_rdatalist_tordataset(&rdatalist, &rdataset);
    284 	assert_int_equal(res, ISC_R_SUCCESS);
    285 
    286 	res = dns_db_findnode(db1, dns_rootname, false, &node);
    287 	assert_int_equal(res, ISC_R_SUCCESS);
    288 
    289 	res = dns_db_subtractrdataset(db1, node, v1, &rdataset, 0, NULL);
    290 	assert_int_equal(res, DNS_R_UNCHANGED);
    291 
    292 	if (dns_rdataset_isassociated(&rdataset)) {
    293 		dns_rdataset_disassociate(&rdataset);
    294 	}
    295 
    296 	dns_rdataset_init(&rdataset);
    297 	res = dns_rdatalist_tordataset(&rdatalist, &rdataset);
    298 	assert_int_equal(res, ISC_R_SUCCESS);
    299 
    300 	check_assertion(
    301 		dns_db_subtractrdataset(db1, node, v2, &rdataset, 0, NULL));
    302 
    303 	dns_db_detachnode(db1, &node);
    304 	assert_null(node);
    305 }
    306 
    307 /*
    308  * Check dns_db_dump() passes with matching db and version, and
    309  * asserts with mis-matching db and version.
    310  */
    311 ISC_RUN_TEST_IMPL(dump) {
    312 	isc_result_t res;
    313 	FILE *f = NULL;
    314 
    315 	UNUSED(state);
    316 
    317 	res = isc_file_openunique(tempname, &f);
    318 	fclose(f);
    319 	assert_int_equal(res, ISC_R_SUCCESS);
    320 
    321 	res = dns_db_dump(db1, v1, tempname);
    322 	assert_int_equal(res, ISC_R_SUCCESS);
    323 
    324 	check_assertion(dns_db_dump(db1, v2, tempname));
    325 }
    326 
    327 /*
    328  * Check dns_db_addrdataset() passes with matching db and version, and
    329  * asserts with mis-matching db and version.
    330  */
    331 ISC_RUN_TEST_IMPL(addrdataset) {
    332 	isc_result_t res;
    333 	dns_rdataset_t rdataset;
    334 	dns_dbnode_t *node = NULL;
    335 	dns_rdatalist_t rdatalist;
    336 
    337 	UNUSED(state);
    338 
    339 	dns_rdataset_init(&rdataset);
    340 	dns_rdatalist_init(&rdatalist);
    341 
    342 	rdatalist.rdclass = dns_rdataclass_in;
    343 
    344 	res = dns_rdatalist_tordataset(&rdatalist, &rdataset);
    345 	assert_int_equal(res, ISC_R_SUCCESS);
    346 
    347 	res = dns_db_findnode(db1, dns_rootname, false, &node);
    348 	assert_int_equal(res, ISC_R_SUCCESS);
    349 
    350 	res = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, NULL);
    351 	assert_int_equal(res, ISC_R_SUCCESS);
    352 
    353 	check_assertion(
    354 		dns_db_addrdataset(db1, node, v2, 0, &rdataset, 0, NULL));
    355 
    356 	dns_db_detachnode(db1, &node);
    357 	assert_null(node);
    358 }
    359 
    360 /*
    361  * Check dns_db_getnsec3parameters() passes with matching db and version,
    362  * and asserts with mis-matching db and version.
    363  */
    364 ISC_RUN_TEST_IMPL(getnsec3parameters) {
    365 	isc_result_t res;
    366 	dns_hash_t hash;
    367 	uint8_t flags;
    368 	uint16_t iterations;
    369 	unsigned char salt[DNS_NSEC3_SALTSIZE];
    370 	size_t salt_length = sizeof(salt);
    371 
    372 	UNUSED(state);
    373 
    374 	res = dns_db_getnsec3parameters(db1, v1, &hash, &flags, &iterations,
    375 					salt, &salt_length);
    376 	assert_int_equal(res, ISC_R_NOTFOUND);
    377 
    378 	check_assertion(dns_db_getnsec3parameters(
    379 		db1, v2, &hash, &flags, &iterations, salt, &salt_length));
    380 }
    381 
    382 /*
    383  * Check dns_db_resigned() passes with matching db and version, and
    384  * asserts with mis-matching db and version.
    385  */
    386 ISC_RUN_TEST_IMPL(resigned) {
    387 	isc_result_t res;
    388 	dns_rdataset_t rdataset, added;
    389 	dns_dbnode_t *node = NULL;
    390 	dns_rdatalist_t rdatalist;
    391 	dns_rdata_rrsig_t rrsig;
    392 	dns_rdata_t rdata = DNS_RDATA_INIT;
    393 	isc_buffer_t b;
    394 	unsigned char buf[1024];
    395 
    396 	UNUSED(state);
    397 
    398 	/*
    399 	 * Create a dummy RRSIG record and set a resigning time.
    400 	 */
    401 	dns_rdataset_init(&added);
    402 	dns_rdataset_init(&rdataset);
    403 	dns_rdatalist_init(&rdatalist);
    404 	isc_buffer_init(&b, buf, sizeof(buf));
    405 
    406 	DNS_RDATACOMMON_INIT(&rrsig, dns_rdatatype_rrsig, dns_rdataclass_in);
    407 	rrsig.covered = dns_rdatatype_a;
    408 	rrsig.algorithm = 100;
    409 	rrsig.labels = 0;
    410 	rrsig.originalttl = 0;
    411 	rrsig.timeexpire = 3600;
    412 	rrsig.timesigned = 0;
    413 	rrsig.keyid = 0;
    414 	dns_name_init(&rrsig.signer, NULL);
    415 	dns_name_clone(dns_rootname, &rrsig.signer);
    416 	rrsig.siglen = 0;
    417 	rrsig.signature = NULL;
    418 
    419 	res = dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
    420 				   dns_rdatatype_rrsig, &rrsig, &b);
    421 	assert_int_equal(res, ISC_R_SUCCESS);
    422 
    423 	rdatalist.rdclass = dns_rdataclass_in;
    424 	rdatalist.type = dns_rdatatype_rrsig;
    425 	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
    426 
    427 	res = dns_rdatalist_tordataset(&rdatalist, &rdataset);
    428 	assert_int_equal(res, ISC_R_SUCCESS);
    429 
    430 	rdataset.attributes |= DNS_RDATASETATTR_RESIGN;
    431 	rdataset.resign = 7200;
    432 
    433 	res = dns_db_findnode(db1, dns_rootname, false, &node);
    434 	assert_int_equal(res, ISC_R_SUCCESS);
    435 
    436 	res = dns_db_addrdataset(db1, node, v1, 0, &rdataset, 0, &added);
    437 	assert_int_equal(res, ISC_R_SUCCESS);
    438 
    439 	dns_db_detachnode(db1, &node);
    440 	assert_null(node);
    441 
    442 	check_assertion(dns_db_resigned(db1, &added, v2));
    443 
    444 	dns_db_resigned(db1, &added, v1);
    445 
    446 	dns_rdataset_disassociate(&added);
    447 }
    448 
    449 ISC_TEST_LIST_START
    450 ISC_TEST_ENTRY_CUSTOM(dump, setup_test, teardown_test)
    451 ISC_TEST_ENTRY_CUSTOM(find, setup_test, teardown_test)
    452 ISC_TEST_ENTRY_CUSTOM(allrdatasets, setup_test, teardown_test)
    453 ISC_TEST_ENTRY_CUSTOM(findrdataset, setup_test, teardown_test)
    454 ISC_TEST_ENTRY_CUSTOM(deleterdataset, setup_test, teardown_test)
    455 ISC_TEST_ENTRY_CUSTOM(subtract, setup_test, teardown_test)
    456 ISC_TEST_ENTRY_CUSTOM(addrdataset, setup_test, teardown_test)
    457 ISC_TEST_ENTRY_CUSTOM(getnsec3parameters, setup_test, teardown_test)
    458 ISC_TEST_ENTRY_CUSTOM(resigned, setup_test, teardown_test)
    459 ISC_TEST_ENTRY_CUSTOM(attachversion, setup_test, teardown_test)
    460 ISC_TEST_ENTRY_CUSTOM(closeversion, setup_test, teardown_test)
    461 ISC_TEST_LIST_END
    462 
    463 ISC_TEST_MAIN
    464