xref: /netbsd-src/external/mpl/bind/dist/lib/dns/remote.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: remote.c,v 1.2 2025/01/26 16:25:24 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 /*! \file */
17 
18 #include <stdbool.h>
19 #include <string.h>
20 
21 #include <isc/result.h>
22 #include <isc/sockaddr.h>
23 #include <isc/types.h>
24 #include <isc/util.h>
25 
26 #include <dns/name.h>
27 #include <dns/remote.h>
28 #include <dns/types.h>
29 
30 isc_sockaddr_t *
31 dns_remote_addresses(dns_remote_t *remote) {
32 	REQUIRE(DNS_REMOTE_VALID(remote));
33 	return remote->addresses;
34 }
35 
36 isc_sockaddr_t *
37 dns_remote_sources(dns_remote_t *remote) {
38 	REQUIRE(DNS_REMOTE_VALID(remote));
39 	return remote->sources;
40 }
41 
42 unsigned int
43 dns_remote_count(dns_remote_t *remote) {
44 	REQUIRE(DNS_REMOTE_VALID(remote));
45 	return remote->addrcnt;
46 }
47 
48 dns_name_t **
49 dns_remote_keynames(dns_remote_t *remote) {
50 	REQUIRE(DNS_REMOTE_VALID(remote));
51 	return remote->keynames;
52 }
53 
54 dns_name_t **
55 dns_remote_tlsnames(dns_remote_t *remote) {
56 	REQUIRE(DNS_REMOTE_VALID(remote));
57 	return remote->tlsnames;
58 }
59 
60 void
61 dns_remote_init(dns_remote_t *remote, unsigned int count,
62 		const isc_sockaddr_t *addrs, const isc_sockaddr_t *srcs,
63 		dns_name_t **keynames, dns_name_t **tlsnames, bool mark,
64 		isc_mem_t *mctx) {
65 	unsigned int i;
66 
67 	REQUIRE(DNS_REMOTE_VALID(remote));
68 	REQUIRE(count == 0 || addrs != NULL);
69 
70 	if (keynames != NULL || tlsnames != NULL) {
71 		REQUIRE(count != 0);
72 	}
73 
74 	remote->mctx = mctx;
75 
76 	if (addrs != NULL) {
77 		remote->addresses = isc_mem_cget(mctx, count,
78 						 sizeof(isc_sockaddr_t));
79 		memmove(remote->addresses, addrs,
80 			count * sizeof(isc_sockaddr_t));
81 	} else {
82 		remote->addresses = NULL;
83 	}
84 
85 	if (srcs != NULL) {
86 		remote->sources = isc_mem_cget(mctx, count,
87 					       sizeof(isc_sockaddr_t));
88 		memmove(remote->sources, srcs, count * sizeof(isc_sockaddr_t));
89 	} else {
90 		remote->sources = NULL;
91 	}
92 
93 	if (keynames != NULL) {
94 		remote->keynames = isc_mem_cget(mctx, count,
95 						sizeof(keynames[0]));
96 		for (i = 0; i < count; i++) {
97 			remote->keynames[i] = NULL;
98 		}
99 		for (i = 0; i < count; i++) {
100 			if (keynames[i] != NULL) {
101 				remote->keynames[i] =
102 					isc_mem_get(mctx, sizeof(dns_name_t));
103 				dns_name_init(remote->keynames[i], NULL);
104 				dns_name_dup(keynames[i], mctx,
105 					     remote->keynames[i]);
106 			}
107 		}
108 	} else {
109 		remote->keynames = NULL;
110 	}
111 
112 	if (tlsnames != NULL) {
113 		remote->tlsnames = isc_mem_cget(mctx, count,
114 						sizeof(tlsnames[0]));
115 		for (i = 0; i < count; i++) {
116 			remote->tlsnames[i] = NULL;
117 		}
118 		for (i = 0; i < count; i++) {
119 			if (tlsnames[i] != NULL) {
120 				remote->tlsnames[i] =
121 					isc_mem_get(mctx, sizeof(dns_name_t));
122 				dns_name_init(remote->tlsnames[i], NULL);
123 				dns_name_dup(tlsnames[i], mctx,
124 					     remote->tlsnames[i]);
125 			}
126 		}
127 	} else {
128 		remote->tlsnames = NULL;
129 	}
130 
131 	if (mark) {
132 		remote->ok = isc_mem_cget(mctx, count, sizeof(bool));
133 		for (i = 0; i < count; i++) {
134 			remote->ok[i] = false;
135 		}
136 	} else {
137 		remote->ok = NULL;
138 	}
139 
140 	remote->addrcnt = count;
141 	remote->curraddr = 0;
142 }
143 
144 static bool
145 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
146 	   uint32_t count) {
147 	unsigned int i;
148 
149 	if (oldlist == NULL && newlist == NULL) {
150 		return true;
151 	}
152 	if (oldlist == NULL || newlist == NULL) {
153 		return false;
154 	}
155 
156 	for (i = 0; i < count; i++) {
157 		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
158 			return false;
159 		}
160 	}
161 	return true;
162 }
163 
164 static bool
165 same_names(dns_name_t *const *oldlist, dns_name_t *const *newlist,
166 	   uint32_t count) {
167 	unsigned int i;
168 
169 	if (oldlist == NULL && newlist == NULL) {
170 		return true;
171 	}
172 	if (oldlist == NULL || newlist == NULL) {
173 		return false;
174 	}
175 
176 	for (i = 0; i < count; i++) {
177 		if (oldlist[i] == NULL && newlist[i] == NULL) {
178 			continue;
179 		}
180 		if (oldlist[i] == NULL || newlist[i] == NULL ||
181 		    !dns_name_equal(oldlist[i], newlist[i]))
182 		{
183 			return false;
184 		}
185 	}
186 	return true;
187 }
188 
189 void
190 dns_remote_clear(dns_remote_t *remote) {
191 	unsigned int count;
192 	isc_mem_t *mctx;
193 
194 	REQUIRE(DNS_REMOTE_VALID(remote));
195 
196 	count = remote->addrcnt;
197 	mctx = remote->mctx;
198 
199 	if (mctx == NULL) {
200 		return;
201 	}
202 
203 	if (remote->ok != NULL) {
204 		isc_mem_cput(mctx, remote->ok, count, sizeof(bool));
205 		remote->ok = NULL;
206 	}
207 
208 	if (remote->addresses != NULL) {
209 		isc_mem_cput(mctx, remote->addresses, count,
210 			     sizeof(isc_sockaddr_t));
211 		remote->addresses = NULL;
212 	}
213 
214 	if (remote->sources != NULL) {
215 		isc_mem_cput(mctx, remote->sources, count,
216 			     sizeof(isc_sockaddr_t));
217 		remote->sources = NULL;
218 	}
219 
220 	if (remote->keynames != NULL) {
221 		unsigned int i;
222 		for (i = 0; i < count; i++) {
223 			if (remote->keynames[i] != NULL) {
224 				dns_name_free(remote->keynames[i], mctx);
225 				isc_mem_put(mctx, remote->keynames[i],
226 					    sizeof(dns_name_t));
227 				remote->keynames[i] = NULL;
228 			}
229 		}
230 		isc_mem_cput(mctx, remote->keynames, count,
231 			     sizeof(dns_name_t *));
232 		remote->keynames = NULL;
233 	}
234 
235 	if (remote->tlsnames != NULL) {
236 		unsigned int i;
237 		for (i = 0; i < count; i++) {
238 			if (remote->tlsnames[i] != NULL) {
239 				dns_name_free(remote->tlsnames[i], mctx);
240 				isc_mem_put(mctx, remote->tlsnames[i],
241 					    sizeof(dns_name_t));
242 				remote->tlsnames[i] = NULL;
243 			}
244 		}
245 		isc_mem_cput(mctx, remote->tlsnames, count,
246 			     sizeof(dns_name_t *));
247 		remote->tlsnames = NULL;
248 	}
249 
250 	remote->curraddr = 0;
251 	remote->addrcnt = 0;
252 	remote->mctx = NULL;
253 }
254 
255 bool
256 dns_remote_equal(dns_remote_t *a, dns_remote_t *b) {
257 	REQUIRE(DNS_REMOTE_VALID(a));
258 	REQUIRE(DNS_REMOTE_VALID(b));
259 
260 	if (a->addrcnt != b->addrcnt) {
261 		return false;
262 	}
263 
264 	if (!same_addrs(a->addresses, b->addresses, a->addrcnt)) {
265 		return false;
266 	}
267 	if (!same_names(a->keynames, b->keynames, a->addrcnt)) {
268 		return false;
269 	}
270 	if (!same_names(a->tlsnames, b->tlsnames, a->addrcnt)) {
271 		return false;
272 	}
273 
274 	return true;
275 }
276 
277 void
278 dns_remote_reset(dns_remote_t *remote, bool clear_ok) {
279 	REQUIRE(DNS_REMOTE_VALID(remote));
280 
281 	remote->curraddr = 0;
282 
283 	if (clear_ok && remote->ok != NULL) {
284 		for (unsigned int i = 0; i < remote->addrcnt; i++) {
285 			remote->ok[i] = false;
286 		}
287 	}
288 }
289 
290 isc_sockaddr_t
291 dns_remote_curraddr(dns_remote_t *remote) {
292 	REQUIRE(DNS_REMOTE_VALID(remote));
293 	REQUIRE(remote->addresses != NULL);
294 	REQUIRE(remote->curraddr < remote->addrcnt);
295 
296 	return remote->addresses[remote->curraddr];
297 }
298 
299 isc_sockaddr_t
300 dns_remote_addr(dns_remote_t *remote, unsigned int i) {
301 	REQUIRE(DNS_REMOTE_VALID(remote));
302 	REQUIRE(remote->addresses != NULL);
303 	REQUIRE(i < remote->addrcnt);
304 
305 	return remote->addresses[i];
306 }
307 
308 isc_sockaddr_t
309 dns_remote_sourceaddr(dns_remote_t *remote) {
310 	REQUIRE(DNS_REMOTE_VALID(remote));
311 	REQUIRE(remote->sources != NULL);
312 	REQUIRE(remote->curraddr < remote->addrcnt);
313 
314 	return remote->sources[remote->curraddr];
315 }
316 
317 dns_name_t *
318 dns_remote_keyname(dns_remote_t *remote) {
319 	REQUIRE(DNS_REMOTE_VALID(remote));
320 
321 	if (remote->keynames == NULL) {
322 		return NULL;
323 	}
324 	if (remote->curraddr >= remote->addrcnt) {
325 		return NULL;
326 	}
327 
328 	return remote->keynames[remote->curraddr];
329 }
330 
331 dns_name_t *
332 dns_remote_tlsname(dns_remote_t *remote) {
333 	REQUIRE(DNS_REMOTE_VALID(remote));
334 
335 	if (remote->tlsnames == NULL) {
336 		return NULL;
337 	}
338 	if (remote->curraddr >= remote->addrcnt) {
339 		return NULL;
340 	}
341 
342 	return remote->tlsnames[remote->curraddr];
343 }
344 
345 void
346 dns_remote_next(dns_remote_t *remote, bool skip_good) {
347 	REQUIRE(DNS_REMOTE_VALID(remote));
348 
349 skip_to_next:
350 	remote->curraddr++;
351 
352 	if (remote->curraddr >= remote->addrcnt) {
353 		return;
354 	}
355 
356 	if (skip_good && remote->ok != NULL && remote->ok[remote->curraddr]) {
357 		goto skip_to_next;
358 	}
359 }
360 
361 bool
362 dns_remote_done(dns_remote_t *remote) {
363 	REQUIRE(DNS_REMOTE_VALID(remote));
364 
365 	return remote->curraddr >= remote->addrcnt;
366 }
367 
368 void
369 dns_remote_mark(dns_remote_t *remote, bool good) {
370 	REQUIRE(DNS_REMOTE_VALID(remote));
371 	REQUIRE(remote->curraddr < remote->addrcnt);
372 
373 	remote->ok[remote->curraddr] = good;
374 }
375