]> git.ipfire.org Git - thirdparty/dhcp.git/blob - omapip/generic.c
73d39346f27fe0e3b4ffd303e94b25a086568685
[thirdparty/dhcp.git] / omapip / generic.c
1 /* generic.c
2
3 Subroutines that support the generic object. */
4
5 /*
6 * Copyright (c) 1996-2000 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
12 *
13 * http://www.isc.org/isc-license-1.0.html.
14 *
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
18 *
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
21 */
22
23 #include <omapip/omapip_p.h>
24
25 isc_result_t omapi_generic_new (omapi_object_t **gen,
26 const char *file, int line)
27 {
28 omapi_generic_object_t *obj;
29
30 obj = dmalloc (sizeof *obj, file, line);
31 if (!obj)
32 return ISC_R_NOMEMORY;
33 memset (obj, 0, sizeof *obj);
34 obj -> refcnt = 0;
35 obj -> type = omapi_type_generic;
36
37 return omapi_object_reference (gen, (omapi_object_t *)obj, file, line);
38 }
39
40 isc_result_t omapi_generic_set_value (omapi_object_t *h,
41 omapi_object_t *id,
42 omapi_data_string_t *name,
43 omapi_typed_data_t *value)
44 {
45 omapi_generic_object_t *g;
46 omapi_value_t *new;
47 omapi_value_t **va;
48 int vm_new;
49 int i;
50 isc_result_t status;
51
52 if (h -> type != omapi_type_generic)
53 return ISC_R_INVALIDARG;
54 g = (omapi_generic_object_t *)h;
55
56 /* See if there's already a value with this name attached to
57 the generic object, and if so, replace the current value
58 with the new one. */
59 for (i = 0; i < g -> nvalues; i++) {
60 if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
61 /* There's an inconsistency here: the standard
62 behaviour of a set_values method when
63 passed a matching name and a null value is
64 to delete the value associated with that
65 name (where possible). In the generic
66 object, we remember the name/null pair,
67 because generic objects are generally used
68 to pass messages around, and this is the
69 way that remote entities delete values from
70 local objects. If the get_value method of
71 a generic object is called for a name that
72 maps to a name/null pair, ISC_R_NOTFOUND is
73 returned. */
74 new = (omapi_value_t *)0;
75 status = (omapi_value_new (&new, MDL));
76 if (status != ISC_R_SUCCESS)
77 return status;
78 omapi_data_string_reference (&new -> name, name, MDL);
79 if (value)
80 omapi_typed_data_reference (&new -> value,
81 value, MDL);
82
83 omapi_value_dereference (&(g -> values [i]), MDL);
84 status = (omapi_value_reference
85 (&(g -> values [i]), new, MDL));
86 omapi_value_dereference (&new, MDL);
87 return status;
88 }
89 }
90
91 /* If the name isn't already attached to this object, see if an
92 inner object has it. */
93 if (h -> inner && h -> inner -> type -> set_value) {
94 status = ((*(h -> inner -> type -> set_value))
95 (h -> inner, id, name, value));
96 if (status != ISC_R_NOTFOUND)
97 return status;
98 }
99
100 /* Okay, so it's a value that no inner object knows about, and
101 (implicitly, since the outer object set_value method would
102 have called this object's set_value method) it's an object that
103 no outer object knows about, it's this object's responsibility
104 to remember it - that's what generic objects do. */
105
106 /* Arrange for there to be space for the pointer to the new
107 name/value pair if necessary: */
108 if (g -> nvalues == g -> va_max) {
109 if (g -> va_max)
110 vm_new = 2 * g -> va_max;
111 else
112 vm_new = 10;
113 va = dmalloc (vm_new * sizeof *va, MDL);
114 if (!va)
115 return ISC_R_NOMEMORY;
116 if (g -> va_max)
117 memcpy (va, g -> values, g -> va_max * sizeof *va);
118 memset (va + g -> va_max, 0,
119 (vm_new - g -> va_max) * sizeof *va);
120 if (g -> values)
121 dfree (g -> values, MDL);
122 g -> values = va;
123 g -> va_max = vm_new;
124 }
125 status = omapi_value_new (&g -> values [g -> nvalues], MDL);
126 if (status != ISC_R_SUCCESS)
127 return status;
128 omapi_data_string_reference (&g -> values [g -> nvalues] -> name,
129 name, MDL);
130 if (value)
131 omapi_typed_data_reference
132 (&g -> values [g -> nvalues] -> value, value, MDL);
133 g -> nvalues++;
134 return ISC_R_SUCCESS;
135 }
136
137 isc_result_t omapi_generic_get_value (omapi_object_t *h,
138 omapi_object_t *id,
139 omapi_data_string_t *name,
140 omapi_value_t **value)
141 {
142 int i;
143 omapi_generic_object_t *g;
144
145 if (h -> type != omapi_type_generic)
146 return ISC_R_INVALIDARG;
147 g = (omapi_generic_object_t *)h;
148
149 /* Look up the specified name in our list of objects. */
150 for (i = 0; i < g -> nvalues; i++) {
151 if (!omapi_data_string_cmp (name, g -> values [i] -> name)) {
152 /* If this is a name/null value pair, this is the
153 same as if there were no value that matched
154 the specified name, so return ISC_R_NOTFOUND. */
155 if (!g -> values [i] -> value)
156 return ISC_R_NOTFOUND;
157 /* Otherwise, return the name/value pair. */
158 return omapi_value_reference (value,
159 g -> values [i], MDL);
160 }
161 }
162
163 if (h -> inner && h -> inner -> type -> get_value)
164 return (*(h -> inner -> type -> get_value))
165 (h -> inner, id, name, value);
166 return ISC_R_NOTFOUND;
167 }
168
169 isc_result_t omapi_generic_destroy (omapi_object_t *h,
170 const char *file, int line)
171 {
172 omapi_generic_object_t *g;
173 int i;
174
175 if (h -> type != omapi_type_generic)
176 return ISC_R_UNEXPECTED;
177 g = (omapi_generic_object_t *)h;
178
179 if (g -> values) {
180 for (i = 0; i < g -> nvalues; i++) {
181 if (g -> values [i])
182 omapi_value_dereference (&g -> values [i],
183 file, line);
184 }
185 dfree (g -> values, file, line);
186 g -> values = (omapi_value_t **)0;
187 g -> va_max = 0;
188 }
189
190 return ISC_R_SUCCESS;
191 }
192
193 isc_result_t omapi_generic_signal_handler (omapi_object_t *h,
194 const char *name, va_list ap)
195 {
196 if (h -> type != omapi_type_generic)
197 return ISC_R_INVALIDARG;
198
199 if (h -> inner && h -> inner -> type -> signal_handler)
200 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
201 name, ap);
202 return ISC_R_NOTFOUND;
203 }
204
205 /* Write all the published values associated with the object through the
206 specified connection. */
207
208 isc_result_t omapi_generic_stuff_values (omapi_object_t *c,
209 omapi_object_t *id,
210 omapi_object_t *g)
211 {
212 omapi_generic_object_t *src;
213 int i;
214 isc_result_t status;
215
216 if (g -> type != omapi_type_generic)
217 return ISC_R_INVALIDARG;
218 src = (omapi_generic_object_t *)g;
219
220 for (i = 0; i < src -> nvalues; i++) {
221 if (src -> values [i] && src -> values [i] -> name -> len) {
222 status = (omapi_connection_put_uint16
223 (c, src -> values [i] -> name -> len));
224 if (status != ISC_R_SUCCESS)
225 return status;
226 status = (omapi_connection_copyin
227 (c, src -> values [i] -> name -> value,
228 src -> values [i] -> name -> len));
229 if (status != ISC_R_SUCCESS)
230 return status;
231
232 status = (omapi_connection_write_typed_data
233 (c, src -> values [i] -> value));
234 if (status != ISC_R_SUCCESS)
235 return status;
236 }
237 }
238
239 if (g -> inner && g -> inner -> type -> stuff_values)
240 return (*(g -> inner -> type -> stuff_values)) (c, id,
241 g -> inner);
242 return ISC_R_SUCCESS;
243 }
244