3 Subroutines that support the generic object. */
6 * Copyright (c) 2004-2007,2009 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
25 * https://www.isc.org/
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 * ``https://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''.
37 #include <omapip/omapip_p.h>
39 OMAPI_OBJECT_ALLOC (omapi_generic
,
40 omapi_generic_object_t
, omapi_type_generic
)
42 isc_result_t
omapi_generic_new (omapi_object_t
**gen
,
43 const char *file
, int line
)
45 /* Backwards compatibility. */
46 return omapi_generic_allocate ((omapi_generic_object_t
**)gen
,
50 isc_result_t
omapi_generic_set_value (omapi_object_t
*h
,
52 omapi_data_string_t
*name
,
53 omapi_typed_data_t
*value
)
55 omapi_generic_object_t
*g
;
63 if (h
-> type
!= omapi_type_generic
)
64 return DHCP_R_INVALIDARG
;
65 g
= (omapi_generic_object_t
*)h
;
67 /* See if there's already a value with this name attached to
68 the generic object, and if so, replace the current value
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
85 new = (omapi_value_t
*)0;
86 status
= (omapi_value_new (&new, MDL
));
87 if (status
!= ISC_R_SUCCESS
)
89 omapi_data_string_reference (&new -> name
, name
, MDL
);
91 omapi_typed_data_reference (&new -> value
,
94 omapi_value_dereference (&(g
-> values
[i
]), MDL
);
95 status
= (omapi_value_reference
96 (&(g
-> values
[i
]), new, MDL
));
97 omapi_value_dereference (&new, MDL
);
101 /* Notice a free slot if we pass one. */
102 else if (vfree
== -1 && !g
-> values
[i
])
106 /* If the name isn't already attached to this object, see if an
107 inner object has it. */
108 if (h
-> inner
&& h
-> inner
-> type
-> set_value
) {
109 status
= ((*(h
-> inner
-> type
-> set_value
))
110 (h
-> inner
, id
, name
, value
));
111 if (status
!= ISC_R_NOTFOUND
)
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. */
121 /* Arrange for there to be space for the pointer to the new
122 name/value pair if necessary: */
124 vfree
= g
-> nvalues
;
125 if (vfree
== g
-> va_max
) {
127 vm_new
= 2 * g
-> va_max
;
130 va
= dmalloc (vm_new
* sizeof *va
, MDL
);
132 return ISC_R_NOMEMORY
;
133 ca
= dmalloc (vm_new
* sizeof *ca
, MDL
);
136 return ISC_R_NOMEMORY
;
139 memcpy (va
, g
-> values
,
140 g
-> va_max
* sizeof *va
);
141 memcpy (ca
, g
-> changed
,
142 g
-> va_max
* sizeof *ca
);
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
);
149 dfree (g
-> values
, MDL
);
151 dfree (g
-> changed
, MDL
);
154 g
-> va_max
= vm_new
;
157 status
= omapi_value_new (&g
-> values
[vfree
], MDL
);
158 if (status
!= ISC_R_SUCCESS
)
160 omapi_data_string_reference (&g
-> values
[vfree
] -> name
,
163 omapi_typed_data_reference
164 (&g
-> values
[vfree
] -> value
, value
, MDL
);
165 g
-> changed
[vfree
] = 1;
166 if (vfree
== g
-> nvalues
)
168 return ISC_R_SUCCESS
;
171 isc_result_t
omapi_generic_get_value (omapi_object_t
*h
,
173 omapi_data_string_t
*name
,
174 omapi_value_t
**value
)
177 omapi_generic_object_t
*g
;
179 if (h
-> type
!= omapi_type_generic
)
180 return DHCP_R_INVALIDARG
;
181 g
= (omapi_generic_object_t
*)h
;
183 /* Look up the specified name in our list of objects. */
184 for (i
= 0; i
< g
-> nvalues
; i
++) {
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. */
194 return omapi_value_reference (value
,
195 g
-> values
[i
], MDL
);
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
;
205 isc_result_t
omapi_generic_destroy (omapi_object_t
*h
,
206 const char *file
, int line
)
208 omapi_generic_object_t
*g
;
211 if (h
-> type
!= omapi_type_generic
)
212 return ISC_R_UNEXPECTED
;
213 g
= (omapi_generic_object_t
*)h
;
216 for (i
= 0; i
< g
-> nvalues
; i
++) {
218 omapi_value_dereference (&g
-> values
[i
],
221 dfree (g
-> values
, file
, line
);
222 dfree (g
-> changed
, file
, line
);
223 g
-> values
= (omapi_value_t
**)0;
224 g
-> changed
= (u_int8_t
*)0;
228 return ISC_R_SUCCESS
;
231 isc_result_t
omapi_generic_signal_handler (omapi_object_t
*h
,
232 const char *name
, va_list ap
)
234 if (h
-> type
!= omapi_type_generic
)
235 return DHCP_R_INVALIDARG
;
237 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
238 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
240 return ISC_R_NOTFOUND
;
243 /* Write all the published values associated with the object through the
244 specified connection. */
246 isc_result_t
omapi_generic_stuff_values (omapi_object_t
*c
,
250 omapi_generic_object_t
*src
;
254 if (g
-> type
!= omapi_type_generic
)
255 return DHCP_R_INVALIDARG
;
256 src
= (omapi_generic_object_t
*)g
;
258 for (i
= 0; i
< src
-> nvalues
; i
++) {
259 if (src
-> values
[i
] && src
-> values
[i
] -> name
-> len
&&
260 src
-> changed
[i
]) {
261 status
= (omapi_connection_put_uint16
262 (c
, src
-> values
[i
] -> name
-> len
));
263 if (status
!= ISC_R_SUCCESS
)
265 status
= (omapi_connection_copyin
266 (c
, src
-> values
[i
] -> name
-> value
,
267 src
-> values
[i
] -> name
-> len
));
268 if (status
!= ISC_R_SUCCESS
)
271 status
= (omapi_connection_write_typed_data
272 (c
, src
-> values
[i
] -> value
));
273 if (status
!= ISC_R_SUCCESS
)
278 if (g
-> inner
&& g
-> inner
-> type
-> stuff_values
)
279 return (*(g
-> inner
-> type
-> stuff_values
)) (c
, id
,
281 return ISC_R_SUCCESS
;
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. */
289 isc_result_t
omapi_generic_clear_flags (omapi_object_t
*o
)
292 omapi_generic_object_t
*g
;
294 if (o
-> type
!= omapi_type_generic
)
295 return DHCP_R_INVALIDARG
;
296 g
= (omapi_generic_object_t
*)o
;
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
);
304 return ISC_R_SUCCESS
;