]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* generic.c |
2 | ||
3 | Subroutines that support the generic object. */ | |
4 | ||
5 | /* | |
706792c9 | 6 | * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC") |
98311e4b | 7 | * Copyright (c) 1999-2003 by Internet Software Consortium |
61b844bf | 8 | * |
98311e4b DH |
9 | * Permission to use, copy, modify, and distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above | |
11 | * copyright notice and this permission notice appear in all copies. | |
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 DH |
21 | * Internet Systems Consortium, Inc. |
22 | * 950 Charter Street | |
23 | * Redwood City, CA 94063 | |
24 | * <info@isc.org> | |
25 | * http://www.isc.org/ | |
49733f31 | 26 | * |
98311e4b | 27 | * This software has been written for Internet Systems Consortium |
49733f31 | 28 | * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. |
98311e4b | 29 | * To learn more about Internet Systems Consortium, see |
49733f31 TL |
30 | * ``http://www.isc.org/''. To learn more about Vixie Enterprises, |
31 | * see ``http://www.vix.com''. To learn more about Nominum, Inc., see | |
32 | * ``http://www.nominum.com''. | |
61b844bf TL |
33 | */ |
34 | ||
fe5b0fdd DH |
35 | #include "dhcpd.h" |
36 | ||
6a4c4be8 | 37 | #include <omapip/omapip_p.h> |
61b844bf | 38 | |
20916cae TL |
39 | OMAPI_OBJECT_ALLOC (omapi_generic, |
40 | omapi_generic_object_t, omapi_type_generic) | |
41 | ||
4bd8800e TL |
42 | isc_result_t omapi_generic_new (omapi_object_t **gen, |
43 | const char *file, int line) | |
61b844bf | 44 | { |
20916cae TL |
45 | /* Backwards compatibility. */ |
46 | return omapi_generic_allocate ((omapi_generic_object_t **)gen, | |
47 | file, line); | |
61b844bf TL |
48 | } |
49 | ||
50 | isc_result_t omapi_generic_set_value (omapi_object_t *h, | |
51 | omapi_object_t *id, | |
52 | omapi_data_string_t *name, | |
53 | omapi_typed_data_t *value) | |
54 | { | |
55 | omapi_generic_object_t *g; | |
56 | omapi_value_t *new; | |
57 | omapi_value_t **va; | |
d758ad8c | 58 | u_int8_t *ca; |
61b844bf | 59 | int vm_new; |
d758ad8c | 60 | int i, vfree = -1; |
61b844bf TL |
61 | isc_result_t status; |
62 | ||
63 | if (h -> type != omapi_type_generic) | |
64 | return ISC_R_INVALIDARG; | |
65 | g = (omapi_generic_object_t *)h; | |
66 | ||
67 | /* See if there's already a value with this name attached to | |
68 | the generic object, and if so, replace the current value | |
69 | with the new one. */ | |
70 | for (i = 0; i < g -> nvalues; i++) { | |
71 | if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { | |
72 | /* There's an inconsistency here: the standard | |
73 | behaviour of a set_values method when | |
74 | passed a matching name and a null value is | |
75 | to delete the value associated with that | |
76 | name (where possible). In the generic | |
77 | object, we remember the name/null pair, | |
78 | because generic objects are generally used | |
79 | to pass messages around, and this is the | |
80 | way that remote entities delete values from | |
81 | local objects. If the get_value method of | |
82 | a generic object is called for a name that | |
83 | maps to a name/null pair, ISC_R_NOTFOUND is | |
84 | returned. */ | |
85 | new = (omapi_value_t *)0; | |
4bd8800e | 86 | status = (omapi_value_new (&new, MDL)); |
61b844bf TL |
87 | if (status != ISC_R_SUCCESS) |
88 | return status; | |
4bd8800e | 89 | omapi_data_string_reference (&new -> name, name, MDL); |
61b844bf | 90 | if (value) |
4bd8800e TL |
91 | omapi_typed_data_reference (&new -> value, |
92 | value, MDL); | |
61b844bf | 93 | |
4bd8800e | 94 | omapi_value_dereference (&(g -> values [i]), MDL); |
61b844bf | 95 | status = (omapi_value_reference |
4bd8800e TL |
96 | (&(g -> values [i]), new, MDL)); |
97 | omapi_value_dereference (&new, MDL); | |
d758ad8c | 98 | g -> changed [i] = 1; |
61b844bf TL |
99 | return status; |
100 | } | |
d758ad8c TL |
101 | /* Notice a free slot if we pass one. */ |
102 | else if (vfree == -1 && !g -> values [i]) | |
103 | vfree = i; | |
61b844bf TL |
104 | } |
105 | ||
106 | /* If the name isn't already attached to this object, see if an | |
107 | inner object has it. */ | |
581e37e4 | 108 | if (h -> inner && h -> inner -> type -> set_value) { |
61b844bf TL |
109 | status = ((*(h -> inner -> type -> set_value)) |
110 | (h -> inner, id, name, value)); | |
581e37e4 TL |
111 | if (status != ISC_R_NOTFOUND) |
112 | return status; | |
113 | } | |
61b844bf TL |
114 | |
115 | /* Okay, so it's a value that no inner object knows about, and | |
116 | (implicitly, since the outer object set_value method would | |
117 | have called this object's set_value method) it's an object that | |
118 | no outer object knows about, it's this object's responsibility | |
119 | to remember it - that's what generic objects do. */ | |
120 | ||
121 | /* Arrange for there to be space for the pointer to the new | |
122 | name/value pair if necessary: */ | |
d758ad8c TL |
123 | if (vfree == -1) { |
124 | vfree = g -> nvalues; | |
125 | if (vfree == g -> va_max) { | |
126 | if (g -> va_max) | |
127 | vm_new = 2 * g -> va_max; | |
128 | else | |
129 | vm_new = 10; | |
130 | va = dmalloc (vm_new * sizeof *va, MDL); | |
131 | if (!va) | |
132 | return ISC_R_NOMEMORY; | |
133 | ca = dmalloc (vm_new * sizeof *ca, MDL); | |
134 | if (!ca) { | |
135 | dfree (va, MDL); | |
136 | return ISC_R_NOMEMORY; | |
137 | } | |
138 | if (g -> va_max) { | |
139 | memcpy (va, g -> values, | |
140 | g -> va_max * sizeof *va); | |
141 | memcpy (ca, g -> changed, | |
142 | g -> va_max * sizeof *ca); | |
143 | } | |
144 | memset (va + g -> va_max, 0, | |
145 | (vm_new - g -> va_max) * sizeof *va); | |
146 | memset (ca + g -> va_max, 0, | |
147 | (vm_new - g -> va_max) * sizeof *ca); | |
148 | if (g -> values) | |
149 | dfree (g -> values, MDL); | |
150 | if (g -> changed) | |
151 | dfree (g -> changed, MDL); | |
152 | g -> values = va; | |
153 | g -> changed = ca; | |
154 | g -> va_max = vm_new; | |
155 | } | |
61b844bf | 156 | } |
d758ad8c | 157 | status = omapi_value_new (&g -> values [vfree], MDL); |
61b844bf TL |
158 | if (status != ISC_R_SUCCESS) |
159 | return status; | |
d758ad8c | 160 | omapi_data_string_reference (&g -> values [vfree] -> name, |
4bd8800e | 161 | name, MDL); |
61b844bf TL |
162 | if (value) |
163 | omapi_typed_data_reference | |
d758ad8c TL |
164 | (&g -> values [vfree] -> value, value, MDL); |
165 | g -> changed [vfree] = 1; | |
166 | if (vfree == g -> nvalues) | |
167 | g -> nvalues++; | |
61b844bf TL |
168 | return ISC_R_SUCCESS; |
169 | } | |
170 | ||
171 | isc_result_t omapi_generic_get_value (omapi_object_t *h, | |
172 | omapi_object_t *id, | |
173 | omapi_data_string_t *name, | |
174 | omapi_value_t **value) | |
175 | { | |
176 | int i; | |
177 | omapi_generic_object_t *g; | |
178 | ||
179 | if (h -> type != omapi_type_generic) | |
180 | return ISC_R_INVALIDARG; | |
181 | g = (omapi_generic_object_t *)h; | |
182 | ||
183 | /* Look up the specified name in our list of objects. */ | |
184 | for (i = 0; i < g -> nvalues; i++) { | |
98311e4b DH |
185 | if (!g -> values[i]) |
186 | continue; | |
61b844bf TL |
187 | if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { |
188 | /* If this is a name/null value pair, this is the | |
189 | same as if there were no value that matched | |
190 | the specified name, so return ISC_R_NOTFOUND. */ | |
191 | if (!g -> values [i] -> value) | |
192 | return ISC_R_NOTFOUND; | |
193 | /* Otherwise, return the name/value pair. */ | |
4bd8800e TL |
194 | return omapi_value_reference (value, |
195 | g -> values [i], MDL); | |
61b844bf TL |
196 | } |
197 | } | |
198 | ||
199 | if (h -> inner && h -> inner -> type -> get_value) | |
200 | return (*(h -> inner -> type -> get_value)) | |
201 | (h -> inner, id, name, value); | |
202 | return ISC_R_NOTFOUND; | |
203 | } | |
204 | ||
4bd8800e TL |
205 | isc_result_t omapi_generic_destroy (omapi_object_t *h, |
206 | const char *file, int line) | |
61b844bf TL |
207 | { |
208 | omapi_generic_object_t *g; | |
209 | int i; | |
210 | ||
211 | if (h -> type != omapi_type_generic) | |
212 | return ISC_R_UNEXPECTED; | |
213 | g = (omapi_generic_object_t *)h; | |
214 | ||
215 | if (g -> values) { | |
216 | for (i = 0; i < g -> nvalues; i++) { | |
217 | if (g -> values [i]) | |
218 | omapi_value_dereference (&g -> values [i], | |
4bd8800e | 219 | file, line); |
61b844bf | 220 | } |
4bd8800e | 221 | dfree (g -> values, file, line); |
d758ad8c | 222 | dfree (g -> changed, file, line); |
61b844bf | 223 | g -> values = (omapi_value_t **)0; |
d758ad8c | 224 | g -> changed = (u_int8_t *)0; |
61b844bf TL |
225 | g -> va_max = 0; |
226 | } | |
227 | ||
228 | return ISC_R_SUCCESS; | |
229 | } | |
230 | ||
231 | isc_result_t omapi_generic_signal_handler (omapi_object_t *h, | |
b1b7b521 | 232 | const char *name, va_list ap) |
61b844bf TL |
233 | { |
234 | if (h -> type != omapi_type_generic) | |
235 | return ISC_R_INVALIDARG; | |
236 | ||
237 | if (h -> inner && h -> inner -> type -> signal_handler) | |
238 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
239 | name, ap); | |
240 | return ISC_R_NOTFOUND; | |
241 | } | |
242 | ||
243 | /* Write all the published values associated with the object through the | |
244 | specified connection. */ | |
245 | ||
246 | isc_result_t omapi_generic_stuff_values (omapi_object_t *c, | |
247 | omapi_object_t *id, | |
248 | omapi_object_t *g) | |
249 | { | |
250 | omapi_generic_object_t *src; | |
251 | int i; | |
252 | isc_result_t status; | |
253 | ||
254 | if (g -> type != omapi_type_generic) | |
255 | return ISC_R_INVALIDARG; | |
256 | src = (omapi_generic_object_t *)g; | |
257 | ||
258 | for (i = 0; i < src -> nvalues; i++) { | |
d758ad8c TL |
259 | if (src -> values [i] && src -> values [i] -> name -> len && |
260 | src -> changed [i]) { | |
61b844bf TL |
261 | status = (omapi_connection_put_uint16 |
262 | (c, src -> values [i] -> name -> len)); | |
263 | if (status != ISC_R_SUCCESS) | |
264 | return status; | |
581e37e4 TL |
265 | status = (omapi_connection_copyin |
266 | (c, src -> values [i] -> name -> value, | |
61b844bf TL |
267 | src -> values [i] -> name -> len)); |
268 | if (status != ISC_R_SUCCESS) | |
269 | return status; | |
270 | ||
271 | status = (omapi_connection_write_typed_data | |
272 | (c, src -> values [i] -> value)); | |
273 | if (status != ISC_R_SUCCESS) | |
274 | return status; | |
275 | } | |
276 | } | |
277 | ||
278 | if (g -> inner && g -> inner -> type -> stuff_values) | |
279 | return (*(g -> inner -> type -> stuff_values)) (c, id, | |
280 | g -> inner); | |
281 | return ISC_R_SUCCESS; | |
282 | } | |
283 | ||
d758ad8c TL |
284 | /* Clear the changed flags on the object. This has the effect that if |
285 | generic_stuff is called, any attributes that still have a cleared changed | |
286 | flag aren't sent to the peer. This also deletes any values that are | |
287 | null, presuming that these have now been properly handled. */ | |
288 | ||
289 | isc_result_t omapi_generic_clear_flags (omapi_object_t *o) | |
290 | { | |
291 | int i; | |
d758ad8c TL |
292 | omapi_generic_object_t *g; |
293 | ||
294 | if (o -> type != omapi_type_generic) | |
295 | return ISC_R_INVALIDARG; | |
296 | g = (omapi_generic_object_t *)o; | |
297 | ||
298 | for (i = 0; i < g -> nvalues; i++) { | |
299 | g -> changed [i] = 0; | |
300 | if (g -> values [i] && | |
301 | !g -> values [i] -> value) | |
302 | omapi_value_dereference (&g -> values [i], MDL); | |
303 | } | |
304 | return ISC_R_SUCCESS; | |
305 | } |