Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: dns64_test.c,v 1.3 2025/01/26 16:25:47 christos 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/netaddr.h>
     29 #include <isc/result.h>
     30 #include <isc/string.h>
     31 #include <isc/util.h>
     32 
     33 #include <dns/dns64.h>
     34 #include <dns/rdata.h>
     35 #include <dns/rdatalist.h>
     36 #include <dns/rdataset.h>
     37 
     38 #include <tests/dns.h>
     39 
     40 static void
     41 multiple_prefixes(void) {
     42 	size_t i, count;
     43 	/*
     44 	 * Two prefix, non consectutive.
     45 	 */
     46 	unsigned char aaaa[4][16] = {
     47 		{ 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0, 192, 0, 0, 171 },
     48 		{ 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0, 192, 0, 0, 170 },
     49 		{ 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0, 192, 0, 0, 170 },
     50 		{ 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0, 192, 0, 0, 171 },
     51 	};
     52 	dns_rdataset_t rdataset;
     53 	dns_rdatalist_t rdatalist;
     54 	dns_rdata_t rdata[4] = { DNS_RDATA_INIT, DNS_RDATA_INIT, DNS_RDATA_INIT,
     55 				 DNS_RDATA_INIT };
     56 	isc_netprefix_t prefix[2];
     57 	unsigned char p1[] = { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0 };
     58 	unsigned char p2[] = { 0, 0, 0, 0, 192, 55, 0, 170, 0, 0, 0, 0 };
     59 	isc_result_t result;
     60 	bool have_p1, have_p2;
     61 
     62 	/*
     63 	 * Construct AAAA rdataset containing 2 prefixes.
     64 	 */
     65 	dns_rdatalist_init(&rdatalist);
     66 	for (i = 0; i < 4; i++) {
     67 		isc_region_t region;
     68 		region.base = aaaa[i];
     69 		region.length = 16;
     70 		dns_rdata_fromregion(&rdata[i], dns_rdataclass_in,
     71 				     dns_rdatatype_aaaa, &region);
     72 		ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
     73 	}
     74 	rdatalist.type = rdata[0].type;
     75 	rdatalist.rdclass = rdata[0].rdclass;
     76 	rdatalist.ttl = 0;
     77 	dns_rdataset_init(&rdataset);
     78 	dns_rdatalist_tordataset(&rdatalist, &rdataset);
     79 
     80 	count = ARRAY_SIZE(prefix);
     81 	memset(&prefix, 0, sizeof(prefix));
     82 	result = dns_dns64_findprefix(&rdataset, prefix, &count);
     83 	assert_int_equal(result, ISC_R_SUCCESS);
     84 	assert_int_equal(count, 2);
     85 	have_p1 = have_p2 = false;
     86 	for (i = 0; i < count; i++) {
     87 		assert_int_equal(prefix[i].prefixlen, 96);
     88 		assert_int_equal(prefix[i].addr.family, AF_INET6);
     89 		if (memcmp(prefix[i].addr.type.in6.s6_addr, p1, 12) == 0) {
     90 			have_p1 = true;
     91 		}
     92 		if (memcmp(prefix[i].addr.type.in6.s6_addr, p2, 12) == 0) {
     93 			have_p2 = true;
     94 		}
     95 	}
     96 	assert_true(have_p1);
     97 	assert_true(have_p2);
     98 
     99 	/*
    100 	 * Check that insufficient prefix space returns ISC_R_NOSPACE
    101 	 * and that the prefix is populated.
    102 	 */
    103 	count = 1;
    104 	memset(&prefix, 0, sizeof(prefix));
    105 	result = dns_dns64_findprefix(&rdataset, prefix, &count);
    106 	assert_int_equal(result, ISC_R_NOSPACE);
    107 	assert_int_equal(count, 2);
    108 	have_p1 = have_p2 = false;
    109 	assert_int_equal(prefix[0].prefixlen, 96);
    110 	assert_int_equal(prefix[0].addr.family, AF_INET6);
    111 	if (memcmp(prefix[0].addr.type.in6.s6_addr, p1, 12) == 0) {
    112 		have_p1 = true;
    113 	}
    114 	if (memcmp(prefix[0].addr.type.in6.s6_addr, p2, 12) == 0) {
    115 		have_p2 = true;
    116 	}
    117 	if (!have_p2) {
    118 		assert_true(have_p1);
    119 	}
    120 	if (!have_p1) {
    121 		assert_true(have_p2);
    122 	}
    123 	assert_true(have_p1 != have_p2);
    124 }
    125 
    126 ISC_RUN_TEST_IMPL(dns64_findprefix) {
    127 	unsigned int i, j, o;
    128 	isc_result_t result;
    129 	struct {
    130 		unsigned char prefix[12];
    131 		unsigned int prefixlen;
    132 		isc_result_t result;
    133 	} tests[] = {
    134 		/* The WKP with various lengths. */
    135 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 },
    136 		  32,
    137 		  ISC_R_SUCCESS },
    138 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 },
    139 		  40,
    140 		  ISC_R_SUCCESS },
    141 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 },
    142 		  48,
    143 		  ISC_R_SUCCESS },
    144 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 },
    145 		  56,
    146 		  ISC_R_SUCCESS },
    147 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 },
    148 		  64,
    149 		  ISC_R_SUCCESS },
    150 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 0, 0, 0, 0 },
    151 		  96,
    152 		  ISC_R_SUCCESS },
    153 		/*
    154 		 * Prefix with the mapped addresses also appearing in the
    155 		 * prefix.
    156 		 */
    157 		{ { 0, 0, 0, 0, 192, 0, 0, 170, 0, 0, 0, 0 },
    158 		  96,
    159 		  ISC_R_SUCCESS },
    160 		{ { 0, 0, 0, 0, 192, 0, 0, 171, 0, 0, 0, 0 },
    161 		  96,
    162 		  ISC_R_SUCCESS },
    163 		/* Bad prefix, MBZ != 0. */
    164 		{ { 0, 0x64, 0xff, 0x9b, 0, 0, 0, 0, 1, 0, 0, 0 },
    165 		  96,
    166 		  ISC_R_NOTFOUND },
    167 	};
    168 
    169 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
    170 		size_t count = 2;
    171 		dns_rdataset_t rdataset;
    172 		dns_rdatalist_t rdatalist;
    173 		dns_rdata_t rdata[2] = { DNS_RDATA_INIT, DNS_RDATA_INIT };
    174 		struct in6_addr ina6[2];
    175 		isc_netprefix_t prefix[2];
    176 		unsigned char aa[] = { 192, 0, 0, 170 };
    177 		unsigned char ab[] = { 192, 0, 0, 171 };
    178 		isc_region_t region;
    179 
    180 		/*
    181 		 * Construct rdata.
    182 		 */
    183 		memset(ina6[0].s6_addr, 0, sizeof(ina6[0].s6_addr));
    184 		memset(ina6[1].s6_addr, 0, sizeof(ina6[1].s6_addr));
    185 		memmove(ina6[0].s6_addr, tests[i].prefix, 12);
    186 		memmove(ina6[1].s6_addr, tests[i].prefix, 12);
    187 		o = tests[i].prefixlen / 8;
    188 		for (j = 0; j < 4; j++) {
    189 			if ((o + j) == 8U) {
    190 				o++; /* skip mbz */
    191 			}
    192 			ina6[0].s6_addr[j + o] = aa[j];
    193 			ina6[1].s6_addr[j + o] = ab[j];
    194 		}
    195 		region.base = ina6[0].s6_addr;
    196 		region.length = sizeof(ina6[0].s6_addr);
    197 		dns_rdata_fromregion(&rdata[0], dns_rdataclass_in,
    198 				     dns_rdatatype_aaaa, &region);
    199 		region.base = ina6[1].s6_addr;
    200 		region.length = sizeof(ina6[1].s6_addr);
    201 		dns_rdata_fromregion(&rdata[1], dns_rdataclass_in,
    202 				     dns_rdatatype_aaaa, &region);
    203 
    204 		dns_rdatalist_init(&rdatalist);
    205 		rdatalist.type = rdata[0].type;
    206 		rdatalist.rdclass = rdata[0].rdclass;
    207 		rdatalist.ttl = 0;
    208 		ISC_LIST_APPEND(rdatalist.rdata, &rdata[0], link);
    209 		ISC_LIST_APPEND(rdatalist.rdata, &rdata[1], link);
    210 		dns_rdataset_init(&rdataset);
    211 		dns_rdatalist_tordataset(&rdatalist, &rdataset);
    212 
    213 		result = dns_dns64_findprefix(&rdataset, prefix, &count);
    214 		assert_int_equal(result, tests[i].result);
    215 		if (tests[i].result == ISC_R_SUCCESS) {
    216 			assert_int_equal(count, 1);
    217 			assert_int_equal(prefix[0].prefixlen,
    218 					 tests[i].prefixlen);
    219 			assert_int_equal(prefix[0].addr.family, AF_INET6);
    220 			assert_memory_equal(prefix[0].addr.type.in6.s6_addr,
    221 					    tests[i].prefix,
    222 					    tests[i].prefixlen / 8);
    223 		}
    224 	}
    225 
    226 	/*
    227 	 * Test multiple prefixes.
    228 	 */
    229 	multiple_prefixes();
    230 }
    231 
    232 ISC_TEST_LIST_START
    233 ISC_TEST_ENTRY(dns64_findprefix)
    234 ISC_TEST_LIST_END
    235 
    236 ISC_TEST_MAIN
    237