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