diff options
Diffstat (limited to '')
-rw-r--r-- | tests/dns/dns64_test.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/tests/dns/dns64_test.c b/tests/dns/dns64_test.c new file mode 100644 index 0000000..5834991 --- /dev/null +++ b/tests/dns/dns64_test.c @@ -0,0 +1,236 @@ +/* + * 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> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/netaddr.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/dns64.h> +#include <dns/rdata.h> +#include <dns/rdatalist.h> +#include <dns/rdataset.h> + +#include <tests/dns.h> + +static void +multiple_prefixes(void) { + size_t i, count; + /* + * Two prefix, non consectutive. + */ + unsigned char aaaa[4][16] = { + { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0, 192, 0, 0, 171 }, + { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0, 192, 0, 0, 170 }, + { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0, 192, 0, 0, 170 }, + { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0, 192, 0, 0, 171 }, + }; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_rdata_t rdata[4] = { DNS_RDATA_INIT, DNS_RDATA_INIT, DNS_RDATA_INIT, + DNS_RDATA_INIT }; + isc_netprefix_t prefix[2]; + unsigned char p1[] = { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0 }; + unsigned char p2[] = { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0 }; + isc_result_t result; + bool have_p1, have_p2; + + /* + * Construct AAAA rdataset containing 2 prefixes. + */ + dns_rdatalist_init(&rdatalist); + for (i = 0; i < 4; i++) { + isc_region_t region; + region.base = aaaa[i]; + region.length = 16; + dns_rdata_fromregion(&rdata[i], dns_rdataclass_in, + dns_rdatatype_aaaa, ®ion); + ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link); + } + rdatalist.type = rdata[0].type; + rdatalist.rdclass = rdata[0].rdclass; + rdatalist.ttl = 0; + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(result, ISC_R_SUCCESS); + + count = ARRAY_SIZE(prefix); + memset(&prefix, 0, sizeof(prefix)); + result = dns_dns64_findprefix(&rdataset, prefix, &count); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(count, 2); + have_p1 = have_p2 = false; + for (i = 0; i < count; i++) { + assert_int_equal(prefix[i].prefixlen, 96); + assert_int_equal(prefix[i].addr.family, AF_INET6); + if (memcmp(prefix[i].addr.type.in6.s6_addr, p1, 12) == 0) { + have_p1 = true; + } + if (memcmp(prefix[i].addr.type.in6.s6_addr, p2, 12) == 0) { + have_p2 = true; + } + } + assert_true(have_p1); + assert_true(have_p2); + + /* + * Check that insufficient prefix space returns ISC_R_NOSPACE + * and that the prefix is populated. + */ + count = 1; + memset(&prefix, 0, sizeof(prefix)); + result = dns_dns64_findprefix(&rdataset, prefix, &count); + assert_int_equal(result, ISC_R_NOSPACE); + assert_int_equal(count, 2); + have_p1 = have_p2 = false; + assert_int_equal(prefix[0].prefixlen, 96); + assert_int_equal(prefix[0].addr.family, AF_INET6); + if (memcmp(prefix[0].addr.type.in6.s6_addr, p1, 12) == 0) { + have_p1 = true; + } + if (memcmp(prefix[0].addr.type.in6.s6_addr, p2, 12) == 0) { + have_p2 = true; + } + if (!have_p2) { + assert_true(have_p1); + } + if (!have_p1) { + assert_true(have_p2); + } + assert_true(have_p1 != have_p2); +} + +ISC_RUN_TEST_IMPL(dns64_findprefix) { + unsigned int i, j, o; + isc_result_t result; + struct { + unsigned char prefix[12]; + unsigned int prefixlen; + isc_result_t result; + } tests[] = { + /* The WKP with various lengths. */ + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 32, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 40, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 48, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 56, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 64, + ISC_R_SUCCESS }, + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 }, + 96, + ISC_R_SUCCESS }, + /* + * Prefix with the mapped addresses also appearing in the + * prefix. + */ + { { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0 }, + 96, + ISC_R_SUCCESS }, + { { 0, 0, 0, 0, 192, 0, 0, 171, 0, 0, 0, 0 }, + 96, + ISC_R_SUCCESS }, + /* Bad prefix, MBZ != 0. */ + { { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 1, 0, 0, 0 }, + 96, + ISC_R_NOTFOUND }, + }; + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + size_t count = 2; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist; + dns_rdata_t rdata[2] = { DNS_RDATA_INIT, DNS_RDATA_INIT }; + struct in6_addr ina6[2]; + isc_netprefix_t prefix[2]; + unsigned char aa[] = { 192, 0, 0, 170 }; + unsigned char ab[] = { 192, 0, 0, 171 }; + isc_region_t region; + + /* + * Construct rdata. + */ + memset(ina6[0].s6_addr, 0, sizeof(ina6[0].s6_addr)); + memset(ina6[1].s6_addr, 0, sizeof(ina6[1].s6_addr)); + memmove(ina6[0].s6_addr, tests[i].prefix, 12); + memmove(ina6[1].s6_addr, tests[i].prefix, 12); + o = tests[i].prefixlen / 8; + for (j = 0; j < 4; j++) { + if ((o + j) == 8U) { + o++; /* skip mbz */ + } + ina6[0].s6_addr[j + o] = aa[j]; + ina6[1].s6_addr[j + o] = ab[j]; + } + region.base = ina6[0].s6_addr; + region.length = sizeof(ina6[0].s6_addr); + dns_rdata_fromregion(&rdata[0], dns_rdataclass_in, + dns_rdatatype_aaaa, ®ion); + region.base = ina6[1].s6_addr; + region.length = sizeof(ina6[1].s6_addr); + dns_rdata_fromregion(&rdata[1], dns_rdataclass_in, + dns_rdatatype_aaaa, ®ion); + + dns_rdatalist_init(&rdatalist); + rdatalist.type = rdata[0].type; + rdatalist.rdclass = rdata[0].rdclass; + rdatalist.ttl = 0; + ISC_LIST_APPEND(rdatalist.rdata, &rdata[0], link); + ISC_LIST_APPEND(rdatalist.rdata, &rdata[1], link); + dns_rdataset_init(&rdataset); + result = dns_rdatalist_tordataset(&rdatalist, &rdataset); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_dns64_findprefix(&rdataset, prefix, &count); + assert_int_equal(result, tests[i].result); + if (tests[i].result == ISC_R_SUCCESS) { + assert_int_equal(count, 1); + assert_int_equal(prefix[0].prefixlen, + tests[i].prefixlen); + assert_int_equal(prefix[0].addr.family, AF_INET6); + assert_memory_equal(prefix[0].addr.type.in6.s6_addr, + tests[i].prefix, + tests[i].prefixlen / 8); + } + } + + /* + * Test multiple prefixes. + */ + multiple_prefixes(); +} + +ISC_TEST_LIST_START +ISC_TEST_ENTRY(dns64_findprefix) +ISC_TEST_LIST_END + +ISC_TEST_MAIN |