]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/generic.c
copy rights update
[thirdparty/dhcp.git] / omapip / generic.c
CommitLineData
61b844bf
TL
1/* generic.c
2
3 Subroutines that support the generic object. */
4
5/*
49a7fb58 6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
98311e4b 7 * Copyright (c) 1999-2003 by Internet Software Consortium
61b844bf 8 *
7512d88b
TM
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
61b844bf 12 *
98311e4b
DH
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
61b844bf 20 *
98311e4b 21 * Internet Systems Consortium, Inc.
429a56d7
TM
22 * PO Box 360
23 * Newmarket, NH 03857 USA
98311e4b 24 * <info@isc.org>
2c85ac9b 25 * https://www.isc.org/
49733f31 26 *
61b844bf
TL
27 */
28
fe5b0fdd
DH
29#include "dhcpd.h"
30
6a4c4be8 31#include <omapip/omapip_p.h>
61b844bf 32
20916cae
TL
33OMAPI_OBJECT_ALLOC (omapi_generic,
34 omapi_generic_object_t, omapi_type_generic)
35
4bd8800e
TL
36isc_result_t omapi_generic_new (omapi_object_t **gen,
37 const char *file, int line)
61b844bf 38{
20916cae
TL
39 /* Backwards compatibility. */
40 return omapi_generic_allocate ((omapi_generic_object_t **)gen,
41 file, line);
61b844bf
TL
42}
43
44isc_result_t omapi_generic_set_value (omapi_object_t *h,
45 omapi_object_t *id,
46 omapi_data_string_t *name,
47 omapi_typed_data_t *value)
48{
49 omapi_generic_object_t *g;
50 omapi_value_t *new;
51 omapi_value_t **va;
d758ad8c 52 u_int8_t *ca;
61b844bf 53 int vm_new;
d758ad8c 54 int i, vfree = -1;
61b844bf
TL
55 isc_result_t status;
56
57 if (h -> type != omapi_type_generic)
98bf1607 58 return DHCP_R_INVALIDARG;
61b844bf
TL
59 g = (omapi_generic_object_t *)h;
60
61 /* See if there's already a value with this name attached to
62 the generic object, and if so, replace the current value
63 with the new one. */
64 for (i = 0; i < g -> nvalues; i++) {
48ffe4b8
TM
65 if (!g -> values[i])
66 continue;
67
61b844bf
TL
68 if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
69 /* There's an inconsistency here: the standard
70 behaviour of a set_values method when
71 passed a matching name and a null value is
72 to delete the value associated with that
73 name (where possible). In the generic
74 object, we remember the name/null pair,
75 because generic objects are generally used
76 to pass messages around, and this is the
77 way that remote entities delete values from
78 local objects. If the get_value method of
79 a generic object is called for a name that
80 maps to a name/null pair, ISC_R_NOTFOUND is
81 returned. */
82 new = (omapi_value_t *)0;
4bd8800e 83 status = (omapi_value_new (&new, MDL));
61b844bf
TL
84 if (status != ISC_R_SUCCESS)
85 return status;
4bd8800e 86 omapi_data_string_reference (&new -> name, name, MDL);
61b844bf 87 if (value)
4bd8800e
TL
88 omapi_typed_data_reference (&new -> value,
89 value, MDL);
61b844bf 90
4bd8800e 91 omapi_value_dereference (&(g -> values [i]), MDL);
61b844bf 92 status = (omapi_value_reference
4bd8800e
TL
93 (&(g -> values [i]), new, MDL));
94 omapi_value_dereference (&new, MDL);
d758ad8c 95 g -> changed [i] = 1;
61b844bf
TL
96 return status;
97 }
d758ad8c
TL
98 /* Notice a free slot if we pass one. */
99 else if (vfree == -1 && !g -> values [i])
100 vfree = i;
f6b8f48d 101 }
61b844bf
TL
102
103 /* If the name isn't already attached to this object, see if an
104 inner object has it. */
581e37e4 105 if (h -> inner && h -> inner -> type -> set_value) {
61b844bf
TL
106 status = ((*(h -> inner -> type -> set_value))
107 (h -> inner, id, name, value));
581e37e4
TL
108 if (status != ISC_R_NOTFOUND)
109 return status;
110 }
61b844bf
TL
111
112 /* Okay, so it's a value that no inner object knows about, and
113 (implicitly, since the outer object set_value method would
114 have called this object's set_value method) it's an object that
115 no outer object knows about, it's this object's responsibility
116 to remember it - that's what generic objects do. */
117
118 /* Arrange for there to be space for the pointer to the new
119 name/value pair if necessary: */
d758ad8c
TL
120 if (vfree == -1) {
121 vfree = g -> nvalues;
122 if (vfree == g -> va_max) {
123 if (g -> va_max)
124 vm_new = 2 * g -> va_max;
125 else
126 vm_new = 10;
127 va = dmalloc (vm_new * sizeof *va, MDL);
128 if (!va)
129 return ISC_R_NOMEMORY;
130 ca = dmalloc (vm_new * sizeof *ca, MDL);
131 if (!ca) {
132 dfree (va, MDL);
133 return ISC_R_NOMEMORY;
134 }
135 if (g -> va_max) {
136 memcpy (va, g -> values,
137 g -> va_max * sizeof *va);
138 memcpy (ca, g -> changed,
139 g -> va_max * sizeof *ca);
140 }
141 memset (va + g -> va_max, 0,
142 (vm_new - g -> va_max) * sizeof *va);
143 memset (ca + g -> va_max, 0,
144 (vm_new - g -> va_max) * sizeof *ca);
145 if (g -> values)
146 dfree (g -> values, MDL);
147 if (g -> changed)
148 dfree (g -> changed, MDL);
149 g -> values = va;
150 g -> changed = ca;
151 g -> va_max = vm_new;
152 }
61b844bf 153 }
d758ad8c 154 status = omapi_value_new (&g -> values [vfree], MDL);
61b844bf
TL
155 if (status != ISC_R_SUCCESS)
156 return status;
d758ad8c 157 omapi_data_string_reference (&g -> values [vfree] -> name,
4bd8800e 158 name, MDL);
61b844bf
TL
159 if (value)
160 omapi_typed_data_reference
d758ad8c
TL
161 (&g -> values [vfree] -> value, value, MDL);
162 g -> changed [vfree] = 1;
163 if (vfree == g -> nvalues)
164 g -> nvalues++;
61b844bf
TL
165 return ISC_R_SUCCESS;
166}
167
168isc_result_t omapi_generic_get_value (omapi_object_t *h,
169 omapi_object_t *id,
170 omapi_data_string_t *name,
171 omapi_value_t **value)
172{
173 int i;
174 omapi_generic_object_t *g;
175
176 if (h -> type != omapi_type_generic)
98bf1607 177 return DHCP_R_INVALIDARG;
61b844bf 178 g = (omapi_generic_object_t *)h;
f6b8f48d 179
61b844bf
TL
180 /* Look up the specified name in our list of objects. */
181 for (i = 0; i < g -> nvalues; i++) {
98311e4b
DH
182 if (!g -> values[i])
183 continue;
61b844bf
TL
184 if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
185 /* If this is a name/null value pair, this is the
186 same as if there were no value that matched
187 the specified name, so return ISC_R_NOTFOUND. */
188 if (!g -> values [i] -> value)
189 return ISC_R_NOTFOUND;
190 /* Otherwise, return the name/value pair. */
4bd8800e
TL
191 return omapi_value_reference (value,
192 g -> values [i], MDL);
61b844bf 193 }
f6b8f48d 194 }
61b844bf
TL
195
196 if (h -> inner && h -> inner -> type -> get_value)
197 return (*(h -> inner -> type -> get_value))
198 (h -> inner, id, name, value);
199 return ISC_R_NOTFOUND;
200}
201
4bd8800e
TL
202isc_result_t omapi_generic_destroy (omapi_object_t *h,
203 const char *file, int line)
61b844bf
TL
204{
205 omapi_generic_object_t *g;
206 int i;
207
208 if (h -> type != omapi_type_generic)
209 return ISC_R_UNEXPECTED;
210 g = (omapi_generic_object_t *)h;
f6b8f48d 211
61b844bf
TL
212 if (g -> values) {
213 for (i = 0; i < g -> nvalues; i++) {
214 if (g -> values [i])
215 omapi_value_dereference (&g -> values [i],
4bd8800e 216 file, line);
61b844bf 217 }
4bd8800e 218 dfree (g -> values, file, line);
d758ad8c 219 dfree (g -> changed, file, line);
61b844bf 220 g -> values = (omapi_value_t **)0;
d758ad8c 221 g -> changed = (u_int8_t *)0;
61b844bf
TL
222 g -> va_max = 0;
223 }
224
225 return ISC_R_SUCCESS;
226}
227
228isc_result_t omapi_generic_signal_handler (omapi_object_t *h,
b1b7b521 229 const char *name, va_list ap)
61b844bf
TL
230{
231 if (h -> type != omapi_type_generic)
98bf1607 232 return DHCP_R_INVALIDARG;
f6b8f48d 233
61b844bf
TL
234 if (h -> inner && h -> inner -> type -> signal_handler)
235 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
236 name, ap);
237 return ISC_R_NOTFOUND;
238}
239
240/* Write all the published values associated with the object through the
241 specified connection. */
242
243isc_result_t omapi_generic_stuff_values (omapi_object_t *c,
244 omapi_object_t *id,
245 omapi_object_t *g)
246{
247 omapi_generic_object_t *src;
248 int i;
249 isc_result_t status;
250
251 if (g -> type != omapi_type_generic)
98bf1607 252 return DHCP_R_INVALIDARG;
61b844bf 253 src = (omapi_generic_object_t *)g;
f6b8f48d 254
61b844bf 255 for (i = 0; i < src -> nvalues; i++) {
d758ad8c
TL
256 if (src -> values [i] && src -> values [i] -> name -> len &&
257 src -> changed [i]) {
61b844bf
TL
258 status = (omapi_connection_put_uint16
259 (c, src -> values [i] -> name -> len));
260 if (status != ISC_R_SUCCESS)
261 return status;
581e37e4
TL
262 status = (omapi_connection_copyin
263 (c, src -> values [i] -> name -> value,
61b844bf
TL
264 src -> values [i] -> name -> len));
265 if (status != ISC_R_SUCCESS)
266 return status;
267
268 status = (omapi_connection_write_typed_data
269 (c, src -> values [i] -> value));
270 if (status != ISC_R_SUCCESS)
271 return status;
272 }
f6b8f48d 273 }
61b844bf
TL
274
275 if (g -> inner && g -> inner -> type -> stuff_values)
276 return (*(g -> inner -> type -> stuff_values)) (c, id,
277 g -> inner);
278 return ISC_R_SUCCESS;
279}
280
d758ad8c
TL
281/* Clear the changed flags on the object. This has the effect that if
282 generic_stuff is called, any attributes that still have a cleared changed
283 flag aren't sent to the peer. This also deletes any values that are
284 null, presuming that these have now been properly handled. */
285
286isc_result_t omapi_generic_clear_flags (omapi_object_t *o)
287{
288 int i;
d758ad8c
TL
289 omapi_generic_object_t *g;
290
291 if (o -> type != omapi_type_generic)
98bf1607 292 return DHCP_R_INVALIDARG;
d758ad8c
TL
293 g = (omapi_generic_object_t *)o;
294
295 for (i = 0; i < g -> nvalues; i++) {
296 g -> changed [i] = 0;
297 if (g -> values [i] &&
298 !g -> values [i] -> value)
299 omapi_value_dereference (&g -> values [i], MDL);
300 }
301 return ISC_R_SUCCESS;
302}