234 lines
6.3 KiB
C
234 lines
6.3 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>
|
|
#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);
|
|
dns_rdatalist_tordataset(&rdatalist, &rdataset);
|
|
|
|
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);
|
|
dns_rdatalist_tordataset(&rdatalist, &rdataset);
|
|
|
|
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
|