mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-21 17:41:35 -04:00
291 lines
8.6 KiB
C
291 lines
8.6 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
#include <inttypes.h>
|
|
#include <sched.h> /* IWYU pragma: keep */
|
|
#include <setjmp.h>
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define UNIT_TESTING
|
|
#include <cmocka.h>
|
|
|
|
#include <isc/buffer.h>
|
|
#include <isc/lib.h>
|
|
#include <isc/mem.h>
|
|
#include <isc/result.h>
|
|
#include <isc/util.h>
|
|
|
|
#include <dns/db.h>
|
|
#include <dns/fixedname.h>
|
|
#include <dns/lib.h>
|
|
#include <dns/name.h>
|
|
#include <dns/rdata.h>
|
|
#include <dns/rdataclass.h>
|
|
#include <dns/rdatalist.h>
|
|
#include <dns/rdataset.h>
|
|
#include <dns/rdatatype.h>
|
|
#include <dns/rdatavec.h>
|
|
|
|
#include <tests/dns.h>
|
|
#include <tests/isc.h>
|
|
|
|
/* Helper function to create a vecheader directly */
|
|
static isc_result_t
|
|
create_vecheader(isc_mem_t *mctx, dns_rdatatype_t type,
|
|
dns_rdataclass_t rdclass, dns_ttl_t ttl,
|
|
const char *rdata_text, dns_vecheader_t **headerp) {
|
|
dns_rdataset_t rdataset;
|
|
dns_rdatalist_t *rdatalist;
|
|
dns_rdata_t *rdata;
|
|
unsigned char *data;
|
|
isc_region_t region;
|
|
isc_result_t result;
|
|
|
|
/* Allocate temporary structures */
|
|
data = isc_mem_get(mctx, 256);
|
|
rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
|
|
rdata = isc_mem_get(mctx, sizeof(*rdata));
|
|
|
|
/* Initialize rdataset and rdatalist */
|
|
dns_rdataset_init(&rdataset);
|
|
dns_rdatalist_init(rdatalist);
|
|
rdatalist->type = type;
|
|
rdatalist->rdclass = rdclass;
|
|
rdatalist->ttl = ttl;
|
|
|
|
/* Create rdata */
|
|
dns_rdata_init(rdata);
|
|
CHECK(dns_test_rdatafromstring(rdata, rdclass, type, data, 256,
|
|
rdata_text, false));
|
|
|
|
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
|
dns_rdatalist_tordataset(rdatalist, &rdataset);
|
|
|
|
/* Convert to vecheader */
|
|
CHECK(dns_rdatavec_fromrdataset(&rdataset, mctx, ®ion, 0));
|
|
*headerp = (dns_vecheader_t *)region.base;
|
|
|
|
/* Cleanup rdataset */
|
|
dns_rdataset_disassociate(&rdataset);
|
|
|
|
cleanup:
|
|
/* Cleanup temporary structures */
|
|
isc_mem_put(mctx, rdata, sizeof(*rdata));
|
|
isc_mem_put(mctx, rdatalist, sizeof(*rdatalist));
|
|
isc_mem_put(mctx, data, 256);
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Helper function to create an rdataset from a vecheader */
|
|
static void
|
|
create_rdataset_from_vecheader(dns_vecheader_t *header,
|
|
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
|
dns_rdataset_t *rdataset) {
|
|
dns_rdataset_init(rdataset);
|
|
rdataset->methods = &dns_rdatavec_rdatasetmethods;
|
|
rdataset->rdclass = rdclass;
|
|
rdataset->type = type;
|
|
rdataset->vec.header = header;
|
|
}
|
|
|
|
/* Test merging two headers */
|
|
ISC_RUN_TEST_IMPL(merge_headers) {
|
|
isc_mem_t *mctx = isc_g_mctx;
|
|
UNUSED(state);
|
|
dns_vecheader_t *header1 = NULL, *header2 = NULL, *merged_header = NULL;
|
|
unsigned int size1, size2, merged_size, expected_size;
|
|
unsigned int count1, count2, merged_count, expected_count;
|
|
isc_result_t result;
|
|
|
|
/* Create vecheaders with A records */
|
|
CHECK(create_vecheader(mctx, dns_rdatatype_a, dns_rdataclass_in, 300,
|
|
"192.168.1.1", &header1));
|
|
|
|
CHECK(create_vecheader(mctx, dns_rdatatype_a, dns_rdataclass_in, 300,
|
|
"192.168.1.2", &header2));
|
|
|
|
/* Get sizes and counts before merging */
|
|
size1 = dns_rdatavec_size(header1);
|
|
size2 = dns_rdatavec_size(header2);
|
|
count1 = dns_rdatavec_count(header1);
|
|
count2 = dns_rdatavec_count(header2);
|
|
|
|
/* Merge headers */
|
|
CHECK(dns_rdatavec_merge(header1, header2, mctx, dns_rdataclass_in,
|
|
dns_rdatatype_a, 0, 0, &merged_header));
|
|
assert_non_null(merged_header);
|
|
|
|
/* Get merged size and count */
|
|
merged_size = dns_rdatavec_size(merged_header);
|
|
merged_count = dns_rdatavec_count(merged_header);
|
|
|
|
/* Test: merged size should be first_size + second_size - sizeof(header)
|
|
* - count_field_size */
|
|
expected_size = size1 + size2 - sizeof(dns_vecheader_t) - 2;
|
|
assert_int_equal(merged_size, expected_size);
|
|
|
|
/* Test: merged count should be first_count + second_count */
|
|
expected_count = count1 + count2;
|
|
assert_int_equal(merged_count, expected_count);
|
|
|
|
cleanup:
|
|
/* Cleanup */
|
|
if (header1 != NULL) {
|
|
size1 = dns_rdatavec_size(header1);
|
|
isc_mem_put(mctx, header1, size1);
|
|
}
|
|
if (header2 != NULL) {
|
|
size2 = dns_rdatavec_size(header2);
|
|
isc_mem_put(mctx, header2, size2);
|
|
}
|
|
if (merged_header != NULL) {
|
|
merged_size = dns_rdatavec_size(merged_header);
|
|
isc_mem_put(mctx, merged_header, merged_size);
|
|
}
|
|
}
|
|
|
|
/* Test case preservation during merge */
|
|
ISC_RUN_TEST_IMPL(merge_case_preservation) {
|
|
isc_mem_t *mctx = isc_g_mctx;
|
|
UNUSED(state);
|
|
dns_vecheader_t *header1 = NULL, *header2 = NULL, *merged_header = NULL;
|
|
dns_fixedname_t fname1, fname2, fmerged_name;
|
|
dns_name_t *name1 = dns_fixedname_initname(&fname1);
|
|
dns_name_t *name2 = dns_fixedname_initname(&fname2);
|
|
dns_name_t *merged_name = dns_fixedname_initname(&fmerged_name);
|
|
unsigned int size1, size2, merged_size;
|
|
isc_result_t result;
|
|
|
|
dns_test_namefromstring("Example.COM", &fname1);
|
|
dns_test_namefromstring("example.com", &fname2);
|
|
|
|
/* Create vecheaders */
|
|
CHECK(create_vecheader(mctx, dns_rdatatype_a, dns_rdataclass_in, 300,
|
|
"192.168.1.1", &header1));
|
|
|
|
CHECK(create_vecheader(mctx, dns_rdatatype_a, dns_rdataclass_in, 300,
|
|
"192.168.1.2", &header2));
|
|
|
|
/* Set case on first header */
|
|
dns_vecheader_setownercase(header1, name1);
|
|
|
|
/* Set case on second header */
|
|
dns_vecheader_setownercase(header2, name2);
|
|
|
|
/* Get sizes */
|
|
size1 = dns_rdatavec_size(header1);
|
|
size2 = dns_rdatavec_size(header2);
|
|
|
|
/* Merge headers */
|
|
CHECK(dns_rdatavec_merge(header1, header2, mctx, dns_rdataclass_in,
|
|
dns_rdatatype_a, 0, 0, &merged_header));
|
|
assert_non_null(merged_header);
|
|
|
|
/* Test: case should be the same as the first header */
|
|
/* Copy the name for testing */
|
|
dns_name_copy(name1, merged_name);
|
|
|
|
/* Create a test rdataset from merged header to test case */
|
|
dns_rdataset_t test_rdataset;
|
|
create_rdataset_from_vecheader(merged_header, dns_rdataclass_in,
|
|
dns_rdatatype_a, &test_rdataset);
|
|
|
|
/* Apply case from merged header */
|
|
dns_rdataset_getownercase(&test_rdataset, merged_name);
|
|
|
|
/* The case should match the original first name */
|
|
assert_true(dns_name_caseequal(name1, merged_name));
|
|
|
|
cleanup:
|
|
/* Cleanup */
|
|
if (header1 != NULL) {
|
|
size1 = dns_rdatavec_size(header1);
|
|
isc_mem_put(mctx, header1, size1);
|
|
}
|
|
if (header2 != NULL) {
|
|
size2 = dns_rdatavec_size(header2);
|
|
isc_mem_put(mctx, header2, size2);
|
|
}
|
|
if (merged_header != NULL) {
|
|
merged_size = dns_rdatavec_size(merged_header);
|
|
isc_mem_put(mctx, merged_header, merged_size);
|
|
}
|
|
}
|
|
|
|
/* Test size consistency after setting case */
|
|
ISC_RUN_TEST_IMPL(setcase_size_consistency) {
|
|
isc_mem_t *mctx = isc_g_mctx;
|
|
UNUSED(state);
|
|
dns_vecheader_t *header = NULL;
|
|
dns_fixedname_t fname, flower_fname, fretrieved_fname;
|
|
dns_name_t *name = dns_fixedname_initname(&fname);
|
|
dns_name_t *lower_name = dns_fixedname_initname(&flower_fname);
|
|
dns_name_t *retrieved_name = dns_fixedname_initname(&fretrieved_fname);
|
|
unsigned int original_size, cased_size;
|
|
dns_rdataset_t test_rdataset;
|
|
isc_result_t result;
|
|
|
|
/* Initialize name */
|
|
dns_test_namefromstring("Example.COM", &fname);
|
|
|
|
/* Create vecheader */
|
|
CHECK(create_vecheader(mctx, dns_rdatatype_a, dns_rdataclass_in, 300,
|
|
"192.168.1.1", &header));
|
|
|
|
/* Get original size */
|
|
original_size = dns_rdatavec_size(header);
|
|
|
|
/* Set case */
|
|
dns_vecheader_setownercase(header, name);
|
|
|
|
/* Get size after setting case */
|
|
cased_size = dns_rdatavec_size(header);
|
|
|
|
/* Test: size should be the same after setting case */
|
|
assert_int_equal(cased_size, original_size);
|
|
|
|
/* Create lowercase version of the original name */
|
|
dns_test_namefromstring("example.com", &flower_fname);
|
|
|
|
/* Copy lowercase name to retrieved_name for testing */
|
|
dns_name_copy(lower_name, retrieved_name);
|
|
|
|
/* Create a test rdataset from cased header */
|
|
create_rdataset_from_vecheader(header, dns_rdataclass_in,
|
|
dns_rdatatype_a, &test_rdataset);
|
|
|
|
/* Apply case from cased header to retrieved_name */
|
|
dns_rdataset_getownercase(&test_rdataset, retrieved_name);
|
|
|
|
/* Test: retrieved case should match the original mixed case */
|
|
assert_true(dns_name_caseequal(name, retrieved_name));
|
|
|
|
cleanup:
|
|
/* Cleanup */
|
|
if (header != NULL) {
|
|
cased_size = dns_rdatavec_size(header);
|
|
isc_mem_put(mctx, header, cased_size);
|
|
}
|
|
}
|
|
|
|
ISC_TEST_LIST_START
|
|
ISC_TEST_ENTRY_CUSTOM(merge_headers, setup_mctx, teardown_mctx)
|
|
ISC_TEST_ENTRY_CUSTOM(merge_case_preservation, setup_mctx, teardown_mctx)
|
|
ISC_TEST_ENTRY_CUSTOM(setcase_size_consistency, setup_mctx, teardown_mctx)
|
|
ISC_TEST_LIST_END
|
|
|
|
ISC_TEST_MAIN
|