1: /* generic.c
2:
3: Subroutines that support the generic object. */
4:
5: /*
6: * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
7: * Copyright (c) 1999-2003 by Internet Software Consortium
8: *
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.
12: *
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.
20: *
21: * Internet Systems Consortium, Inc.
22: * 950 Charter Street
23: * Redwood City, CA 94063
24: * <info@isc.org>
25: * https://www.isc.org/
26: *
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''.
33: */
34:
35: #include "dhcpd.h"
36:
37: #include <omapip/omapip_p.h>
38:
39: OMAPI_OBJECT_ALLOC (omapi_generic,
40: omapi_generic_object_t, omapi_type_generic)
41:
42: isc_result_t omapi_generic_new (omapi_object_t **gen,
43: const char *file, int line)
44: {
45: /* Backwards compatibility. */
46: return omapi_generic_allocate ((omapi_generic_object_t **)gen,
47: file, line);
48: }
49:
50: isc_result_t omapi_generic_set_value (omapi_object_t *h,
51: omapi_object_t *id,
52: omapi_data_string_t *name,
53: omapi_typed_data_t *value)
54: {
55: omapi_generic_object_t *g;
56: omapi_value_t *new;
57: omapi_value_t **va;
58: u_int8_t *ca;
59: int vm_new;
60: int i, vfree = -1;
61: isc_result_t status;
62:
63: if (h -> type != omapi_type_generic)
64: return ISC_R_INVALIDARG;
65: g = (omapi_generic_object_t *)h;
66:
67: /* See if there's already a value with this name attached to
68: the generic object, and if so, replace the current value
69: with the new one. */
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
84: returned. */
85: new = (omapi_value_t *)0;
86: status = (omapi_value_new (&new, MDL));
87: if (status != ISC_R_SUCCESS)
88: return status;
89: omapi_data_string_reference (&new -> name, name, MDL);
90: if (value)
91: omapi_typed_data_reference (&new -> value,
92: value, MDL);
93:
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);
98: g -> changed [i] = 1;
99: return status;
100: }
101: /* Notice a free slot if we pass one. */
102: else if (vfree == -1 && !g -> values [i])
103: vfree = i;
104: }
105:
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)
112: return status;
113: }
114:
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. */
120:
121: /* Arrange for there to be space for the pointer to the new
122: name/value pair if necessary: */
123: if (vfree == -1) {
124: vfree = g -> nvalues;
125: if (vfree == g -> va_max) {
126: if (g -> va_max)
127: vm_new = 2 * g -> va_max;
128: else
129: vm_new = 10;
130: va = dmalloc (vm_new * sizeof *va, MDL);
131: if (!va)
132: return ISC_R_NOMEMORY;
133: ca = dmalloc (vm_new * sizeof *ca, MDL);
134: if (!ca) {
135: dfree (va, MDL);
136: return ISC_R_NOMEMORY;
137: }
138: if (g -> va_max) {
139: memcpy (va, g -> values,
140: g -> va_max * sizeof *va);
141: memcpy (ca, g -> changed,
142: g -> va_max * sizeof *ca);
143: }
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);
148: if (g -> values)
149: dfree (g -> values, MDL);
150: if (g -> changed)
151: dfree (g -> changed, MDL);
152: g -> values = va;
153: g -> changed = ca;
154: g -> va_max = vm_new;
155: }
156: }
157: status = omapi_value_new (&g -> values [vfree], MDL);
158: if (status != ISC_R_SUCCESS)
159: return status;
160: omapi_data_string_reference (&g -> values [vfree] -> name,
161: name, MDL);
162: if (value)
163: omapi_typed_data_reference
164: (&g -> values [vfree] -> value, value, MDL);
165: g -> changed [vfree] = 1;
166: if (vfree == g -> nvalues)
167: g -> nvalues++;
168: return ISC_R_SUCCESS;
169: }
170:
171: isc_result_t omapi_generic_get_value (omapi_object_t *h,
172: omapi_object_t *id,
173: omapi_data_string_t *name,
174: omapi_value_t **value)
175: {
176: int i;
177: omapi_generic_object_t *g;
178:
179: if (h -> type != omapi_type_generic)
180: return ISC_R_INVALIDARG;
181: g = (omapi_generic_object_t *)h;
182:
183: /* Look up the specified name in our list of objects. */
184: for (i = 0; i < g -> nvalues; i++) {
185: if (!g -> values[i])
186: continue;
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);
196: }
197: }
198:
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;
203: }
204:
205: isc_result_t omapi_generic_destroy (omapi_object_t *h,
206: const char *file, int line)
207: {
208: omapi_generic_object_t *g;
209: int i;
210:
211: if (h -> type != omapi_type_generic)
212: return ISC_R_UNEXPECTED;
213: g = (omapi_generic_object_t *)h;
214:
215: if (g -> values) {
216: for (i = 0; i < g -> nvalues; i++) {
217: if (g -> values [i])
218: omapi_value_dereference (&g -> values [i],
219: file, line);
220: }
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;
225: g -> va_max = 0;
226: }
227:
228: return ISC_R_SUCCESS;
229: }
230:
231: isc_result_t omapi_generic_signal_handler (omapi_object_t *h,
232: const char *name, va_list ap)
233: {
234: if (h -> type != omapi_type_generic)
235: return ISC_R_INVALIDARG;
236:
237: if (h -> inner && h -> inner -> type -> signal_handler)
238: return (*(h -> inner -> type -> signal_handler)) (h -> inner,
239: name, ap);
240: return ISC_R_NOTFOUND;
241: }
242:
243: /* Write all the published values associated with the object through the
244: specified connection. */
245:
246: isc_result_t omapi_generic_stuff_values (omapi_object_t *c,
247: omapi_object_t *id,
248: omapi_object_t *g)
249: {
250: omapi_generic_object_t *src;
251: int i;
252: isc_result_t status;
253:
254: if (g -> type != omapi_type_generic)
255: return ISC_R_INVALIDARG;
256: src = (omapi_generic_object_t *)g;
257:
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)
264: return status;
265: status = (omapi_connection_copyin
266: (c, src -> values [i] -> name -> value,
267: src -> values [i] -> name -> len));
268: if (status != ISC_R_SUCCESS)
269: return status;
270:
271: status = (omapi_connection_write_typed_data
272: (c, src -> values [i] -> value));
273: if (status != ISC_R_SUCCESS)
274: return status;
275: }
276: }
277:
278: if (g -> inner && g -> inner -> type -> stuff_values)
279: return (*(g -> inner -> type -> stuff_values)) (c, id,
280: g -> inner);
281: return ISC_R_SUCCESS;
282: }
283:
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. */
288:
289: isc_result_t omapi_generic_clear_flags (omapi_object_t *o)
290: {
291: int i;
292: omapi_generic_object_t *g;
293:
294: if (o -> type != omapi_type_generic)
295: return ISC_R_INVALIDARG;
296: g = (omapi_generic_object_t *)o;
297:
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);
303: }
304: return ISC_R_SUCCESS;
305: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>