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