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