1/*	$NetBSD: ipkeylist.c,v 1.7 2024/02/21 22:52:06 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 <string.h>
18
19#include <isc/mem.h>
20#include <isc/sockaddr.h>
21#include <isc/util.h>
22
23#include <dns/ipkeylist.h>
24#include <dns/name.h>
25
26void
27dns_ipkeylist_init(dns_ipkeylist_t *ipkl) {
28	ipkl->count = 0;
29	ipkl->allocated = 0;
30	ipkl->addrs = NULL;
31	ipkl->keys = NULL;
32	ipkl->tlss = NULL;
33	ipkl->labels = NULL;
34}
35
36void
37dns_ipkeylist_clear(isc_mem_t *mctx, dns_ipkeylist_t *ipkl) {
38	uint32_t i;
39
40	REQUIRE(ipkl != NULL);
41
42	if (ipkl->allocated == 0) {
43		return;
44	}
45
46	if (ipkl->addrs != NULL) {
47		isc_mem_put(mctx, ipkl->addrs,
48			    ipkl->allocated * sizeof(isc_sockaddr_t));
49	}
50
51	if (ipkl->keys != NULL) {
52		for (i = 0; i < ipkl->allocated; i++) {
53			if (ipkl->keys[i] == NULL) {
54				continue;
55			}
56			if (dns_name_dynamic(ipkl->keys[i])) {
57				dns_name_free(ipkl->keys[i], mctx);
58			}
59			isc_mem_put(mctx, ipkl->keys[i], sizeof(dns_name_t));
60		}
61		isc_mem_put(mctx, ipkl->keys,
62			    ipkl->allocated * sizeof(dns_name_t *));
63	}
64
65	if (ipkl->tlss != NULL) {
66		for (i = 0; i < ipkl->allocated; i++) {
67			if (ipkl->tlss[i] == NULL) {
68				continue;
69			}
70			if (dns_name_dynamic(ipkl->tlss[i])) {
71				dns_name_free(ipkl->tlss[i], mctx);
72			}
73			isc_mem_put(mctx, ipkl->tlss[i], sizeof(dns_name_t));
74		}
75		isc_mem_put(mctx, ipkl->tlss,
76			    ipkl->allocated * sizeof(dns_name_t *));
77	}
78
79	if (ipkl->labels != NULL) {
80		for (i = 0; i < ipkl->allocated; i++) {
81			if (ipkl->labels[i] == NULL) {
82				continue;
83			}
84			if (dns_name_dynamic(ipkl->labels[i])) {
85				dns_name_free(ipkl->labels[i], mctx);
86			}
87			isc_mem_put(mctx, ipkl->labels[i], sizeof(dns_name_t));
88		}
89		isc_mem_put(mctx, ipkl->labels,
90			    ipkl->allocated * sizeof(dns_name_t *));
91	}
92
93	dns_ipkeylist_init(ipkl);
94}
95
96isc_result_t
97dns_ipkeylist_copy(isc_mem_t *mctx, const dns_ipkeylist_t *src,
98		   dns_ipkeylist_t *dst) {
99	isc_result_t result = ISC_R_SUCCESS;
100	uint32_t i;
101
102	REQUIRE(dst != NULL);
103	/* dst might be preallocated, we don't care, but it must be empty */
104	REQUIRE(dst->count == 0);
105
106	if (src->count == 0) {
107		return (ISC_R_SUCCESS);
108	}
109
110	result = dns_ipkeylist_resize(mctx, dst, src->count);
111	if (result != ISC_R_SUCCESS) {
112		return (result);
113	}
114
115	memmove(dst->addrs, src->addrs, src->count * sizeof(isc_sockaddr_t));
116
117	if (src->keys != NULL) {
118		for (i = 0; i < src->count; i++) {
119			if (src->keys[i] != NULL) {
120				dst->keys[i] = isc_mem_get(mctx,
121							   sizeof(dns_name_t));
122				dns_name_init(dst->keys[i], NULL);
123				dns_name_dup(src->keys[i], mctx, dst->keys[i]);
124			} else {
125				dst->keys[i] = NULL;
126			}
127		}
128	}
129
130	if (src->tlss != NULL) {
131		for (i = 0; i < src->count; i++) {
132			if (src->tlss[i] != NULL) {
133				dst->tlss[i] = isc_mem_get(mctx,
134							   sizeof(dns_name_t));
135				dns_name_init(dst->tlss[i], NULL);
136				dns_name_dup(src->tlss[i], mctx, dst->tlss[i]);
137			} else {
138				dst->tlss[i] = NULL;
139			}
140		}
141	}
142
143	if (src->labels != NULL) {
144		for (i = 0; i < src->count; i++) {
145			if (src->labels[i] != NULL) {
146				dst->labels[i] =
147					isc_mem_get(mctx, sizeof(dns_name_t));
148				dns_name_init(dst->labels[i], NULL);
149				dns_name_dup(src->labels[i], mctx,
150					     dst->labels[i]);
151			} else {
152				dst->labels[i] = NULL;
153			}
154		}
155	}
156	dst->count = src->count;
157	return (ISC_R_SUCCESS);
158}
159
160isc_result_t
161dns_ipkeylist_resize(isc_mem_t *mctx, dns_ipkeylist_t *ipkl, unsigned int n) {
162	isc_sockaddr_t *addrs = NULL;
163	dns_name_t **keys = NULL;
164	dns_name_t **tlss = NULL;
165	dns_name_t **labels = NULL;
166
167	REQUIRE(ipkl != NULL);
168	REQUIRE(n > ipkl->count);
169
170	if (n <= ipkl->allocated) {
171		return (ISC_R_SUCCESS);
172	}
173
174	addrs = isc_mem_get(mctx, n * sizeof(isc_sockaddr_t));
175	keys = isc_mem_get(mctx, n * sizeof(dns_name_t *));
176	tlss = isc_mem_get(mctx, n * sizeof(dns_name_t *));
177	labels = isc_mem_get(mctx, n * sizeof(dns_name_t *));
178
179	if (ipkl->addrs != NULL) {
180		memmove(addrs, ipkl->addrs,
181			ipkl->allocated * sizeof(isc_sockaddr_t));
182		isc_mem_put(mctx, ipkl->addrs,
183			    ipkl->allocated * sizeof(isc_sockaddr_t));
184	}
185	ipkl->addrs = addrs;
186	memset(&ipkl->addrs[ipkl->allocated], 0,
187	       (n - ipkl->allocated) * sizeof(isc_sockaddr_t));
188
189	if (ipkl->keys) {
190		memmove(keys, ipkl->keys,
191			ipkl->allocated * sizeof(dns_name_t *));
192		isc_mem_put(mctx, ipkl->keys,
193			    ipkl->allocated * sizeof(dns_name_t *));
194	}
195	ipkl->keys = keys;
196	memset(&ipkl->keys[ipkl->allocated], 0,
197	       (n - ipkl->allocated) * sizeof(dns_name_t *));
198
199	if (ipkl->tlss) {
200		memmove(tlss, ipkl->tlss,
201			ipkl->allocated * sizeof(dns_name_t *));
202		isc_mem_put(mctx, ipkl->tlss,
203			    ipkl->allocated * sizeof(dns_name_t *));
204	}
205	ipkl->tlss = tlss;
206	memset(&ipkl->tlss[ipkl->allocated], 0,
207	       (n - ipkl->allocated) * sizeof(dns_name_t *));
208
209	if (ipkl->labels != NULL) {
210		memmove(labels, ipkl->labels,
211			ipkl->allocated * sizeof(dns_name_t *));
212		isc_mem_put(mctx, ipkl->labels,
213			    ipkl->allocated * sizeof(dns_name_t *));
214	}
215	ipkl->labels = labels;
216	memset(&ipkl->labels[ipkl->allocated], 0,
217	       (n - ipkl->allocated) * sizeof(dns_name_t *));
218
219	ipkl->allocated = n;
220	return (ISC_R_SUCCESS);
221
222	isc_mem_put(mctx, addrs, n * sizeof(isc_sockaddr_t));
223	isc_mem_put(mctx, tlss, n * sizeof(dns_name_t *));
224	isc_mem_put(mctx, keys, n * sizeof(dns_name_t *));
225	isc_mem_put(mctx, labels, n * sizeof(dns_name_t *));
226
227	return (ISC_R_NOMEMORY);
228}
229