mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-24 02:58:38 +00:00
253 lines
6.9 KiB
C
253 lines
6.9 KiB
C
/*
|
|
* Copyright (C) 1996, 1997, 1998, 1999, 2000 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
|
* CONSORTIUM 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.
|
|
*/
|
|
|
|
/* $Id: generic.c,v 1.11 2000/03/14 03:38:54 tale Exp $ */
|
|
|
|
/* Principal Author: Ted Lemon */
|
|
|
|
/*
|
|
* Subroutines that support the generic object.
|
|
*/
|
|
#include <stddef.h> /* NULL */
|
|
#include <string.h> /* memset */
|
|
|
|
#include <isc/assertions.h>
|
|
|
|
#include <omapi/private.h>
|
|
|
|
static isc_result_t
|
|
generic_setvalue(omapi_object_t *h, omapi_string_t *name, omapi_data_t *value)
|
|
{
|
|
omapi_generic_t *g;
|
|
omapi_value_t *new;
|
|
omapi_value_t **va;
|
|
int vm_new;
|
|
unsigned int i;
|
|
isc_result_t result;
|
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_generic);
|
|
|
|
g = (omapi_generic_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_string_stringcmp(name, g->values[i]->name) == 0) {
|
|
/*
|
|
* 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 = NULL;
|
|
result = omapi_value_create(&new);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
|
|
omapi_string_reference(&new->name, name);
|
|
if (value != NULL)
|
|
omapi_data_reference(&new->value, value);
|
|
|
|
omapi_value_dereference(&(g->values[i]));
|
|
omapi_value_reference(&(g->values[i]), new);
|
|
omapi_value_dereference(&new);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the name isn't already attached to this object, see if an
|
|
* inner object has it.
|
|
*/
|
|
result = omapi_object_passsetvalue(h, name, value);
|
|
if (result != ISC_R_NOTFOUND)
|
|
return (result);
|
|
|
|
/*
|
|
* 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 (g->nvalues == g->va_max) {
|
|
/*
|
|
* Increase the maximum number of values by 10.
|
|
* 10 is an arbitrary constant.
|
|
*/
|
|
vm_new = g->va_max + 10;
|
|
va = isc_mem_get(omapi_mctx, vm_new * sizeof(*va));
|
|
if (va == NULL)
|
|
return (ISC_R_NOMEMORY);
|
|
if (g->va_max != 0) {
|
|
memcpy(va, g->values, g->va_max * sizeof(*va));
|
|
isc_mem_put(omapi_mctx, g->values,
|
|
g->va_max * sizeof(*va));
|
|
}
|
|
|
|
memset(va + g->va_max, 0, (vm_new - g->va_max) * sizeof(*va));
|
|
g->values = va;
|
|
g->va_max = vm_new;
|
|
}
|
|
result = omapi_value_create(&g->values[g->nvalues]);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
|
|
omapi_string_reference(&g->values[g->nvalues]->name, name);
|
|
if (value != NULL)
|
|
omapi_data_reference(&g->values[g->nvalues]->value, value);
|
|
g->nvalues++;
|
|
return (ISC_R_SUCCESS);
|
|
}
|
|
|
|
static isc_result_t
|
|
generic_getvalue(omapi_object_t *h, omapi_string_t *name,
|
|
omapi_value_t **value)
|
|
{
|
|
unsigned int i;
|
|
omapi_generic_t *g;
|
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_generic);
|
|
|
|
g = (omapi_generic_t *)h;
|
|
|
|
/*
|
|
* Look up the specified name in our list of objects.
|
|
*/
|
|
for (i = 0; i < g->nvalues; i++) {
|
|
if (omapi_string_stringcmp(name, g->values[i]->name) == 0) {
|
|
/*
|
|
* 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 == NULL)
|
|
return (ISC_R_NOTFOUND);
|
|
/*
|
|
* Otherwise, return the name/value pair.
|
|
*/
|
|
omapi_value_reference(value, g->values[i]);
|
|
return (ISC_R_SUCCESS);
|
|
}
|
|
}
|
|
|
|
return (omapi_object_passgetvalue(h, name, value));
|
|
}
|
|
|
|
static void
|
|
generic_destroy(omapi_object_t *h) {
|
|
omapi_generic_t *g;
|
|
unsigned int i;
|
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_generic);
|
|
|
|
g = (omapi_generic_t *)h;
|
|
|
|
if (g->values != NULL) {
|
|
for (i = 0; i < g->nvalues; i++)
|
|
if (g->values[i] != NULL)
|
|
omapi_value_dereference(&g->values[i]);
|
|
|
|
isc_mem_put(omapi_mctx, g->values,
|
|
g->va_max * sizeof(*g->values));
|
|
g->values = NULL;
|
|
g->va_max = 0;
|
|
}
|
|
}
|
|
|
|
static isc_result_t
|
|
generic_signalhandler(omapi_object_t *h, const char *name, va_list ap) {
|
|
REQUIRE(h != NULL && h->type == omapi_type_generic);
|
|
|
|
/*
|
|
* XXXDCL I suppose that ideally the status would be set in all
|
|
* objects in the chain.
|
|
*/
|
|
if (strcmp(name, "status") == 0) {
|
|
h->waitresult = va_arg(ap, isc_result_t);
|
|
return (ISC_R_SUCCESS);
|
|
}
|
|
|
|
return (omapi_object_passsignal(h, name, ap));
|
|
}
|
|
|
|
/*
|
|
* Write all the published values associated with the object through the
|
|
* specified connection.
|
|
*/
|
|
static isc_result_t
|
|
generic_stuffvalues(omapi_object_t *connection, omapi_object_t *h) {
|
|
omapi_generic_t *src;
|
|
unsigned int i;
|
|
isc_result_t result;
|
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_generic);
|
|
|
|
src = (omapi_generic_t *)h;
|
|
|
|
for (i = 0; i < src->nvalues; i++) {
|
|
if (src->values[i] != NULL &&
|
|
src->values[i]->name->len != 0) {
|
|
result = omapi_connection_putuint16(connection,
|
|
src->values[i]->name->len);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
result = omapi_connection_putmem(connection,
|
|
src->values[i]->name->value,
|
|
src->values[i]->name->len);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
|
|
result = omapi_connection_putdata(connection,
|
|
src->values[i]->value);
|
|
if (result != ISC_R_SUCCESS)
|
|
return (result);
|
|
}
|
|
}
|
|
|
|
return (omapi_object_passstuffvalues(connection, h));
|
|
}
|
|
|
|
isc_result_t
|
|
generic_init(void) {
|
|
return (omapi_object_register(&omapi_type_generic, "generic",
|
|
generic_setvalue,
|
|
generic_getvalue,
|
|
generic_destroy,
|
|
generic_signalhandler,
|
|
generic_stuffvalues,
|
|
NULL, NULL, NULL));
|
|
}
|