3 Subroutines that support the generic object. */
6 * Copyright (c) 2004-2007,2009,2014 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/
31 #include <omapip/omapip_p.h>
33 OMAPI_OBJECT_ALLOC (omapi_generic
,
34 omapi_generic_object_t
, omapi_type_generic
)
36 isc_result_t
omapi_generic_new (omapi_object_t
**gen
,
37 const char *file
, int line
)
39 /* Backwards compatibility. */
40 return omapi_generic_allocate ((omapi_generic_object_t
**)gen
,
44 isc_result_t
omapi_generic_set_value (omapi_object_t
*h
,
46 omapi_data_string_t
*name
,
47 omapi_typed_data_t
*value
)
49 omapi_generic_object_t
*g
;
57 if (h
-> type
!= omapi_type_generic
)
58 return DHCP_R_INVALIDARG
;
59 g
= (omapi_generic_object_t
*)h
;
61 /* See if there's already a value with this name attached to
62 the generic object, and if so, replace the current value
64 for (i
= 0; i
< g
-> nvalues
; i
++) {
65 if (!omapi_data_string_cmp (name
, g
-> values
[i
] -> name
)) {
66 /* There's an inconsistency here: the standard
67 behaviour of a set_values method when
68 passed a matching name and a null value is
69 to delete the value associated with that
70 name (where possible). In the generic
71 object, we remember the name/null pair,
72 because generic objects are generally used
73 to pass messages around, and this is the
74 way that remote entities delete values from
75 local objects. If the get_value method of
76 a generic object is called for a name that
77 maps to a name/null pair, ISC_R_NOTFOUND is
79 new = (omapi_value_t
*)0;
80 status
= (omapi_value_new (&new, MDL
));
81 if (status
!= ISC_R_SUCCESS
)
83 omapi_data_string_reference (&new -> name
, name
, MDL
);
85 omapi_typed_data_reference (&new -> value
,
88 omapi_value_dereference (&(g
-> values
[i
]), MDL
);
89 status
= (omapi_value_reference
90 (&(g
-> values
[i
]), new, MDL
));
91 omapi_value_dereference (&new, MDL
);
95 /* Notice a free slot if we pass one. */
96 else if (vfree
== -1 && !g
-> values
[i
])
100 /* If the name isn't already attached to this object, see if an
101 inner object has it. */
102 if (h
-> inner
&& h
-> inner
-> type
-> set_value
) {
103 status
= ((*(h
-> inner
-> type
-> set_value
))
104 (h
-> inner
, id
, name
, value
));
105 if (status
!= ISC_R_NOTFOUND
)
109 /* Okay, so it's a value that no inner object knows about, and
110 (implicitly, since the outer object set_value method would
111 have called this object's set_value method) it's an object that
112 no outer object knows about, it's this object's responsibility
113 to remember it - that's what generic objects do. */
115 /* Arrange for there to be space for the pointer to the new
116 name/value pair if necessary: */
118 vfree
= g
-> nvalues
;
119 if (vfree
== g
-> va_max
) {
121 vm_new
= 2 * g
-> va_max
;
124 va
= dmalloc (vm_new
* sizeof *va
, MDL
);
126 return ISC_R_NOMEMORY
;
127 ca
= dmalloc (vm_new
* sizeof *ca
, MDL
);
130 return ISC_R_NOMEMORY
;
133 memcpy (va
, g
-> values
,
134 g
-> va_max
* sizeof *va
);
135 memcpy (ca
, g
-> changed
,
136 g
-> va_max
* sizeof *ca
);
138 memset (va
+ g
-> va_max
, 0,
139 (vm_new
- g
-> va_max
) * sizeof *va
);
140 memset (ca
+ g
-> va_max
, 0,
141 (vm_new
- g
-> va_max
) * sizeof *ca
);
143 dfree (g
-> values
, MDL
);
145 dfree (g
-> changed
, MDL
);
148 g
-> va_max
= vm_new
;
151 status
= omapi_value_new (&g
-> values
[vfree
], MDL
);
152 if (status
!= ISC_R_SUCCESS
)
154 omapi_data_string_reference (&g
-> values
[vfree
] -> name
,
157 omapi_typed_data_reference
158 (&g
-> values
[vfree
] -> value
, value
, MDL
);
159 g
-> changed
[vfree
] = 1;
160 if (vfree
== g
-> nvalues
)
162 return ISC_R_SUCCESS
;
165 isc_result_t
omapi_generic_get_value (omapi_object_t
*h
,
167 omapi_data_string_t
*name
,
168 omapi_value_t
**value
)
171 omapi_generic_object_t
*g
;
173 if (h
-> type
!= omapi_type_generic
)
174 return DHCP_R_INVALIDARG
;
175 g
= (omapi_generic_object_t
*)h
;
177 /* Look up the specified name in our list of objects. */
178 for (i
= 0; i
< g
-> nvalues
; i
++) {
181 if (!omapi_data_string_cmp (name
, g
-> values
[i
] -> name
)) {
182 /* If this is a name/null value pair, this is the
183 same as if there were no value that matched
184 the specified name, so return ISC_R_NOTFOUND. */
185 if (!g
-> values
[i
] -> value
)
186 return ISC_R_NOTFOUND
;
187 /* Otherwise, return the name/value pair. */
188 return omapi_value_reference (value
,
189 g
-> values
[i
], MDL
);
193 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
194 return (*(h
-> inner
-> type
-> get_value
))
195 (h
-> inner
, id
, name
, value
);
196 return ISC_R_NOTFOUND
;
199 isc_result_t
omapi_generic_destroy (omapi_object_t
*h
,
200 const char *file
, int line
)
202 omapi_generic_object_t
*g
;
205 if (h
-> type
!= omapi_type_generic
)
206 return ISC_R_UNEXPECTED
;
207 g
= (omapi_generic_object_t
*)h
;
210 for (i
= 0; i
< g
-> nvalues
; i
++) {
212 omapi_value_dereference (&g
-> values
[i
],
215 dfree (g
-> values
, file
, line
);
216 dfree (g
-> changed
, file
, line
);
217 g
-> values
= (omapi_value_t
**)0;
218 g
-> changed
= (u_int8_t
*)0;
222 return ISC_R_SUCCESS
;
225 isc_result_t
omapi_generic_signal_handler (omapi_object_t
*h
,
226 const char *name
, va_list ap
)
228 if (h
-> type
!= omapi_type_generic
)
229 return DHCP_R_INVALIDARG
;
231 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
232 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
234 return ISC_R_NOTFOUND
;
237 /* Write all the published values associated with the object through the
238 specified connection. */
240 isc_result_t
omapi_generic_stuff_values (omapi_object_t
*c
,
244 omapi_generic_object_t
*src
;
248 if (g
-> type
!= omapi_type_generic
)
249 return DHCP_R_INVALIDARG
;
250 src
= (omapi_generic_object_t
*)g
;
252 for (i
= 0; i
< src
-> nvalues
; i
++) {
253 if (src
-> values
[i
] && src
-> values
[i
] -> name
-> len
&&
254 src
-> changed
[i
]) {
255 status
= (omapi_connection_put_uint16
256 (c
, src
-> values
[i
] -> name
-> len
));
257 if (status
!= ISC_R_SUCCESS
)
259 status
= (omapi_connection_copyin
260 (c
, src
-> values
[i
] -> name
-> value
,
261 src
-> values
[i
] -> name
-> len
));
262 if (status
!= ISC_R_SUCCESS
)
265 status
= (omapi_connection_write_typed_data
266 (c
, src
-> values
[i
] -> value
));
267 if (status
!= ISC_R_SUCCESS
)
272 if (g
-> inner
&& g
-> inner
-> type
-> stuff_values
)
273 return (*(g
-> inner
-> type
-> stuff_values
)) (c
, id
,
275 return ISC_R_SUCCESS
;
278 /* Clear the changed flags on the object. This has the effect that if
279 generic_stuff is called, any attributes that still have a cleared changed
280 flag aren't sent to the peer. This also deletes any values that are
281 null, presuming that these have now been properly handled. */
283 isc_result_t
omapi_generic_clear_flags (omapi_object_t
*o
)
286 omapi_generic_object_t
*g
;
288 if (o
-> type
!= omapi_type_generic
)
289 return DHCP_R_INVALIDARG
;
290 g
= (omapi_generic_object_t
*)o
;
292 for (i
= 0; i
< g
-> nvalues
; i
++) {
293 g
-> changed
[i
] = 0;
294 if (g
-> values
[i
] &&
295 !g
-> values
[i
] -> value
)
296 omapi_value_dereference (&g
-> values
[i
], MDL
);
298 return ISC_R_SUCCESS
;