3 Subroutines that support the generic object. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
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''.
35 #include <omapip/omapip_p.h>
37 OMAPI_OBJECT_ALLOC (omapi_generic
,
38 omapi_generic_object_t
, omapi_type_generic
)
40 isc_result_t
omapi_generic_new (omapi_object_t
**gen
,
41 const char *file
, int line
)
43 /* Backwards compatibility. */
44 return omapi_generic_allocate ((omapi_generic_object_t
**)gen
,
48 isc_result_t
omapi_generic_set_value (omapi_object_t
*h
,
50 omapi_data_string_t
*name
,
51 omapi_typed_data_t
*value
)
53 omapi_generic_object_t
*g
;
61 if (h
-> type
!= omapi_type_generic
)
62 return ISC_R_INVALIDARG
;
63 g
= (omapi_generic_object_t
*)h
;
65 /* See if there's already a value with this name attached to
66 the generic object, and if so, replace the current value
68 for (i
= 0; i
< g
-> nvalues
; i
++) {
69 if (!omapi_data_string_cmp (name
, g
-> values
[i
] -> name
)) {
70 /* There's an inconsistency here: the standard
71 behaviour of a set_values method when
72 passed a matching name and a null value is
73 to delete the value associated with that
74 name (where possible). In the generic
75 object, we remember the name/null pair,
76 because generic objects are generally used
77 to pass messages around, and this is the
78 way that remote entities delete values from
79 local objects. If the get_value method of
80 a generic object is called for a name that
81 maps to a name/null pair, ISC_R_NOTFOUND is
83 new = (omapi_value_t
*)0;
84 status
= (omapi_value_new (&new, MDL
));
85 if (status
!= ISC_R_SUCCESS
)
87 omapi_data_string_reference (&new -> name
, name
, MDL
);
89 omapi_typed_data_reference (&new -> value
,
92 omapi_value_dereference (&(g
-> values
[i
]), MDL
);
93 status
= (omapi_value_reference
94 (&(g
-> values
[i
]), new, MDL
));
95 omapi_value_dereference (&new, MDL
);
99 /* Notice a free slot if we pass one. */
100 else if (vfree
== -1 && !g
-> values
[i
])
104 /* If the name isn't already attached to this object, see if an
105 inner object has it. */
106 if (h
-> inner
&& h
-> inner
-> type
-> set_value
) {
107 status
= ((*(h
-> inner
-> type
-> set_value
))
108 (h
-> inner
, id
, name
, value
));
109 if (status
!= ISC_R_NOTFOUND
)
113 /* Okay, so it's a value that no inner object knows about, and
114 (implicitly, since the outer object set_value method would
115 have called this object's set_value method) it's an object that
116 no outer object knows about, it's this object's responsibility
117 to remember it - that's what generic objects do. */
119 /* Arrange for there to be space for the pointer to the new
120 name/value pair if necessary: */
122 vfree
= g
-> nvalues
;
123 if (vfree
== g
-> va_max
) {
125 vm_new
= 2 * g
-> va_max
;
128 va
= dmalloc (vm_new
* sizeof *va
, MDL
);
130 return ISC_R_NOMEMORY
;
131 ca
= dmalloc (vm_new
* sizeof *ca
, MDL
);
134 return ISC_R_NOMEMORY
;
137 memcpy (va
, g
-> values
,
138 g
-> va_max
* sizeof *va
);
139 memcpy (ca
, g
-> changed
,
140 g
-> va_max
* sizeof *ca
);
142 memset (va
+ g
-> va_max
, 0,
143 (vm_new
- g
-> va_max
) * sizeof *va
);
144 memset (ca
+ g
-> va_max
, 0,
145 (vm_new
- g
-> va_max
) * sizeof *ca
);
147 dfree (g
-> values
, MDL
);
149 dfree (g
-> changed
, MDL
);
152 g
-> va_max
= vm_new
;
155 status
= omapi_value_new (&g
-> values
[vfree
], MDL
);
156 if (status
!= ISC_R_SUCCESS
)
158 omapi_data_string_reference (&g
-> values
[vfree
] -> name
,
161 omapi_typed_data_reference
162 (&g
-> values
[vfree
] -> value
, value
, MDL
);
163 g
-> changed
[vfree
] = 1;
164 if (vfree
== g
-> nvalues
)
166 return ISC_R_SUCCESS
;
169 isc_result_t
omapi_generic_get_value (omapi_object_t
*h
,
171 omapi_data_string_t
*name
,
172 omapi_value_t
**value
)
175 omapi_generic_object_t
*g
;
177 if (h
-> type
!= omapi_type_generic
)
178 return ISC_R_INVALIDARG
;
179 g
= (omapi_generic_object_t
*)h
;
181 /* Look up the specified name in our list of objects. */
182 for (i
= 0; i
< g
-> nvalues
; i
++) {
185 if (!omapi_data_string_cmp (name
, g
-> values
[i
] -> name
)) {
186 /* If this is a name/null value pair, this is the
187 same as if there were no value that matched
188 the specified name, so return ISC_R_NOTFOUND. */
189 if (!g
-> values
[i
] -> value
)
190 return ISC_R_NOTFOUND
;
191 /* Otherwise, return the name/value pair. */
192 return omapi_value_reference (value
,
193 g
-> values
[i
], MDL
);
197 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
198 return (*(h
-> inner
-> type
-> get_value
))
199 (h
-> inner
, id
, name
, value
);
200 return ISC_R_NOTFOUND
;
203 isc_result_t
omapi_generic_destroy (omapi_object_t
*h
,
204 const char *file
, int line
)
206 omapi_generic_object_t
*g
;
209 if (h
-> type
!= omapi_type_generic
)
210 return ISC_R_UNEXPECTED
;
211 g
= (omapi_generic_object_t
*)h
;
214 for (i
= 0; i
< g
-> nvalues
; i
++) {
216 omapi_value_dereference (&g
-> values
[i
],
219 dfree (g
-> values
, file
, line
);
220 dfree (g
-> changed
, file
, line
);
221 g
-> values
= (omapi_value_t
**)0;
222 g
-> changed
= (u_int8_t
*)0;
226 return ISC_R_SUCCESS
;
229 isc_result_t
omapi_generic_signal_handler (omapi_object_t
*h
,
230 const char *name
, va_list ap
)
232 if (h
-> type
!= omapi_type_generic
)
233 return ISC_R_INVALIDARG
;
235 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
236 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
238 return ISC_R_NOTFOUND
;
241 /* Write all the published values associated with the object through the
242 specified connection. */
244 isc_result_t
omapi_generic_stuff_values (omapi_object_t
*c
,
248 omapi_generic_object_t
*src
;
252 if (g
-> type
!= omapi_type_generic
)
253 return ISC_R_INVALIDARG
;
254 src
= (omapi_generic_object_t
*)g
;
256 for (i
= 0; i
< src
-> nvalues
; i
++) {
257 if (src
-> values
[i
] && src
-> values
[i
] -> name
-> len
&&
258 src
-> changed
[i
]) {
259 status
= (omapi_connection_put_uint16
260 (c
, src
-> values
[i
] -> name
-> len
));
261 if (status
!= ISC_R_SUCCESS
)
263 status
= (omapi_connection_copyin
264 (c
, src
-> values
[i
] -> name
-> value
,
265 src
-> values
[i
] -> name
-> len
));
266 if (status
!= ISC_R_SUCCESS
)
269 status
= (omapi_connection_write_typed_data
270 (c
, src
-> values
[i
] -> value
));
271 if (status
!= ISC_R_SUCCESS
)
276 if (g
-> inner
&& g
-> inner
-> type
-> stuff_values
)
277 return (*(g
-> inner
-> type
-> stuff_values
)) (c
, id
,
279 return ISC_R_SUCCESS
;
282 /* Clear the changed flags on the object. This has the effect that if
283 generic_stuff is called, any attributes that still have a cleared changed
284 flag aren't sent to the peer. This also deletes any values that are
285 null, presuming that these have now been properly handled. */
287 isc_result_t
omapi_generic_clear_flags (omapi_object_t
*o
)
290 // isc_result_t status;
291 omapi_generic_object_t
*g
;
293 if (o
-> type
!= omapi_type_generic
)
294 return ISC_R_INVALIDARG
;
295 g
= (omapi_generic_object_t
*)o
;
297 for (i
= 0; i
< g
-> nvalues
; i
++) {
298 g
-> changed
[i
] = 0;
299 if (g
-> values
[i
] &&
300 !g
-> values
[i
] -> value
)
301 omapi_value_dereference (&g
-> values
[i
], MDL
);
303 return ISC_R_SUCCESS
;