diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-03-02 19:04:49 +0000 |
---|---|---|
committer | <> | 2015-05-08 15:30:59 +0000 |
commit | f800382616186a5d30e28d8b2c51e97a9a8360f2 (patch) | |
tree | 0d5270190548a37223d14b54383ce8a3d3af5302 /omapip/generic.c | |
download | isc-dhcp-tarball-master.tar.gz |
Imported from /home/lorry/working-area/delta_isc-dhcp-tarball/dhcp-4.2.8.tar.gz.HEADdhcp-4.2.8master
Diffstat (limited to 'omapip/generic.c')
-rw-r--r-- | omapip/generic.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/omapip/generic.c b/omapip/generic.c new file mode 100644 index 0000000..6dee801 --- /dev/null +++ b/omapip/generic.c @@ -0,0 +1,299 @@ +/* generic.c + + Subroutines that support the generic object. */ + +/* + * Copyright (c) 2004-2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#include "dhcpd.h" + +#include <omapip/omapip_p.h> + +OMAPI_OBJECT_ALLOC (omapi_generic, + omapi_generic_object_t, omapi_type_generic) + +isc_result_t omapi_generic_new (omapi_object_t **gen, + const char *file, int line) +{ + /* Backwards compatibility. */ + return omapi_generic_allocate ((omapi_generic_object_t **)gen, + file, line); +} + +isc_result_t omapi_generic_set_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_typed_data_t *value) +{ + omapi_generic_object_t *g; + omapi_value_t *new; + omapi_value_t **va; + u_int8_t *ca; + int vm_new; + int i, vfree = -1; + isc_result_t status; + + if (h -> type != omapi_type_generic) + return DHCP_R_INVALIDARG; + g = (omapi_generic_object_t *)h; + + /* See if there's already a value with this name attached to + the generic object, and if so, replace the current value + with the new one. */ + for (i = 0; i < g -> nvalues; i++) { + if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { + /* There's an inconsistency here: the standard + behaviour of a set_values method when + passed a matching name and a null value is + to delete the value associated with that + name (where possible). In the generic + object, we remember the name/null pair, + because generic objects are generally used + to pass messages around, and this is the + way that remote entities delete values from + local objects. If the get_value method of + a generic object is called for a name that + maps to a name/null pair, ISC_R_NOTFOUND is + returned. */ + new = (omapi_value_t *)0; + status = (omapi_value_new (&new, MDL)); + if (status != ISC_R_SUCCESS) + return status; + omapi_data_string_reference (&new -> name, name, MDL); + if (value) + omapi_typed_data_reference (&new -> value, + value, MDL); + + omapi_value_dereference (&(g -> values [i]), MDL); + status = (omapi_value_reference + (&(g -> values [i]), new, MDL)); + omapi_value_dereference (&new, MDL); + g -> changed [i] = 1; + return status; + } + /* Notice a free slot if we pass one. */ + else if (vfree == -1 && !g -> values [i]) + vfree = i; + } + + /* If the name isn't already attached to this object, see if an + inner object has it. */ + if (h -> inner && h -> inner -> type -> set_value) { + status = ((*(h -> inner -> type -> set_value)) + (h -> inner, id, name, value)); + if (status != ISC_R_NOTFOUND) + return status; + } + + /* Okay, so it's a value that no inner object knows about, and + (implicitly, since the outer object set_value method would + have called this object's set_value method) it's an object that + no outer object knows about, it's this object's responsibility + to remember it - that's what generic objects do. */ + + /* Arrange for there to be space for the pointer to the new + name/value pair if necessary: */ + if (vfree == -1) { + vfree = g -> nvalues; + if (vfree == g -> va_max) { + if (g -> va_max) + vm_new = 2 * g -> va_max; + else + vm_new = 10; + va = dmalloc (vm_new * sizeof *va, MDL); + if (!va) + return ISC_R_NOMEMORY; + ca = dmalloc (vm_new * sizeof *ca, MDL); + if (!ca) { + dfree (va, MDL); + return ISC_R_NOMEMORY; + } + if (g -> va_max) { + memcpy (va, g -> values, + g -> va_max * sizeof *va); + memcpy (ca, g -> changed, + g -> va_max * sizeof *ca); + } + memset (va + g -> va_max, 0, + (vm_new - g -> va_max) * sizeof *va); + memset (ca + g -> va_max, 0, + (vm_new - g -> va_max) * sizeof *ca); + if (g -> values) + dfree (g -> values, MDL); + if (g -> changed) + dfree (g -> changed, MDL); + g -> values = va; + g -> changed = ca; + g -> va_max = vm_new; + } + } + status = omapi_value_new (&g -> values [vfree], MDL); + if (status != ISC_R_SUCCESS) + return status; + omapi_data_string_reference (&g -> values [vfree] -> name, + name, MDL); + if (value) + omapi_typed_data_reference + (&g -> values [vfree] -> value, value, MDL); + g -> changed [vfree] = 1; + if (vfree == g -> nvalues) + g -> nvalues++; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_generic_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + int i; + omapi_generic_object_t *g; + + if (h -> type != omapi_type_generic) + return DHCP_R_INVALIDARG; + g = (omapi_generic_object_t *)h; + + /* Look up the specified name in our list of objects. */ + for (i = 0; i < g -> nvalues; i++) { + if (!g -> values[i]) + continue; + if (!omapi_data_string_cmp (name, g -> values [i] -> name)) { + /* If this is a name/null value pair, this is the + same as if there were no value that matched + the specified name, so return ISC_R_NOTFOUND. */ + if (!g -> values [i] -> value) + return ISC_R_NOTFOUND; + /* Otherwise, return the name/value pair. */ + return omapi_value_reference (value, + g -> values [i], MDL); + } + } + + if (h -> inner && h -> inner -> type -> get_value) + return (*(h -> inner -> type -> get_value)) + (h -> inner, id, name, value); + return ISC_R_NOTFOUND; +} + +isc_result_t omapi_generic_destroy (omapi_object_t *h, + const char *file, int line) +{ + omapi_generic_object_t *g; + int i; + + if (h -> type != omapi_type_generic) + return ISC_R_UNEXPECTED; + g = (omapi_generic_object_t *)h; + + if (g -> values) { + for (i = 0; i < g -> nvalues; i++) { + if (g -> values [i]) + omapi_value_dereference (&g -> values [i], + file, line); + } + dfree (g -> values, file, line); + dfree (g -> changed, file, line); + g -> values = (omapi_value_t **)0; + g -> changed = (u_int8_t *)0; + g -> va_max = 0; + } + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_generic_signal_handler (omapi_object_t *h, + const char *name, va_list ap) +{ + if (h -> type != omapi_type_generic) + return DHCP_R_INVALIDARG; + + if (h -> inner && h -> inner -> type -> signal_handler) + return (*(h -> inner -> type -> signal_handler)) (h -> inner, + name, ap); + return ISC_R_NOTFOUND; +} + +/* Write all the published values associated with the object through the + specified connection. */ + +isc_result_t omapi_generic_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *g) +{ + omapi_generic_object_t *src; + int i; + isc_result_t status; + + if (g -> type != omapi_type_generic) + return DHCP_R_INVALIDARG; + src = (omapi_generic_object_t *)g; + + for (i = 0; i < src -> nvalues; i++) { + if (src -> values [i] && src -> values [i] -> name -> len && + src -> changed [i]) { + status = (omapi_connection_put_uint16 + (c, src -> values [i] -> name -> len)); + if (status != ISC_R_SUCCESS) + return status; + status = (omapi_connection_copyin + (c, src -> values [i] -> name -> value, + src -> values [i] -> name -> len)); + if (status != ISC_R_SUCCESS) + return status; + + status = (omapi_connection_write_typed_data + (c, src -> values [i] -> value)); + if (status != ISC_R_SUCCESS) + return status; + } + } + + if (g -> inner && g -> inner -> type -> stuff_values) + return (*(g -> inner -> type -> stuff_values)) (c, id, + g -> inner); + return ISC_R_SUCCESS; +} + +/* Clear the changed flags on the object. This has the effect that if + generic_stuff is called, any attributes that still have a cleared changed + flag aren't sent to the peer. This also deletes any values that are + null, presuming that these have now been properly handled. */ + +isc_result_t omapi_generic_clear_flags (omapi_object_t *o) +{ + int i; + omapi_generic_object_t *g; + + if (o -> type != omapi_type_generic) + return DHCP_R_INVALIDARG; + g = (omapi_generic_object_t *)o; + + for (i = 0; i < g -> nvalues; i++) { + g -> changed [i] = 0; + if (g -> values [i] && + !g -> values [i] -> value) + omapi_value_dereference (&g -> values [i], MDL); + } + return ISC_R_SUCCESS; +} |