xref: /netbsd-src/external/mpl/bind/dist/lib/dns/remote.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1*bcda20f6Schristos /*	$NetBSD: remote.c,v 1.2 2025/01/26 16:25:24 christos Exp $	*/
29689912eSchristos 
39689912eSchristos /*
49689912eSchristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
59689912eSchristos  *
69689912eSchristos  * SPDX-License-Identifier: MPL-2.0
79689912eSchristos  *
89689912eSchristos  * This Source Code Form is subject to the terms of the Mozilla Public
99689912eSchristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
109689912eSchristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
119689912eSchristos  *
129689912eSchristos  * See the COPYRIGHT file distributed with this work for additional
139689912eSchristos  * information regarding copyright ownership.
149689912eSchristos  */
159689912eSchristos 
169689912eSchristos /*! \file */
179689912eSchristos 
189689912eSchristos #include <stdbool.h>
199689912eSchristos #include <string.h>
209689912eSchristos 
219689912eSchristos #include <isc/result.h>
229689912eSchristos #include <isc/sockaddr.h>
239689912eSchristos #include <isc/types.h>
249689912eSchristos #include <isc/util.h>
259689912eSchristos 
269689912eSchristos #include <dns/name.h>
279689912eSchristos #include <dns/remote.h>
289689912eSchristos #include <dns/types.h>
299689912eSchristos 
309689912eSchristos isc_sockaddr_t *
319689912eSchristos dns_remote_addresses(dns_remote_t *remote) {
329689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
339689912eSchristos 	return remote->addresses;
349689912eSchristos }
359689912eSchristos 
369689912eSchristos isc_sockaddr_t *
379689912eSchristos dns_remote_sources(dns_remote_t *remote) {
389689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
399689912eSchristos 	return remote->sources;
409689912eSchristos }
419689912eSchristos 
429689912eSchristos unsigned int
439689912eSchristos dns_remote_count(dns_remote_t *remote) {
449689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
459689912eSchristos 	return remote->addrcnt;
469689912eSchristos }
479689912eSchristos 
489689912eSchristos dns_name_t **
499689912eSchristos dns_remote_keynames(dns_remote_t *remote) {
509689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
519689912eSchristos 	return remote->keynames;
529689912eSchristos }
539689912eSchristos 
549689912eSchristos dns_name_t **
559689912eSchristos dns_remote_tlsnames(dns_remote_t *remote) {
569689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
579689912eSchristos 	return remote->tlsnames;
589689912eSchristos }
599689912eSchristos 
609689912eSchristos void
619689912eSchristos dns_remote_init(dns_remote_t *remote, unsigned int count,
629689912eSchristos 		const isc_sockaddr_t *addrs, const isc_sockaddr_t *srcs,
639689912eSchristos 		dns_name_t **keynames, dns_name_t **tlsnames, bool mark,
649689912eSchristos 		isc_mem_t *mctx) {
659689912eSchristos 	unsigned int i;
669689912eSchristos 
679689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
689689912eSchristos 	REQUIRE(count == 0 || addrs != NULL);
699689912eSchristos 
709689912eSchristos 	if (keynames != NULL || tlsnames != NULL) {
719689912eSchristos 		REQUIRE(count != 0);
729689912eSchristos 	}
739689912eSchristos 
749689912eSchristos 	remote->mctx = mctx;
759689912eSchristos 
769689912eSchristos 	if (addrs != NULL) {
779689912eSchristos 		remote->addresses = isc_mem_cget(mctx, count,
789689912eSchristos 						 sizeof(isc_sockaddr_t));
799689912eSchristos 		memmove(remote->addresses, addrs,
809689912eSchristos 			count * sizeof(isc_sockaddr_t));
819689912eSchristos 	} else {
829689912eSchristos 		remote->addresses = NULL;
839689912eSchristos 	}
849689912eSchristos 
859689912eSchristos 	if (srcs != NULL) {
869689912eSchristos 		remote->sources = isc_mem_cget(mctx, count,
879689912eSchristos 					       sizeof(isc_sockaddr_t));
889689912eSchristos 		memmove(remote->sources, srcs, count * sizeof(isc_sockaddr_t));
899689912eSchristos 	} else {
909689912eSchristos 		remote->sources = NULL;
919689912eSchristos 	}
929689912eSchristos 
939689912eSchristos 	if (keynames != NULL) {
949689912eSchristos 		remote->keynames = isc_mem_cget(mctx, count,
959689912eSchristos 						sizeof(keynames[0]));
969689912eSchristos 		for (i = 0; i < count; i++) {
979689912eSchristos 			remote->keynames[i] = NULL;
989689912eSchristos 		}
999689912eSchristos 		for (i = 0; i < count; i++) {
1009689912eSchristos 			if (keynames[i] != NULL) {
1019689912eSchristos 				remote->keynames[i] =
1029689912eSchristos 					isc_mem_get(mctx, sizeof(dns_name_t));
1039689912eSchristos 				dns_name_init(remote->keynames[i], NULL);
1049689912eSchristos 				dns_name_dup(keynames[i], mctx,
1059689912eSchristos 					     remote->keynames[i]);
1069689912eSchristos 			}
1079689912eSchristos 		}
1089689912eSchristos 	} else {
1099689912eSchristos 		remote->keynames = NULL;
1109689912eSchristos 	}
1119689912eSchristos 
1129689912eSchristos 	if (tlsnames != NULL) {
1139689912eSchristos 		remote->tlsnames = isc_mem_cget(mctx, count,
1149689912eSchristos 						sizeof(tlsnames[0]));
1159689912eSchristos 		for (i = 0; i < count; i++) {
1169689912eSchristos 			remote->tlsnames[i] = NULL;
1179689912eSchristos 		}
1189689912eSchristos 		for (i = 0; i < count; i++) {
1199689912eSchristos 			if (tlsnames[i] != NULL) {
1209689912eSchristos 				remote->tlsnames[i] =
1219689912eSchristos 					isc_mem_get(mctx, sizeof(dns_name_t));
1229689912eSchristos 				dns_name_init(remote->tlsnames[i], NULL);
1239689912eSchristos 				dns_name_dup(tlsnames[i], mctx,
1249689912eSchristos 					     remote->tlsnames[i]);
1259689912eSchristos 			}
1269689912eSchristos 		}
1279689912eSchristos 	} else {
1289689912eSchristos 		remote->tlsnames = NULL;
1299689912eSchristos 	}
1309689912eSchristos 
1319689912eSchristos 	if (mark) {
1329689912eSchristos 		remote->ok = isc_mem_cget(mctx, count, sizeof(bool));
1339689912eSchristos 		for (i = 0; i < count; i++) {
1349689912eSchristos 			remote->ok[i] = false;
1359689912eSchristos 		}
1369689912eSchristos 	} else {
1379689912eSchristos 		remote->ok = NULL;
1389689912eSchristos 	}
1399689912eSchristos 
1409689912eSchristos 	remote->addrcnt = count;
1419689912eSchristos 	remote->curraddr = 0;
1429689912eSchristos }
1439689912eSchristos 
1449689912eSchristos static bool
1459689912eSchristos same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
1469689912eSchristos 	   uint32_t count) {
1479689912eSchristos 	unsigned int i;
1489689912eSchristos 
1499689912eSchristos 	if (oldlist == NULL && newlist == NULL) {
1509689912eSchristos 		return true;
1519689912eSchristos 	}
1529689912eSchristos 	if (oldlist == NULL || newlist == NULL) {
1539689912eSchristos 		return false;
1549689912eSchristos 	}
1559689912eSchristos 
1569689912eSchristos 	for (i = 0; i < count; i++) {
1579689912eSchristos 		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
1589689912eSchristos 			return false;
1599689912eSchristos 		}
1609689912eSchristos 	}
1619689912eSchristos 	return true;
1629689912eSchristos }
1639689912eSchristos 
1649689912eSchristos static bool
1659689912eSchristos same_names(dns_name_t *const *oldlist, dns_name_t *const *newlist,
1669689912eSchristos 	   uint32_t count) {
1679689912eSchristos 	unsigned int i;
1689689912eSchristos 
1699689912eSchristos 	if (oldlist == NULL && newlist == NULL) {
1709689912eSchristos 		return true;
1719689912eSchristos 	}
1729689912eSchristos 	if (oldlist == NULL || newlist == NULL) {
1739689912eSchristos 		return false;
1749689912eSchristos 	}
1759689912eSchristos 
1769689912eSchristos 	for (i = 0; i < count; i++) {
1779689912eSchristos 		if (oldlist[i] == NULL && newlist[i] == NULL) {
1789689912eSchristos 			continue;
1799689912eSchristos 		}
1809689912eSchristos 		if (oldlist[i] == NULL || newlist[i] == NULL ||
1819689912eSchristos 		    !dns_name_equal(oldlist[i], newlist[i]))
1829689912eSchristos 		{
1839689912eSchristos 			return false;
1849689912eSchristos 		}
1859689912eSchristos 	}
1869689912eSchristos 	return true;
1879689912eSchristos }
1889689912eSchristos 
1899689912eSchristos void
1909689912eSchristos dns_remote_clear(dns_remote_t *remote) {
1919689912eSchristos 	unsigned int count;
1929689912eSchristos 	isc_mem_t *mctx;
1939689912eSchristos 
1949689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
1959689912eSchristos 
1969689912eSchristos 	count = remote->addrcnt;
1979689912eSchristos 	mctx = remote->mctx;
1989689912eSchristos 
1999689912eSchristos 	if (mctx == NULL) {
2009689912eSchristos 		return;
2019689912eSchristos 	}
2029689912eSchristos 
2039689912eSchristos 	if (remote->ok != NULL) {
2049689912eSchristos 		isc_mem_cput(mctx, remote->ok, count, sizeof(bool));
2059689912eSchristos 		remote->ok = NULL;
2069689912eSchristos 	}
2079689912eSchristos 
2089689912eSchristos 	if (remote->addresses != NULL) {
2099689912eSchristos 		isc_mem_cput(mctx, remote->addresses, count,
2109689912eSchristos 			     sizeof(isc_sockaddr_t));
2119689912eSchristos 		remote->addresses = NULL;
2129689912eSchristos 	}
2139689912eSchristos 
2149689912eSchristos 	if (remote->sources != NULL) {
2159689912eSchristos 		isc_mem_cput(mctx, remote->sources, count,
2169689912eSchristos 			     sizeof(isc_sockaddr_t));
2179689912eSchristos 		remote->sources = NULL;
2189689912eSchristos 	}
2199689912eSchristos 
2209689912eSchristos 	if (remote->keynames != NULL) {
2219689912eSchristos 		unsigned int i;
2229689912eSchristos 		for (i = 0; i < count; i++) {
2239689912eSchristos 			if (remote->keynames[i] != NULL) {
2249689912eSchristos 				dns_name_free(remote->keynames[i], mctx);
2259689912eSchristos 				isc_mem_put(mctx, remote->keynames[i],
2269689912eSchristos 					    sizeof(dns_name_t));
2279689912eSchristos 				remote->keynames[i] = NULL;
2289689912eSchristos 			}
2299689912eSchristos 		}
2309689912eSchristos 		isc_mem_cput(mctx, remote->keynames, count,
2319689912eSchristos 			     sizeof(dns_name_t *));
2329689912eSchristos 		remote->keynames = NULL;
2339689912eSchristos 	}
2349689912eSchristos 
2359689912eSchristos 	if (remote->tlsnames != NULL) {
2369689912eSchristos 		unsigned int i;
2379689912eSchristos 		for (i = 0; i < count; i++) {
2389689912eSchristos 			if (remote->tlsnames[i] != NULL) {
2399689912eSchristos 				dns_name_free(remote->tlsnames[i], mctx);
2409689912eSchristos 				isc_mem_put(mctx, remote->tlsnames[i],
2419689912eSchristos 					    sizeof(dns_name_t));
2429689912eSchristos 				remote->tlsnames[i] = NULL;
2439689912eSchristos 			}
2449689912eSchristos 		}
2459689912eSchristos 		isc_mem_cput(mctx, remote->tlsnames, count,
2469689912eSchristos 			     sizeof(dns_name_t *));
2479689912eSchristos 		remote->tlsnames = NULL;
2489689912eSchristos 	}
2499689912eSchristos 
2509689912eSchristos 	remote->curraddr = 0;
2519689912eSchristos 	remote->addrcnt = 0;
2529689912eSchristos 	remote->mctx = NULL;
2539689912eSchristos }
2549689912eSchristos 
2559689912eSchristos bool
2569689912eSchristos dns_remote_equal(dns_remote_t *a, dns_remote_t *b) {
2579689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(a));
2589689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(b));
2599689912eSchristos 
2609689912eSchristos 	if (a->addrcnt != b->addrcnt) {
2619689912eSchristos 		return false;
2629689912eSchristos 	}
2639689912eSchristos 
2649689912eSchristos 	if (!same_addrs(a->addresses, b->addresses, a->addrcnt)) {
2659689912eSchristos 		return false;
2669689912eSchristos 	}
2679689912eSchristos 	if (!same_names(a->keynames, b->keynames, a->addrcnt)) {
2689689912eSchristos 		return false;
2699689912eSchristos 	}
2709689912eSchristos 	if (!same_names(a->tlsnames, b->tlsnames, a->addrcnt)) {
2719689912eSchristos 		return false;
2729689912eSchristos 	}
2739689912eSchristos 
2749689912eSchristos 	return true;
2759689912eSchristos }
2769689912eSchristos 
2779689912eSchristos void
2789689912eSchristos dns_remote_reset(dns_remote_t *remote, bool clear_ok) {
2799689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
2809689912eSchristos 
2819689912eSchristos 	remote->curraddr = 0;
2829689912eSchristos 
2839689912eSchristos 	if (clear_ok && remote->ok != NULL) {
2849689912eSchristos 		for (unsigned int i = 0; i < remote->addrcnt; i++) {
2859689912eSchristos 			remote->ok[i] = false;
2869689912eSchristos 		}
2879689912eSchristos 	}
2889689912eSchristos }
2899689912eSchristos 
2909689912eSchristos isc_sockaddr_t
2919689912eSchristos dns_remote_curraddr(dns_remote_t *remote) {
2929689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
2939689912eSchristos 	REQUIRE(remote->addresses != NULL);
2949689912eSchristos 	REQUIRE(remote->curraddr < remote->addrcnt);
2959689912eSchristos 
2969689912eSchristos 	return remote->addresses[remote->curraddr];
2979689912eSchristos }
2989689912eSchristos 
2999689912eSchristos isc_sockaddr_t
3009689912eSchristos dns_remote_addr(dns_remote_t *remote, unsigned int i) {
3019689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3029689912eSchristos 	REQUIRE(remote->addresses != NULL);
3039689912eSchristos 	REQUIRE(i < remote->addrcnt);
3049689912eSchristos 
3059689912eSchristos 	return remote->addresses[i];
3069689912eSchristos }
3079689912eSchristos 
3089689912eSchristos isc_sockaddr_t
3099689912eSchristos dns_remote_sourceaddr(dns_remote_t *remote) {
3109689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3119689912eSchristos 	REQUIRE(remote->sources != NULL);
3129689912eSchristos 	REQUIRE(remote->curraddr < remote->addrcnt);
3139689912eSchristos 
3149689912eSchristos 	return remote->sources[remote->curraddr];
3159689912eSchristos }
3169689912eSchristos 
3179689912eSchristos dns_name_t *
3189689912eSchristos dns_remote_keyname(dns_remote_t *remote) {
3199689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3209689912eSchristos 
3219689912eSchristos 	if (remote->keynames == NULL) {
3229689912eSchristos 		return NULL;
3239689912eSchristos 	}
3249689912eSchristos 	if (remote->curraddr >= remote->addrcnt) {
3259689912eSchristos 		return NULL;
3269689912eSchristos 	}
3279689912eSchristos 
3289689912eSchristos 	return remote->keynames[remote->curraddr];
3299689912eSchristos }
3309689912eSchristos 
3319689912eSchristos dns_name_t *
3329689912eSchristos dns_remote_tlsname(dns_remote_t *remote) {
3339689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3349689912eSchristos 
3359689912eSchristos 	if (remote->tlsnames == NULL) {
3369689912eSchristos 		return NULL;
3379689912eSchristos 	}
3389689912eSchristos 	if (remote->curraddr >= remote->addrcnt) {
3399689912eSchristos 		return NULL;
3409689912eSchristos 	}
3419689912eSchristos 
3429689912eSchristos 	return remote->tlsnames[remote->curraddr];
3439689912eSchristos }
3449689912eSchristos 
3459689912eSchristos void
3469689912eSchristos dns_remote_next(dns_remote_t *remote, bool skip_good) {
3479689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3489689912eSchristos 
3499689912eSchristos skip_to_next:
3509689912eSchristos 	remote->curraddr++;
3519689912eSchristos 
3529689912eSchristos 	if (remote->curraddr >= remote->addrcnt) {
3539689912eSchristos 		return;
3549689912eSchristos 	}
3559689912eSchristos 
3569689912eSchristos 	if (skip_good && remote->ok != NULL && remote->ok[remote->curraddr]) {
3579689912eSchristos 		goto skip_to_next;
3589689912eSchristos 	}
3599689912eSchristos }
3609689912eSchristos 
3619689912eSchristos bool
3629689912eSchristos dns_remote_done(dns_remote_t *remote) {
3639689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3649689912eSchristos 
3659689912eSchristos 	return remote->curraddr >= remote->addrcnt;
3669689912eSchristos }
3679689912eSchristos 
3689689912eSchristos void
3699689912eSchristos dns_remote_mark(dns_remote_t *remote, bool good) {
3709689912eSchristos 	REQUIRE(DNS_REMOTE_VALID(remote));
3719689912eSchristos 	REQUIRE(remote->curraddr < remote->addrcnt);
3729689912eSchristos 
3739689912eSchristos 	remote->ok[remote->curraddr] = good;
3749689912eSchristos }
375