mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-30 13:57:50 +00:00
Omapi library, initial checkin
This commit is contained in:
79
omapip/Makefile.dist
Normal file
79
omapip/Makefile.dist
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Makefile.dist
|
||||||
|
#
|
||||||
|
# Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
# Use is subject to license terms which appear in the file named
|
||||||
|
# ISC-LICENSE that should have accompanied this file when you
|
||||||
|
# received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
# file, or you are not sure the one you have is correct, you may
|
||||||
|
# obtain an applicable copy of the license at:
|
||||||
|
#
|
||||||
|
# http://www.isc.org/isc-license-1.0.html.
|
||||||
|
#
|
||||||
|
# This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
# associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
# included in the top-level directory of this release.
|
||||||
|
#
|
||||||
|
# Support and other services are available for ISC products - see
|
||||||
|
# http://www.isc.org for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
CATMANPAGES = omapi.cat3
|
||||||
|
SEDMANPAGES = omapi.man3
|
||||||
|
SRC = protocol.c buffer.c alloc.c result.c connection.c \
|
||||||
|
listener.c dispatch.c generic.c support.c handle.c message.c
|
||||||
|
OBJ = protocol.o buffer.o alloc.o result.o connection.o \
|
||||||
|
listener.o dispatch.o generic.o support.o handle.o message.o
|
||||||
|
MAN = omapi.3
|
||||||
|
|
||||||
|
DEBUG = -g
|
||||||
|
INCLUDES = $(BINDINC) -I../includes
|
||||||
|
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
|
||||||
|
|
||||||
|
all: libomapi.a test $(CATMANPAGES)
|
||||||
|
|
||||||
|
test: test.o libomapi.a
|
||||||
|
$(CC) $(DEBUG) -o test test.o libomapi.a
|
||||||
|
|
||||||
|
libomapi.a: $(OBJ)
|
||||||
|
rm -f libomapi.a
|
||||||
|
ar cruv libomapi.a $(OBJ)
|
||||||
|
$(RANLIB) libomapi.a
|
||||||
|
|
||||||
|
install: all
|
||||||
|
for dir in $(LIBMANDIR); do \
|
||||||
|
foo=""; \
|
||||||
|
for bar in `echo $(DESTDIR)$${dir} |tr / ' '`; do \
|
||||||
|
foo=$${foo}/$$bar; \
|
||||||
|
if [ ! -d $$foo ]; then \
|
||||||
|
mkdir $$foo; \
|
||||||
|
chmod 755 $$foo; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
for man in $(MAN); do \
|
||||||
|
prefix=`echo $$man |sed -e 's/\.[0-9]$$//'`; \
|
||||||
|
suffix=`echo $$man |sed -e 's/.*\.\([0-9]\)$$/\1/'`; \
|
||||||
|
$(MANINSTALL) $(MANFROM) $${prefix}.$(MANCAT)$${suffix} $(MANTO) \
|
||||||
|
$(DESTDIR)$(LIBMANDIR)/$(prefix)$(LIBMANEXT); \
|
||||||
|
done
|
||||||
|
|
||||||
|
depend:
|
||||||
|
makedepend $(INCLUDES) $(PREDEFINES) $(SRCS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f $(OBJ)
|
||||||
|
|
||||||
|
realclean: clean
|
||||||
|
-rm -f libdhcp.a *~ $(CATMANPAGES) $(SEDMANPAGES)
|
||||||
|
|
||||||
|
distclean: realclean
|
||||||
|
-rm -f Makefile
|
||||||
|
|
||||||
|
omapi.cat3: omapi.man3
|
||||||
|
nroff -man omapi.man3 >omapi.cat3
|
||||||
|
|
||||||
|
omapi.man3: omapi.3
|
||||||
|
sed -e "s#ETCDIR#$(ETC)#g" -e "s#DBDIR#$(VARDB)#g" \
|
||||||
|
-e "s#RUNDIR#$(VARRUN)#g" < omapi.3 >omapi.man3
|
||||||
|
|
||||||
|
# Dependencies (semi-automatically-generated)
|
443
omapip/alloc.c
Normal file
443
omapip/alloc.c
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
/* alloc.c
|
||||||
|
|
||||||
|
Functions supporting memory allocation for the object management
|
||||||
|
protocol... */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
isc_result_t omapi_object_reference (omapi_object_t **r,
|
||||||
|
omapi_object_t *h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h || !r)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (*r) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: reference store into non-null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*r = h;
|
||||||
|
h -> refcnt++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_object_dereference (omapi_object_t **h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
int outer_reference = 0;
|
||||||
|
int inner_reference = 0;
|
||||||
|
int handle_reference = 0;
|
||||||
|
int extra_references;
|
||||||
|
omapi_object_t *p;
|
||||||
|
|
||||||
|
if (!h)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!*h) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: dereference of null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*h) -> refcnt <= 0) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("dereference of pointer with refcnt of zero!");
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if this object's inner object refers to it, but don't
|
||||||
|
count this as a reference if we're being asked to free the
|
||||||
|
reference from the inner object. */
|
||||||
|
if ((*h) -> inner && (*h) -> inner -> outer &&
|
||||||
|
h != &((*h) -> inner -> outer))
|
||||||
|
inner_reference = 1;
|
||||||
|
|
||||||
|
/* Ditto for the outer object. */
|
||||||
|
if ((*h) -> outer && (*h) -> outer -> inner &&
|
||||||
|
h != &((*h) -> outer -> inner))
|
||||||
|
outer_reference = 1;
|
||||||
|
|
||||||
|
/* Ditto for the outer object. The code below assumes that
|
||||||
|
the only reason we'd get a dereference from the handle
|
||||||
|
table is if this function does it - otherwise we'd have to
|
||||||
|
traverse the handle table to find the address where the
|
||||||
|
reference is stored and compare against that, and we don't
|
||||||
|
want to do that if we can avoid it. */
|
||||||
|
if ((*h) -> handle)
|
||||||
|
handle_reference = 1;
|
||||||
|
|
||||||
|
/* If we are getting rid of the last reference other than
|
||||||
|
references to inner and outer objects, or from the handle
|
||||||
|
table, then we must examine all the objects in either
|
||||||
|
direction to see if they hold any non-inner, non-outer,
|
||||||
|
non-handle-table references. If not, we need to free the
|
||||||
|
entire chain of objects. */
|
||||||
|
if ((*h) -> refcnt ==
|
||||||
|
inner_reference + outer_reference + handle_reference + 1) {
|
||||||
|
if (inner_reference || outer_reference || handle_reference) {
|
||||||
|
/* XXX we could check for a reference from the
|
||||||
|
handle table here. */
|
||||||
|
extra_references = 0;
|
||||||
|
for (p = (*h) -> inner;
|
||||||
|
p && !extra_references; p = p -> inner) {
|
||||||
|
extra_references += p -> refcnt - 1;
|
||||||
|
if (p -> inner)
|
||||||
|
--extra_references;
|
||||||
|
if (p -> handle)
|
||||||
|
--extra_references;
|
||||||
|
}
|
||||||
|
for (p = (*h) -> outer;
|
||||||
|
p && !extra_references; p = p -> outer) {
|
||||||
|
extra_references += p -> refcnt - 1;
|
||||||
|
if (p -> outer)
|
||||||
|
--extra_references;
|
||||||
|
if (p -> handle)
|
||||||
|
--extra_references;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
extra_references = 0;
|
||||||
|
|
||||||
|
if (!extra_references) {
|
||||||
|
if (inner_reference)
|
||||||
|
omapi_object_dereference
|
||||||
|
(&(*h) -> inner -> outer, name);
|
||||||
|
if (outer_reference)
|
||||||
|
omapi_object_dereference
|
||||||
|
(&(*h) -> outer -> inner, name);
|
||||||
|
if ((*h) -> type -> destroy)
|
||||||
|
(*((*h) -> type -> destroy)) (*h, name);
|
||||||
|
free (*h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*h = 0;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_buffer_new (omapi_buffer_t **h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
omapi_buffer_t *t;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
t = (omapi_buffer_t *)malloc (sizeof *t);
|
||||||
|
if (!t)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (t, 0, sizeof *t);
|
||||||
|
status = omapi_buffer_reference (h, t, name);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
free (t);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_buffer_reference (omapi_buffer_t **r,
|
||||||
|
omapi_buffer_t *h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h || !r)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (*r) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: reference store into non-null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*r = h;
|
||||||
|
h -> refcnt++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_buffer_dereference (omapi_buffer_t **h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!*h) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: dereference of null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*h) -> refcnt <= 0) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("dereference of pointer with refcnt of zero!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (--(*h) -> refcnt == 0)
|
||||||
|
free (*h);
|
||||||
|
*h = 0;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_typed_data_new (omapi_typed_data_t **t,
|
||||||
|
omapi_datatype_t type, ...)
|
||||||
|
{
|
||||||
|
va_list l;
|
||||||
|
omapi_typed_data_t *new;
|
||||||
|
int len;
|
||||||
|
int val;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
va_start (l, type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case omapi_datatype_int:
|
||||||
|
len = OMAPI_TYPED_DATA_INT_LEN;
|
||||||
|
val = va_arg (l, int);
|
||||||
|
break;
|
||||||
|
case omapi_datatype_string:
|
||||||
|
s = va_arg (l, char *);
|
||||||
|
val = strlen (s);
|
||||||
|
len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val + 1;
|
||||||
|
break;
|
||||||
|
case omapi_datatype_data:
|
||||||
|
val = va_arg (l, int);
|
||||||
|
len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
|
||||||
|
break;
|
||||||
|
case omapi_datatype_object:
|
||||||
|
len = OMAPI_TYPED_DATA_OBJECT_LEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
new = malloc (len);
|
||||||
|
if (!new)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (new, 0, len);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case omapi_datatype_int:
|
||||||
|
new -> u.integer = val;
|
||||||
|
break;
|
||||||
|
case omapi_datatype_string:
|
||||||
|
strcpy (new -> u.buffer.value, s);
|
||||||
|
new -> u.buffer.len = val;
|
||||||
|
break;
|
||||||
|
case omapi_datatype_data:
|
||||||
|
new -> u.buffer.len = val;
|
||||||
|
break;
|
||||||
|
case omapi_datatype_object:
|
||||||
|
return omapi_object_reference (&new -> u.object,
|
||||||
|
va_arg (l, omapi_object_t *),
|
||||||
|
"omapi_datatype_new");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return omapi_typed_data_reference (t, new, "omapi_typed_data_new");
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r,
|
||||||
|
omapi_typed_data_t *h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h || !r)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (*r) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: reference store into non-null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*r = h;
|
||||||
|
h -> refcnt++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!*h) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: dereference of null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*h) -> refcnt <= 0) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("dereference of pointer with refcnt of zero!");
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--((*h) -> refcnt) <= 0 ) {
|
||||||
|
switch ((*h) -> type) {
|
||||||
|
case omapi_datatype_int:
|
||||||
|
case omapi_datatype_string:
|
||||||
|
case omapi_datatype_data:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case omapi_datatype_object:
|
||||||
|
omapi_object_dereference (&(*h) -> u.object,
|
||||||
|
name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free (*h);
|
||||||
|
}
|
||||||
|
*h = 0;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_data_string_new (omapi_data_string_t **d,
|
||||||
|
int len, char *name)
|
||||||
|
{
|
||||||
|
omapi_data_string_t *new;
|
||||||
|
|
||||||
|
new = malloc (OMAPI_DATA_STRING_EMPTY_SIZE + len);
|
||||||
|
if (!new)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE);
|
||||||
|
new -> len = len;
|
||||||
|
return omapi_data_string_reference (d, new, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_data_string_reference (omapi_data_string_t **r,
|
||||||
|
omapi_data_string_t *h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h || !r)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (*r) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: reference store into non-null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*r = h;
|
||||||
|
h -> refcnt++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_data_string_dereference (omapi_data_string_t **h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!*h) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: dereference of null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*h) -> refcnt <= 0) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("dereference of pointer with refcnt of zero!");
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--((*h) -> refcnt) <= 0 ) {
|
||||||
|
free (*h);
|
||||||
|
}
|
||||||
|
*h = 0;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_value_new (omapi_value_t **d,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
omapi_value_t *new;
|
||||||
|
|
||||||
|
new = malloc (sizeof *new);
|
||||||
|
if (!new)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (new, 0, sizeof *new);
|
||||||
|
return omapi_value_reference (d, new, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_value_reference (omapi_value_t **r,
|
||||||
|
omapi_value_t *h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h || !r)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (*r) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: reference store into non-null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*r = h;
|
||||||
|
h -> refcnt++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_value_dereference (omapi_value_t **h,
|
||||||
|
char *name)
|
||||||
|
{
|
||||||
|
if (!h)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!*h) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("%s: dereference of null pointer!", name);
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*h) -> refcnt <= 0) {
|
||||||
|
#if defined (ALLOCATION_DEBUGGING)
|
||||||
|
abort ("dereference of pointer with refcnt of zero!");
|
||||||
|
#else
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--((*h) -> refcnt) <= 0 ) {
|
||||||
|
if ((*h) -> name)
|
||||||
|
omapi_data_string_dereference (&(*h) -> name, name);
|
||||||
|
if ((*h) -> value)
|
||||||
|
omapi_typed_data_dereference (&(*h) -> value, name);
|
||||||
|
free (*h);
|
||||||
|
}
|
||||||
|
*h = 0;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
396
omapip/buffer.c
Normal file
396
omapip/buffer.c
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
/* buffer.c
|
||||||
|
|
||||||
|
Buffer access functions for the object management protocol... */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
/* Make sure that at least len bytes are in the input buffer, and if not,
|
||||||
|
read enough bytes to make up the difference. */
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_reader (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
omapi_buffer_t *buffer;
|
||||||
|
isc_result_t status;
|
||||||
|
int read_len, read_status;
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
int bytes_to_read;
|
||||||
|
|
||||||
|
if (!h || h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
|
||||||
|
/* Make sure c -> bytes_needed is valid. */
|
||||||
|
if (c -> bytes_needed < 0)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
/* See if there are enough bytes. */
|
||||||
|
if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
|
||||||
|
c -> in_bytes > c -> bytes_needed)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
if (c -> inbufs) {
|
||||||
|
for (buffer = c -> inbufs; buffer -> next;
|
||||||
|
buffer = buffer -> next)
|
||||||
|
;
|
||||||
|
if (!BUFFER_BYTES_AVAIL (buffer)) {
|
||||||
|
status = omapi_buffer_new (&buffer -> next,
|
||||||
|
"omapi_private_read");
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
buffer = buffer -> next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = omapi_buffer_new (&c -> inbufs,
|
||||||
|
"omapi_private_read");
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
buffer = c -> inbufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes_to_read = BUFFER_BYTES_AVAIL (buffer);
|
||||||
|
|
||||||
|
while (bytes_to_read) {
|
||||||
|
if (buffer -> tail >= buffer -> head)
|
||||||
|
read_len = sizeof (buffer -> buf) - buffer -> tail - 1;
|
||||||
|
else
|
||||||
|
read_len = buffer -> tail - buffer -> head - 1;
|
||||||
|
|
||||||
|
read_status = read (c -> socket,
|
||||||
|
&buffer -> buf [buffer -> tail], read_len);
|
||||||
|
if (read_status < 0) {
|
||||||
|
if (errno == EWOULDBLOCK)
|
||||||
|
return ISC_R_NOMORE;
|
||||||
|
else if (errno == EIO)
|
||||||
|
return ISC_R_IOERROR;
|
||||||
|
else if (errno == EINVAL)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
else if (errno == ECONNRESET) {
|
||||||
|
omapi_disconnect (h, 0);
|
||||||
|
return ISC_R_SHUTTINGDOWN;
|
||||||
|
} else
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
if (read_status == 0) {
|
||||||
|
omapi_disconnect (h, 0);
|
||||||
|
return ISC_R_SHUTTINGDOWN;
|
||||||
|
}
|
||||||
|
buffer -> tail += read_status;
|
||||||
|
c -> in_bytes += read_status;
|
||||||
|
if (buffer -> tail == sizeof buffer -> buf)
|
||||||
|
buffer -> tail = 0;
|
||||||
|
if (read_status < read_len)
|
||||||
|
break;
|
||||||
|
bytes_to_read -= read_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c -> bytes_needed >= c -> in_bytes) {
|
||||||
|
omapi_signal (h, "ready", c);
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put some bytes into the output buffer for a connection. */
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_copyin (omapi_object_t *h,
|
||||||
|
unsigned char *bufp,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
omapi_buffer_t *buffer;
|
||||||
|
isc_result_t status;
|
||||||
|
int bytes_copied = 0;
|
||||||
|
int copy_len;
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
/* Make sure len is valid. */
|
||||||
|
if (len < 0)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
if (!h || h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
|
||||||
|
if (c -> outbufs) {
|
||||||
|
for (buffer = c -> outbufs;
|
||||||
|
buffer -> next; buffer = buffer -> next)
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
status = omapi_buffer_new (&c -> outbufs,
|
||||||
|
"omapi_private_buffer_copyin");
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
buffer = c -> outbufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bytes_copied < len) {
|
||||||
|
/* If there is no space available in this buffer,
|
||||||
|
allocate a new one. */
|
||||||
|
if (!BUFFER_BYTES_AVAIL (buffer)) {
|
||||||
|
status = (omapi_buffer_new
|
||||||
|
(&buffer -> next,
|
||||||
|
"omapi_private_buffer_copyin"));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
buffer = buffer -> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer -> tail < buffer -> head)
|
||||||
|
copy_len = buffer -> tail - buffer -> head - 1;
|
||||||
|
else
|
||||||
|
copy_len = sizeof (buffer -> buf) - buffer -> tail - 1;
|
||||||
|
if (copy_len > (len - bytes_copied))
|
||||||
|
copy_len = len - bytes_copied;
|
||||||
|
|
||||||
|
memcpy (&buffer -> buf [buffer -> tail],
|
||||||
|
&bufp [bytes_copied], copy_len);
|
||||||
|
buffer -> tail += copy_len;
|
||||||
|
c -> out_bytes += copy_len;
|
||||||
|
bytes_copied += copy_len;
|
||||||
|
if (buffer -> tail == sizeof buffer -> buf)
|
||||||
|
buffer -> tail = 0;
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy some bytes from the input buffer, and advance the input buffer
|
||||||
|
pointer beyond the bytes copied out. */
|
||||||
|
|
||||||
|
u_int32_t omapi_connection_copyout (unsigned char *buf,
|
||||||
|
omapi_object_t *h,
|
||||||
|
int size)
|
||||||
|
{
|
||||||
|
int bytes_remaining;
|
||||||
|
int bytes_this_copy;
|
||||||
|
omapi_buffer_t *buffer;
|
||||||
|
unsigned char *bufp;
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
if (!h || h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
|
||||||
|
if (size > c -> in_bytes)
|
||||||
|
return ISC_R_NOMORE;
|
||||||
|
bufp = buf;
|
||||||
|
bytes_remaining = size;
|
||||||
|
buffer = c -> inbufs;
|
||||||
|
|
||||||
|
while (bytes_remaining) {
|
||||||
|
if (!buffer)
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
if (buffer -> head != buffer -> tail) {
|
||||||
|
if (buffer -> head > buffer -> tail) {
|
||||||
|
bytes_this_copy = (sizeof buffer -> buf -
|
||||||
|
buffer -> head);
|
||||||
|
} else {
|
||||||
|
bytes_this_copy =
|
||||||
|
buffer -> tail - buffer -> head;
|
||||||
|
}
|
||||||
|
if (bytes_this_copy > bytes_remaining)
|
||||||
|
bytes_this_copy = bytes_remaining;
|
||||||
|
if (bufp) {
|
||||||
|
memcpy (bufp, &buffer -> buf [buffer -> head],
|
||||||
|
bytes_this_copy);
|
||||||
|
bufp += bytes_this_copy;
|
||||||
|
}
|
||||||
|
bytes_remaining -= bytes_this_copy;
|
||||||
|
buffer -> head += bytes_this_copy;
|
||||||
|
if (buffer -> head == sizeof buffer -> buf)
|
||||||
|
buffer -> head = 0;
|
||||||
|
c -> in_bytes -= bytes_this_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer -> head == buffer -> tail)
|
||||||
|
buffer = buffer -> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get rid of any input buffers that we emptied. */
|
||||||
|
buffer = (omapi_buffer_t *)0;
|
||||||
|
while (c -> inbufs &&
|
||||||
|
c -> inbufs -> head == c -> inbufs -> tail) {
|
||||||
|
if (c -> inbufs -> next) {
|
||||||
|
omapi_buffer_reference
|
||||||
|
(&buffer,
|
||||||
|
c -> inbufs -> next,
|
||||||
|
"omapi_private_buffer_copyout");
|
||||||
|
omapi_buffer_dereference
|
||||||
|
(&c -> inbufs -> next,
|
||||||
|
"omapi_private_buffer_copyout");
|
||||||
|
}
|
||||||
|
omapi_buffer_dereference (&c -> inbufs,
|
||||||
|
"omapi_private_buffer_copyout");
|
||||||
|
omapi_buffer_reference (&c -> inbufs,
|
||||||
|
buffer,
|
||||||
|
"omapi_private_buffer_copyout");
|
||||||
|
omapi_buffer_dereference (&buffer,
|
||||||
|
"omapi_private_buffer_copyout");
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_int32_t omapi_connection_writer (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
int bytes_this_write;
|
||||||
|
int bytes_written;
|
||||||
|
omapi_buffer_t *buffer;
|
||||||
|
unsigned char *bufp;
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
if (!h || h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
|
||||||
|
/* Already flushed... */
|
||||||
|
if (!c -> out_bytes)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
buffer = c -> outbufs;
|
||||||
|
|
||||||
|
while (c -> out_bytes) {
|
||||||
|
if (!buffer)
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
if (buffer -> head != buffer -> tail) {
|
||||||
|
if (buffer -> head > buffer -> tail) {
|
||||||
|
bytes_this_write = (sizeof buffer -> buf -
|
||||||
|
buffer -> head);
|
||||||
|
} else {
|
||||||
|
bytes_this_write =
|
||||||
|
(buffer -> tail - buffer -> head);
|
||||||
|
}
|
||||||
|
bytes_written = write (c -> socket,
|
||||||
|
&buffer -> buf [buffer -> head],
|
||||||
|
bytes_this_write);
|
||||||
|
/* If the write failed with EWOULDBLOCK or we wrote
|
||||||
|
zero bytes, a further write would block, so we have
|
||||||
|
flushed as much as we can for now. Other errors
|
||||||
|
are really errors. */
|
||||||
|
if (bytes_written < 0) {
|
||||||
|
if (errno == EWOULDBLOCK || errno == EAGAIN)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
else if (errno == EPIPE)
|
||||||
|
return ISC_R_NOCONN;
|
||||||
|
else if (errno == EFBIG || errno == EDQUOT)
|
||||||
|
return ISC_R_NORESOURCES;
|
||||||
|
else if (errno == ENOSPC)
|
||||||
|
return ISC_R_NOSPACE;
|
||||||
|
else if (errno == EIO)
|
||||||
|
return ISC_R_IOERROR;
|
||||||
|
else if (errno == EINVAL)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
else if (errno == ECONNRESET)
|
||||||
|
return ISC_R_SHUTTINGDOWN;
|
||||||
|
else
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
if (bytes_written == 0)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
buffer -> head += bytes_written;
|
||||||
|
if (buffer -> head == sizeof buffer -> buf)
|
||||||
|
buffer -> head = 0;
|
||||||
|
c -> out_bytes -= bytes_written;
|
||||||
|
|
||||||
|
/* If we didn't finish out the write, we filled the
|
||||||
|
O.S. output buffer and a further write would block,
|
||||||
|
so stop trying to flush now. */
|
||||||
|
if (bytes_written != bytes_this_write)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer -> head == buffer -> tail)
|
||||||
|
buffer = buffer -> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get rid of any output buffers we emptied. */
|
||||||
|
buffer = (omapi_buffer_t *)0;
|
||||||
|
while (c -> outbufs &&
|
||||||
|
c -> outbufs -> head == c -> outbufs -> tail) {
|
||||||
|
if (c -> outbufs -> next) {
|
||||||
|
omapi_buffer_reference
|
||||||
|
(&buffer, c -> outbufs -> next,
|
||||||
|
"omapi_private_flush");
|
||||||
|
omapi_buffer_dereference
|
||||||
|
(&c -> outbufs -> next, "omapi_private_flush");
|
||||||
|
}
|
||||||
|
omapi_buffer_dereference (&c -> outbufs,
|
||||||
|
"omapi_private_flush");
|
||||||
|
if (buffer) {
|
||||||
|
omapi_buffer_reference (&c -> outbufs, buffer,
|
||||||
|
"omapi_private_flush");
|
||||||
|
omapi_buffer_dereference (&buffer,
|
||||||
|
"omapi_private_flush");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_get_uint32 (omapi_object_t *c,
|
||||||
|
u_int32_t *result)
|
||||||
|
{
|
||||||
|
u_int32_t inbuf;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
status = omapi_connection_copyout ((unsigned char *)&inbuf,
|
||||||
|
c, sizeof inbuf);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
*result = ntohl (inbuf);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_put_uint32 (omapi_object_t *c,
|
||||||
|
u_int32_t value)
|
||||||
|
{
|
||||||
|
u_int32_t inbuf;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
inbuf = htonl (value);
|
||||||
|
|
||||||
|
return omapi_connection_copyin (c, (unsigned char *)&inbuf,
|
||||||
|
sizeof inbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_get_uint16 (omapi_object_t *c,
|
||||||
|
u_int16_t *result)
|
||||||
|
{
|
||||||
|
u_int16_t inbuf;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
status = omapi_connection_copyout ((unsigned char *)&inbuf,
|
||||||
|
c, sizeof inbuf);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
*result = ntohs (inbuf);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_put_uint16 (omapi_object_t *c,
|
||||||
|
u_int16_t value)
|
||||||
|
{
|
||||||
|
u_int16_t inbuf;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
inbuf = htons (value);
|
||||||
|
|
||||||
|
return omapi_connection_copyin (c, (unsigned char *)&inbuf,
|
||||||
|
sizeof inbuf);
|
||||||
|
}
|
||||||
|
|
360
omapip/connection.c
Normal file
360
omapip/connection.c
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
/* connection.c
|
||||||
|
|
||||||
|
Subroutines for dealing with connections. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
isc_result_t omapi_connect (omapi_object_t *c,
|
||||||
|
char *server_name,
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
struct hostent *he;
|
||||||
|
int hix;
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_connection_object_t *obj;
|
||||||
|
|
||||||
|
obj = (omapi_connection_object_t *)malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (obj, 0, sizeof *obj);
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_connection;
|
||||||
|
|
||||||
|
status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = omapi_object_reference (&obj -> inner, c,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up all the constants in the address... */
|
||||||
|
obj -> remote_addr.sin_port = htons (port);
|
||||||
|
|
||||||
|
/* First try for a numeric address, since that's easier to check. */
|
||||||
|
if (!inet_aton (server_name, &obj -> remote_addr.sin_addr)) {
|
||||||
|
/* If we didn't get a numeric address, try for a domain
|
||||||
|
name. It's okay for this call to block. */
|
||||||
|
he = gethostbyname (server_name);
|
||||||
|
if (!he) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_connect");
|
||||||
|
return ISC_R_HOSTUNKNOWN;
|
||||||
|
}
|
||||||
|
hix = 1;
|
||||||
|
memcpy (&obj -> remote_addr.sin_addr,
|
||||||
|
he -> h_addr_list [0],
|
||||||
|
sizeof obj -> remote_addr.sin_addr);
|
||||||
|
} else
|
||||||
|
he = (struct hostent *)0;
|
||||||
|
|
||||||
|
obj -> remote_addr.sin_len =
|
||||||
|
sizeof (struct sockaddr_in);
|
||||||
|
obj -> remote_addr.sin_family = AF_INET;
|
||||||
|
memset (&(obj -> remote_addr.sin_zero), 0,
|
||||||
|
sizeof obj -> remote_addr.sin_zero);
|
||||||
|
|
||||||
|
/* Create a socket on which to communicate. */
|
||||||
|
obj -> socket =
|
||||||
|
socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (obj -> socket < 0) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_connect");
|
||||||
|
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
|
||||||
|
return ISC_R_NORESOURCES;
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to connect to the one IP address we were given, or any of
|
||||||
|
the IP addresses listed in the host's A RR. */
|
||||||
|
while (connect (obj -> socket,
|
||||||
|
((struct sockaddr *)
|
||||||
|
&obj -> remote_addr),
|
||||||
|
sizeof obj -> remote_addr)) {
|
||||||
|
if (!he || !he -> h_addr_list [hix]) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_connect");
|
||||||
|
if (errno == ECONNREFUSED)
|
||||||
|
return ISC_R_CONNREFUSED;
|
||||||
|
if (errno == ENETUNREACH)
|
||||||
|
return ISC_R_NETUNREACH;
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
memcpy (&obj -> remote_addr.sin_addr,
|
||||||
|
he -> h_addr_list [hix++],
|
||||||
|
sizeof obj -> remote_addr.sin_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj -> state = omapi_connection_connected;
|
||||||
|
|
||||||
|
/* I don't know why this would fail, so I'm tempted not to test
|
||||||
|
the return value. */
|
||||||
|
hix = sizeof (obj -> local_addr);
|
||||||
|
if (getsockname (obj -> socket,
|
||||||
|
((struct sockaddr *)
|
||||||
|
&obj -> local_addr), &hix) < 0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_connect");
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_register_io_object ((omapi_object_t *)obj,
|
||||||
|
omapi_connection_readfd,
|
||||||
|
omapi_connection_writefd,
|
||||||
|
omapi_connection_reader,
|
||||||
|
omapi_connection_writer,
|
||||||
|
omapi_connection_reaper);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disconnect a connection object from the remote end. If force is nonzero,
|
||||||
|
close the connection immediately. Otherwise, shut down the receiving end
|
||||||
|
but allow any unsent data to be sent before actually closing the socket. */
|
||||||
|
|
||||||
|
isc_result_t omapi_disconnect (omapi_object_t *h,
|
||||||
|
int force)
|
||||||
|
{
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
if (c -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!force) {
|
||||||
|
/* If we're already disconnecting, we don't have to do
|
||||||
|
anything. */
|
||||||
|
if (c -> state == omapi_connection_disconnecting)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
/* Try to shut down the socket - this sends a FIN to the
|
||||||
|
remote end, so that it won't send us any more data. If
|
||||||
|
the shutdown succeeds, and we still have bytes left to
|
||||||
|
write, defer closing the socket until that's done. */
|
||||||
|
if (!shutdown (c -> socket, SHUT_RD)) {
|
||||||
|
if (c -> out_bytes > 0) {
|
||||||
|
c -> state = omapi_connection_disconnecting;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close (c -> socket);
|
||||||
|
c -> state = omapi_connection_closed;
|
||||||
|
|
||||||
|
/* Disconnect from I/O object, if any. */
|
||||||
|
if (h -> outer)
|
||||||
|
omapi_object_dereference (&h -> outer, "omapi_disconnect");
|
||||||
|
|
||||||
|
/* If whatever created us registered a signal handler, send it
|
||||||
|
a disconnect signal. */
|
||||||
|
omapi_signal (h, "disconnect", h);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_require (omapi_object_t *h, int bytes)
|
||||||
|
{
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
|
||||||
|
c -> bytes_needed = bytes;
|
||||||
|
if (c -> bytes_needed <= c -> in_bytes) {
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
return ISC_R_NOTYET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the socket on which the dispatcher should wait for readiness
|
||||||
|
to read, for a connection object. If we already have more bytes than
|
||||||
|
we need to do the next thing, and we have at least a single full input
|
||||||
|
buffer, then don't indicate that we're ready to read. */
|
||||||
|
int omapi_connection_readfd (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return -1;
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
if (c -> state != omapi_connection_connected)
|
||||||
|
return -1;
|
||||||
|
if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
|
||||||
|
c -> in_bytes > c -> bytes_needed)
|
||||||
|
return -1;
|
||||||
|
return c -> socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the socket on which the dispatcher should wait for readiness
|
||||||
|
to write, for a connection object. If there are no bytes buffered
|
||||||
|
for writing, then don't indicate that we're ready to write. */
|
||||||
|
int omapi_connection_writefd (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return -1;
|
||||||
|
if (c -> out_bytes)
|
||||||
|
return c -> socket;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reaper function for connection - if the connection is completely closed,
|
||||||
|
reap it. If it's in the disconnecting state, there were bytes left
|
||||||
|
to write when the user closed it, so if there are now no bytes left to
|
||||||
|
write, we can close it. */
|
||||||
|
isc_result_t omapi_connection_reaper (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
c = (omapi_connection_object_t *)h;
|
||||||
|
if (c -> state == omapi_connection_disconnecting &&
|
||||||
|
c -> out_bytes == 0)
|
||||||
|
omapi_disconnect (h, 1);
|
||||||
|
if (c -> state == omapi_connection_closed)
|
||||||
|
return ISC_R_NOTCONNECTED;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> set_value)
|
||||||
|
return (*(h -> inner -> type -> set_value))
|
||||||
|
(h -> inner, id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
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_connection_destroy (omapi_object_t *h, char *name)
|
||||||
|
{
|
||||||
|
omapi_connection_object_t *c;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
c = (omapi_connection_object_t *)(h);
|
||||||
|
if (c -> state == omapi_connection_connected)
|
||||||
|
omapi_disconnect (h, 1);
|
||||||
|
if (c -> listener)
|
||||||
|
omapi_object_dereference (&c -> listener, name);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_connection)
|
||||||
|
return ISC_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_connection_stuff_values (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *m)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (m -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (m -> inner && m -> inner -> type -> stuff_values)
|
||||||
|
return (*(m -> inner -> type -> stuff_values)) (c, id,
|
||||||
|
m -> inner);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_connection_write_typed_data (omapi_object_t *c,
|
||||||
|
omapi_typed_data_t *data)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_handle_t handle;
|
||||||
|
|
||||||
|
switch (data -> type) {
|
||||||
|
case omapi_datatype_int:
|
||||||
|
status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
return omapi_connection_put_uint32 (c, data -> u.integer);
|
||||||
|
|
||||||
|
case omapi_datatype_string:
|
||||||
|
case omapi_datatype_data:
|
||||||
|
status = omapi_connection_put_uint32 (c, data -> u.buffer.len);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
return omapi_connection_copyin (c, data -> u.buffer.value,
|
||||||
|
data -> u.buffer.len);
|
||||||
|
|
||||||
|
case omapi_datatype_object:
|
||||||
|
status = omapi_object_handle (&handle,
|
||||||
|
data -> u.object);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
status = omapi_connection_put_uint32 (c, sizeof handle);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
return omapi_connection_put_uint32 (c, handle);
|
||||||
|
|
||||||
|
}
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
379
omapip/dispatch.c
Normal file
379
omapip/dispatch.c
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
/* dispatch.c
|
||||||
|
|
||||||
|
I/O dispatcher. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
static omapi_io_object_t omapi_io_states;
|
||||||
|
u_int32_t cur_time;
|
||||||
|
|
||||||
|
/* Register an I/O handle so that we can do asynchronous I/O on it. */
|
||||||
|
|
||||||
|
isc_result_t omapi_register_io_object (omapi_object_t *h,
|
||||||
|
int (*readfd) (omapi_object_t *),
|
||||||
|
int (*writefd) (omapi_object_t *),
|
||||||
|
isc_result_t (*reader)
|
||||||
|
(omapi_object_t *),
|
||||||
|
isc_result_t (*writer)
|
||||||
|
(omapi_object_t *),
|
||||||
|
isc_result_t (*reaper)
|
||||||
|
(omapi_object_t *))
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_io_object_t *obj, *p;
|
||||||
|
|
||||||
|
/* omapi_io_states is a static object. If its reference count
|
||||||
|
is zero, this is the first I/O handle to be registered, so
|
||||||
|
we need to initialize it. Because there is no inner or outer
|
||||||
|
pointer on this object, and we're setting its refcnt to 1, it
|
||||||
|
will never be freed. */
|
||||||
|
if (!omapi_io_states.refcnt) {
|
||||||
|
omapi_io_states.refcnt = 1;
|
||||||
|
omapi_io_states.type = omapi_type_io_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (obj, 0, sizeof *obj);
|
||||||
|
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_io_object;
|
||||||
|
|
||||||
|
status = omapi_object_reference (&obj -> inner, h,
|
||||||
|
"omapi_register_io_object");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_register_io_object");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
|
||||||
|
"omapi_register_io_object");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_register_io_object");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the last I/O state, if there are any. */
|
||||||
|
for (p = omapi_io_states.next;
|
||||||
|
p && p -> next; p = p -> next)
|
||||||
|
;
|
||||||
|
if (p)
|
||||||
|
p -> next = obj;
|
||||||
|
else
|
||||||
|
omapi_io_states.next = obj;
|
||||||
|
|
||||||
|
obj -> readfd = readfd;
|
||||||
|
obj -> writefd = writefd;
|
||||||
|
obj -> reader = reader;
|
||||||
|
obj -> writer = writer;
|
||||||
|
obj -> reaper = reaper;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_dispatch (struct timeval *t)
|
||||||
|
{
|
||||||
|
return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
|
||||||
|
t);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_wait_for_completion (omapi_object_t *object,
|
||||||
|
struct timeval *t)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_waiter_object_t *waiter;
|
||||||
|
omapi_object_t *inner;
|
||||||
|
|
||||||
|
if (object) {
|
||||||
|
waiter = malloc (sizeof *waiter);
|
||||||
|
if (!waiter)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (waiter, 0, sizeof *waiter);
|
||||||
|
waiter -> refcnt = 1;
|
||||||
|
waiter -> type = omapi_type_waiter;
|
||||||
|
|
||||||
|
/* Paste the waiter object onto the inner object we're
|
||||||
|
waiting on. */
|
||||||
|
for (inner = object; inner -> inner; inner = inner -> inner)
|
||||||
|
;
|
||||||
|
|
||||||
|
status = omapi_object_reference (&waiter -> outer, inner,
|
||||||
|
"omapi_wait_for_completion");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&waiter,
|
||||||
|
"omapi_wait_for_completion");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_object_reference (&inner -> inner,
|
||||||
|
(omapi_object_t *)waiter,
|
||||||
|
"omapi_wait_for_completion");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&waiter,
|
||||||
|
"omapi_wait_for_completion");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
waiter = (omapi_waiter_object_t *)0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = omapi_one_dispatch (waiter, t);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
} while (!waiter || !waiter -> ready);
|
||||||
|
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&waiter,
|
||||||
|
"omapi_wait_for_completion");
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_one_dispatch (omapi_waiter_object_t *waiter,
|
||||||
|
struct timeval *t)
|
||||||
|
{
|
||||||
|
fd_set r, w, x;
|
||||||
|
int max = 0;
|
||||||
|
int count;
|
||||||
|
int desc;
|
||||||
|
struct timeval now, to;
|
||||||
|
omapi_io_object_t *io, *prev;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
FD_ZERO (&x);
|
||||||
|
|
||||||
|
/* First, see if the timeout has expired, and if so return. */
|
||||||
|
if (t) {
|
||||||
|
gettimeofday (&now, (struct timezone *)0);
|
||||||
|
cur_time = now.tv_sec;
|
||||||
|
if (now.tv_sec > t -> tv_sec ||
|
||||||
|
(now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
|
||||||
|
return ISC_R_TIMEDOUT;
|
||||||
|
|
||||||
|
/* We didn't time out, so figure out how long until
|
||||||
|
we do. */
|
||||||
|
to.tv_sec = t -> tv_sec - now.tv_sec;
|
||||||
|
to.tv_usec = t -> tv_usec - now.tv_usec;
|
||||||
|
if (to.tv_usec < 0) {
|
||||||
|
to.tv_usec += 1000000;
|
||||||
|
to.tv_sec--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the object we're waiting on has reached completion,
|
||||||
|
return now. */
|
||||||
|
if (waiter && waiter -> ready)
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
/* If we have no I/O state, we can't proceed. */
|
||||||
|
if (!(io = omapi_io_states.next))
|
||||||
|
return ISC_R_NOMORE;
|
||||||
|
|
||||||
|
/* Set up the read and write masks. */
|
||||||
|
FD_ZERO (&r);
|
||||||
|
FD_ZERO (&w);
|
||||||
|
|
||||||
|
for (; io; io = io -> next) {
|
||||||
|
/* Check for a read socket. If we shouldn't be
|
||||||
|
trying to read for this I/O object, either there
|
||||||
|
won't be a readfd function, or it'll return -1. */
|
||||||
|
if (io -> readfd &&
|
||||||
|
(desc = (*(io -> readfd)) (io -> inner)) >= 0) {
|
||||||
|
FD_SET (desc, &r);
|
||||||
|
if (desc > max)
|
||||||
|
max = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Same deal for write fdets. */
|
||||||
|
if (io -> writefd &&
|
||||||
|
(desc = (*(io -> writefd)) (io -> inner)) >= 0) {
|
||||||
|
FD_SET (desc, &w);
|
||||||
|
if (desc > max)
|
||||||
|
max = desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for a packet or a timeout... XXX */
|
||||||
|
count = select (max + 1, &r, &w, &x, t ? &to : (struct timeval *)0);
|
||||||
|
|
||||||
|
/* Get the current time... */
|
||||||
|
gettimeofday (&now, (struct timezone *)0);
|
||||||
|
cur_time = now.tv_sec;
|
||||||
|
|
||||||
|
/* Not likely to be transitory... */
|
||||||
|
if (count < 0)
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
|
||||||
|
for (io = omapi_io_states.next; io; io = io -> next) {
|
||||||
|
/* Check for a read descriptor, and if there is one,
|
||||||
|
see if we got input on that socket. */
|
||||||
|
if (io -> readfd &&
|
||||||
|
(desc = (*(io -> readfd)) (io -> inner)) >= 0) {
|
||||||
|
if (FD_ISSET (desc, &r))
|
||||||
|
status = ((*(io -> reader)) (io -> inner));
|
||||||
|
/* XXX what to do with status? */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Same deal for write descriptors. */
|
||||||
|
if (io -> writefd &&
|
||||||
|
(desc = (*(io -> writefd)) (io -> inner)) >= 0)
|
||||||
|
{
|
||||||
|
if (FD_ISSET (desc, &w))
|
||||||
|
status = ((*(io -> writer)) (io -> inner));
|
||||||
|
/* XXX what to do with status? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check for I/O handles that are no longer valid,
|
||||||
|
and remove them from the list. */
|
||||||
|
prev = (omapi_io_object_t *)0;
|
||||||
|
for (io = omapi_io_states.next; io; io = io -> next) {
|
||||||
|
if (io -> reaper) {
|
||||||
|
status = (*(io -> reaper)) (io -> inner);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_io_object_t *tmp =
|
||||||
|
(omapi_io_object_t *)0;
|
||||||
|
/* Save a reference to the next
|
||||||
|
pointer, if there is one. */
|
||||||
|
if (io -> next)
|
||||||
|
omapi_object_reference
|
||||||
|
((omapi_object_t **)&tmp,
|
||||||
|
(omapi_object_t *)io -> next,
|
||||||
|
"omapi_wfc");
|
||||||
|
if (prev) {
|
||||||
|
omapi_object_dereference
|
||||||
|
(((omapi_object_t **)
|
||||||
|
&prev -> next), "omapi_wfc");
|
||||||
|
if (tmp)
|
||||||
|
omapi_object_reference
|
||||||
|
(((omapi_object_t **)
|
||||||
|
&prev -> next),
|
||||||
|
(omapi_object_t *)tmp,
|
||||||
|
"omapi_wfc");
|
||||||
|
} else {
|
||||||
|
omapi_object_dereference
|
||||||
|
(((omapi_object_t **)
|
||||||
|
&omapi_io_states.next),
|
||||||
|
"omapi_wfc");
|
||||||
|
if (tmp)
|
||||||
|
omapi_object_reference
|
||||||
|
(((omapi_object_t **)
|
||||||
|
&omapi_io_states.next),
|
||||||
|
(omapi_object_t *)tmp,
|
||||||
|
"omapi_wfc");
|
||||||
|
else
|
||||||
|
omapi_signal_in
|
||||||
|
((omapi_object_t *)
|
||||||
|
&omapi_io_states,
|
||||||
|
"ready");
|
||||||
|
}
|
||||||
|
if (tmp)
|
||||||
|
omapi_object_dereference
|
||||||
|
((omapi_object_t **)&tmp,
|
||||||
|
"omapi_wfc");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = io;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_io_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_io_object)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> set_value)
|
||||||
|
return (*(h -> inner -> type -> set_value))
|
||||||
|
(h -> inner, id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_io_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_io_object)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
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_io_destroy (omapi_object_t *h, char *name)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_io_object)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_io_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_io_object)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> signal_handler)
|
||||||
|
return (*(h -> inner -> type -> signal_handler)) (h -> inner,
|
||||||
|
name, ap);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_io_stuff_values (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *i)
|
||||||
|
{
|
||||||
|
if (i -> type != omapi_type_io_object)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (i -> inner && i -> inner -> type -> stuff_values)
|
||||||
|
return (*(i -> inner -> type -> stuff_values)) (c, id,
|
||||||
|
i -> inner);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
omapi_waiter_object_t *waiter;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_waiter)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (!strcmp (name, "ready")) {
|
||||||
|
waiter = (omapi_waiter_object_t *)h;
|
||||||
|
waiter -> ready = 1;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> signal_handler)
|
||||||
|
return (*(h -> inner -> type -> signal_handler)) (h -> inner,
|
||||||
|
name, ap);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
249
omapip/generic.c
Normal file
249
omapip/generic.c
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
/* generic.c
|
||||||
|
|
||||||
|
Subroutines that support the generic object. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
isc_result_t omapi_generic_new (omapi_object_t **gen, char *name)
|
||||||
|
{
|
||||||
|
omapi_generic_object_t *obj;
|
||||||
|
|
||||||
|
obj = malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (obj, 0, sizeof *obj);
|
||||||
|
obj -> refcnt = 0;
|
||||||
|
obj -> type = omapi_type_generic;
|
||||||
|
|
||||||
|
return omapi_object_reference (gen, (omapi_object_t *)obj, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int vm_new;
|
||||||
|
int i;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_generic)
|
||||||
|
return ISC_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,
|
||||||
|
"omapi_message_get_value"));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
omapi_data_string_reference
|
||||||
|
(&new -> name, name,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
if (value)
|
||||||
|
omapi_typed_data_reference
|
||||||
|
(&new -> value, value,
|
||||||
|
"omapi_generic_set_value");
|
||||||
|
|
||||||
|
omapi_value_dereference (&(g -> values [i]),
|
||||||
|
"omapi_message_set_value");
|
||||||
|
status = (omapi_value_reference
|
||||||
|
(&(g -> values [i]), new,
|
||||||
|
"omapi_message_set_value"));
|
||||||
|
omapi_value_dereference (&new,
|
||||||
|
"omapi_message_set_value");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 (g -> nvalues == g -> va_max) {
|
||||||
|
if (g -> va_max)
|
||||||
|
vm_new = 2 * g -> va_max;
|
||||||
|
else
|
||||||
|
vm_new = 10;
|
||||||
|
va = malloc (vm_new * sizeof *va);
|
||||||
|
if (!va)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
if (g -> va_max)
|
||||||
|
memcpy (va, g -> values, g -> va_max * sizeof *va);
|
||||||
|
memset (va + g -> va_max, 0,
|
||||||
|
(vm_new - g -> va_max) * sizeof *va);
|
||||||
|
free (g -> values);
|
||||||
|
g -> values = va;
|
||||||
|
}
|
||||||
|
status = omapi_value_new (&g -> values [g -> nvalues],
|
||||||
|
"omapi_generic_set_value");
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
omapi_data_string_reference (&g -> values [g -> nvalues] -> name, name,
|
||||||
|
"omapi_generic_set_value");
|
||||||
|
if (value)
|
||||||
|
omapi_typed_data_reference
|
||||||
|
(&g -> values [g -> nvalues] -> value, value,
|
||||||
|
"omapi_generic_set_value");
|
||||||
|
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 ISC_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 (!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],
|
||||||
|
"omapi_message_get_value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, char *name)
|
||||||
|
{
|
||||||
|
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],
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
free (g -> values);
|
||||||
|
g -> values = (omapi_value_t **)0;
|
||||||
|
g -> va_max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_generic_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_generic)
|
||||||
|
return ISC_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 ISC_R_INVALIDARG;
|
||||||
|
src = (omapi_generic_object_t *)g;
|
||||||
|
|
||||||
|
for (i = 0; i < src -> nvalues; i++) {
|
||||||
|
if (src -> values [i] && src -> values [i] -> name -> len) {
|
||||||
|
status = (omapi_connection_put_uint16
|
||||||
|
(c, src -> values [i] -> name -> len));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
status = (omapi_connection_copyout
|
||||||
|
(src -> values [i] -> name -> value, c,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
265
omapip/handle.c
Normal file
265
omapip/handle.c
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
/* handle.c
|
||||||
|
|
||||||
|
Functions for maintaining handles on objects. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
/* The handle table is a hierarchical tree designed for quick mapping
|
||||||
|
of handle identifiers to objects. Objects contain their own handle
|
||||||
|
identifiers if they have them, so the reverse mapping is also
|
||||||
|
quick. The hierarchy is made up of table objects, each of which
|
||||||
|
has 120 entries, a flag indicating whether the table is a leaf
|
||||||
|
table or an indirect table, the handle of the first object covered
|
||||||
|
by the table and the first object after that that's *not* covered
|
||||||
|
by the table, a count of how many objects of either type are
|
||||||
|
currently stored in the table, and an array of 120 entries pointing
|
||||||
|
either to objects or tables.
|
||||||
|
|
||||||
|
When we go to add an object to the table, we look to see if the
|
||||||
|
next object handle to be assigned is covered by the outermost
|
||||||
|
table. If it is, we find the place within that table where the
|
||||||
|
next handle should go, and if necessary create additional nodes in
|
||||||
|
the tree to contain the new handle. The pointer to the object is
|
||||||
|
then stored in the correct position.
|
||||||
|
|
||||||
|
Theoretically, we could have some code here to free up handle
|
||||||
|
tables as they go out of use, but by and large handle tables won't
|
||||||
|
go out of use, so this is being skipped for now. It shouldn't be
|
||||||
|
too hard to implement in the future if there's a different
|
||||||
|
application. */
|
||||||
|
|
||||||
|
omapi_handle_table_t *omapi_handle_table;
|
||||||
|
omapi_handle_t omapi_next_handle = 1; /* Next handle to be assigned. */
|
||||||
|
|
||||||
|
static isc_result_t omapi_handle_lookup_in (omapi_object_t **,
|
||||||
|
omapi_handle_t,
|
||||||
|
omapi_handle_table_t *);
|
||||||
|
static isc_result_t omapi_object_handle_in_table (omapi_handle_t,
|
||||||
|
omapi_handle_table_t *,
|
||||||
|
omapi_object_t *);
|
||||||
|
static isc_result_t omapi_handle_table_enclose (omapi_handle_table_t **);
|
||||||
|
|
||||||
|
isc_result_t omapi_object_handle (omapi_handle_t *h, omapi_object_t *o)
|
||||||
|
{
|
||||||
|
int tabix;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
if (o -> handle) {
|
||||||
|
*h = o -> handle;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!omapi_handle_table) {
|
||||||
|
omapi_handle_table = malloc (sizeof *omapi_handle_table);
|
||||||
|
if (!omapi_handle_table)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (omapi_handle_table, 0, sizeof *omapi_handle_table);
|
||||||
|
omapi_handle_table -> first = 0;
|
||||||
|
omapi_handle_table -> limit = OMAPI_HANDLE_TABLE_SIZE;
|
||||||
|
omapi_handle_table -> leafp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this handle doesn't fit in the outer table, we need to
|
||||||
|
make a new outer table. This is a while loop in case for
|
||||||
|
some reason we decide to do disjoint handle allocation,
|
||||||
|
where the next level of indirection still isn't big enough
|
||||||
|
to enclose the next handle ID. */
|
||||||
|
|
||||||
|
while (omapi_next_handle >= omapi_handle_table -> limit) {
|
||||||
|
omapi_handle_table_t *new;
|
||||||
|
|
||||||
|
new = malloc (sizeof *new);
|
||||||
|
if (!new)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (omapi_handle_table, 0, sizeof *omapi_handle_table);
|
||||||
|
new -> first = 0;
|
||||||
|
new -> limit = (omapi_handle_table -> limit *
|
||||||
|
OMAPI_HANDLE_TABLE_SIZE);
|
||||||
|
new -> leafp = 0;
|
||||||
|
new -> children [0].table = omapi_handle_table;
|
||||||
|
omapi_handle_table = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to cram this handle into the existing table. */
|
||||||
|
status = omapi_object_handle_in_table (omapi_next_handle,
|
||||||
|
omapi_handle_table, o);
|
||||||
|
/* If it worked, return the next handle and increment it. */
|
||||||
|
if (status == ISC_R_SUCCESS) {
|
||||||
|
*h = omapi_next_handle;
|
||||||
|
omapi_next_handle++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
if (status != ISC_R_NOSPACE)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_handle_table_enclose (&omapi_handle_table);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_handle_in_table (omapi_next_handle,
|
||||||
|
omapi_handle_table, o);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
*h = omapi_next_handle;
|
||||||
|
omapi_next_handle++;
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t omapi_object_handle_in_table (omapi_handle_t h,
|
||||||
|
omapi_handle_table_t *table,
|
||||||
|
omapi_object_t *o)
|
||||||
|
{
|
||||||
|
omapi_handle_table_t *inner;
|
||||||
|
omapi_handle_t scale, index;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
if (table -> first > h || table -> limit <= h)
|
||||||
|
return ISC_R_NOSPACE;
|
||||||
|
|
||||||
|
/* If this is a leaf table, just stash the object in the
|
||||||
|
appropriate place. */
|
||||||
|
if (table -> leafp) {
|
||||||
|
status = (omapi_object_reference
|
||||||
|
(&table -> children [h - table -> first].object,
|
||||||
|
o, "omapi_object_handle_in_table"));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
o -> handle = h;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale is the number of handles represented by each child of this
|
||||||
|
table. For a leaf table, scale would be 1. For a first level
|
||||||
|
of indirection, 120. For a second, 120 * 120. Et cetera. */
|
||||||
|
scale = (table -> limit - table -> first) / OMAPI_HANDLE_TABLE_SIZE;
|
||||||
|
|
||||||
|
/* So the next most direct table from this one that contains the
|
||||||
|
handle must be the subtable of this table whose index into this
|
||||||
|
table's array of children is the handle divided by the scale. */
|
||||||
|
index = (h - table -> first) / scale;
|
||||||
|
inner = table -> children [index].table;
|
||||||
|
|
||||||
|
/* If there is no more direct table than this one in the slot
|
||||||
|
we came up with, make one. */
|
||||||
|
if (!inner) {
|
||||||
|
inner = malloc (sizeof *inner);
|
||||||
|
if (!inner)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (inner, 0, sizeof *inner);
|
||||||
|
inner -> first = index * scale + table -> first;
|
||||||
|
inner -> limit = inner -> first + scale;
|
||||||
|
if (scale == OMAPI_HANDLE_TABLE_SIZE)
|
||||||
|
inner -> leafp = 1;
|
||||||
|
table -> children [index].table = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_object_handle_in_table (h, inner, o);
|
||||||
|
if (status == ISC_R_NOSPACE) {
|
||||||
|
status = (omapi_handle_table_enclose
|
||||||
|
(&table -> children [index].table));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return omapi_object_handle_in_table
|
||||||
|
(h, table -> children [index].table, o);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t omapi_handle_table_enclose (omapi_handle_table_t **table)
|
||||||
|
{
|
||||||
|
omapi_handle_table_t *inner = *table;
|
||||||
|
omapi_handle_table_t *new;
|
||||||
|
int index, base, scale;
|
||||||
|
|
||||||
|
/* The scale of the table we're enclosing is going to be the
|
||||||
|
difference between its "first" and "limit" members. So the
|
||||||
|
scale of the table enclosing it is going to be that multiplied
|
||||||
|
by the table size. */
|
||||||
|
scale = (inner -> first - inner -> limit) * OMAPI_HANDLE_TABLE_SIZE;
|
||||||
|
|
||||||
|
/* The range that the enclosing table covers is going to be
|
||||||
|
the result of subtracting the remainder of dividing the
|
||||||
|
enclosed table's first entry number by the enclosing
|
||||||
|
table's scale. If handle IDs are being allocated
|
||||||
|
sequentially, the enclosing table's "first" value will be
|
||||||
|
the same as the enclosed table's "first" value. */
|
||||||
|
base = inner -> first - inner -> first % scale;
|
||||||
|
|
||||||
|
/* The index into the enclosing table at which the enclosed table
|
||||||
|
will be stored is going to be the difference between the "first"
|
||||||
|
value of the enclosing table and the enclosed table - zero, if
|
||||||
|
we are allocating sequentially. */
|
||||||
|
index = (base - inner -> first) / OMAPI_HANDLE_TABLE_SIZE;
|
||||||
|
|
||||||
|
new = malloc (sizeof *new);
|
||||||
|
if (!new)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (new, 0, sizeof *new);
|
||||||
|
new -> first = base;
|
||||||
|
new -> limit = base + scale;
|
||||||
|
if (scale == OMAPI_HANDLE_TABLE_SIZE)
|
||||||
|
new -> leafp = 0;
|
||||||
|
new -> children [index].table = inner;
|
||||||
|
*table = new;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_handle_lookup (omapi_object_t **o, omapi_handle_t h)
|
||||||
|
{
|
||||||
|
return omapi_handle_lookup_in (o, h, omapi_handle_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t omapi_handle_lookup_in (omapi_object_t **o,
|
||||||
|
omapi_handle_t h,
|
||||||
|
omapi_handle_table_t *table)
|
||||||
|
|
||||||
|
{
|
||||||
|
omapi_handle_table_t *inner;
|
||||||
|
omapi_handle_t scale, index;
|
||||||
|
|
||||||
|
if (!table || table -> first > h || table -> limit <= h)
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
|
||||||
|
/* If this is a leaf table, just grab the object. */
|
||||||
|
if (table -> leafp) {
|
||||||
|
/* Not there? */
|
||||||
|
if (!table -> children [h - table -> first].object)
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
return omapi_object_reference
|
||||||
|
(o, table -> children [h - table -> first].object,
|
||||||
|
"omapi_handle_lookup_in");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale is the number of handles represented by each child of this
|
||||||
|
table. For a leaf table, scale would be 1. For a first level
|
||||||
|
of indirection, 120. For a second, 120 * 120. Et cetera. */
|
||||||
|
scale = (table -> limit - table -> first) / OMAPI_HANDLE_TABLE_SIZE;
|
||||||
|
|
||||||
|
/* So the next most direct table from this one that contains the
|
||||||
|
handle must be the subtable of this table whose index into this
|
||||||
|
table's array of children is the handle divided by the scale. */
|
||||||
|
index = (h - table -> first) / scale;
|
||||||
|
inner = table -> children [index].table;
|
||||||
|
|
||||||
|
return omapi_handle_lookup_in (o, h, table -> children [index].table);
|
||||||
|
}
|
246
omapip/listener.c
Normal file
246
omapip/listener.c
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
/* listener.c
|
||||||
|
|
||||||
|
Subroutines that support the generic listener object. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
isc_result_t omapi_listen (omapi_object_t *h,
|
||||||
|
int port,
|
||||||
|
int max)
|
||||||
|
{
|
||||||
|
struct hostent *he;
|
||||||
|
int hix;
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_listener_object_t *obj;
|
||||||
|
|
||||||
|
/* Get the handle. */
|
||||||
|
obj = (omapi_listener_object_t *)malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_listener;
|
||||||
|
|
||||||
|
/* Connect this object to the inner object. */
|
||||||
|
status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = omapi_object_reference (&obj -> inner, h,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the address on which we will listen... */
|
||||||
|
obj -> address.sin_port = htons (port);
|
||||||
|
obj -> address.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||||
|
|
||||||
|
/* Create a socket on which to listen. */
|
||||||
|
obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (!obj -> socket) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_listen");
|
||||||
|
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
|
||||||
|
return ISC_R_NORESOURCES;
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to bind to the wildcard address using the port number
|
||||||
|
we were given. */
|
||||||
|
if (bind (obj -> socket,
|
||||||
|
(struct sockaddr *)&obj -> address, sizeof obj -> address)) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_listen");
|
||||||
|
if (errno == EADDRINUSE)
|
||||||
|
return ISC_R_ADDRNOTAVAIL;
|
||||||
|
if (errno == EPERM)
|
||||||
|
return ISC_R_NOPERM;
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now tell the kernel to listen for connections. */
|
||||||
|
if (listen (obj -> socket, max)) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_listen");
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_register_io_object ((omapi_object_t *)obj,
|
||||||
|
omapi_listener_readfd, 0,
|
||||||
|
omapi_accept, 0, 0);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_listen");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the socket on which the dispatcher should wait for readiness
|
||||||
|
to read, for a listener object. */
|
||||||
|
int omapi_listener_readfd (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
omapi_listener_object_t *l;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_listener)
|
||||||
|
return -1;
|
||||||
|
l = (omapi_listener_object_t *)h;
|
||||||
|
|
||||||
|
return l -> socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reader callback for a listener object. Accept an incoming connection. */
|
||||||
|
isc_result_t omapi_accept (omapi_object_t *h)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
int len;
|
||||||
|
omapi_connection_object_t *obj;
|
||||||
|
omapi_listener_object_t *listener;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_listener)
|
||||||
|
return -1;
|
||||||
|
listener = (omapi_listener_object_t *)h;
|
||||||
|
|
||||||
|
/* Get the handle. */
|
||||||
|
obj = (omapi_connection_object_t *)malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_connection;
|
||||||
|
|
||||||
|
/* Accept the connection. */
|
||||||
|
len = sizeof obj -> remote_addr;
|
||||||
|
obj -> socket =
|
||||||
|
accept (listener -> socket,
|
||||||
|
((struct sockaddr *)
|
||||||
|
&(obj -> remote_addr)), &len);
|
||||||
|
if (!obj -> socket) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_accept");
|
||||||
|
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
|
||||||
|
return ISC_R_NORESOURCES;
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj -> state = omapi_connection_connected;
|
||||||
|
|
||||||
|
status = omapi_register_io_object ((omapi_object_t *)obj,
|
||||||
|
omapi_connection_readfd,
|
||||||
|
omapi_connection_writefd,
|
||||||
|
omapi_connection_reader,
|
||||||
|
omapi_connection_writer,
|
||||||
|
omapi_connection_reaper);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_accept");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
omapi_object_reference (&obj -> listener, (omapi_object_t *)listener,
|
||||||
|
"omapi_accept");
|
||||||
|
|
||||||
|
status = omapi_signal (h, "connect", obj);
|
||||||
|
|
||||||
|
/* Lose our reference to the connection, so it'll be gc'd when it's
|
||||||
|
reaped. */
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj, "omapi_accept");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_listener_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> set_value)
|
||||||
|
return (*(h -> inner -> type -> set_value))
|
||||||
|
(h -> inner, id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_listener_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
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_listener_destroy (omapi_object_t *h, char *name)
|
||||||
|
{
|
||||||
|
omapi_listener_object_t *l;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
l = (omapi_listener_object_t *)(h);
|
||||||
|
|
||||||
|
if (l -> socket != -1) {
|
||||||
|
close (l -> socket);
|
||||||
|
l -> socket = -1;
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_listener_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_listener)
|
||||||
|
return ISC_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_listener_stuff_values (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *l)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (l -> type != omapi_type_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (l -> inner && l -> inner -> type -> stuff_values)
|
||||||
|
return (*(l -> inner -> type -> stuff_values)) (c, id,
|
||||||
|
l -> inner);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
294
omapip/message.c
Normal file
294
omapip/message.c
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
/* message.c
|
||||||
|
|
||||||
|
Subroutines for dealing with message objects. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
omapi_message_object_t *omapi_registered_messages;
|
||||||
|
|
||||||
|
isc_result_t omapi_message_new (omapi_object_t **o, char *name)
|
||||||
|
{
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
m = malloc (sizeof *m);
|
||||||
|
if (!m)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (m, 0, sizeof *m);
|
||||||
|
m -> type = omapi_type_message;
|
||||||
|
m -> refcnt = 1;
|
||||||
|
|
||||||
|
status = omapi_object_reference (o, (omapi_object_t *)m, name);
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m, name);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_message_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m = (omapi_message_object_t *)h;
|
||||||
|
|
||||||
|
/* Can't set authlen. */
|
||||||
|
|
||||||
|
/* Can set authenticator, but the value must be typed data. */
|
||||||
|
if (!omapi_ds_strcmp (name, "authenticator")) {
|
||||||
|
if (m -> authenticator)
|
||||||
|
omapi_typed_data_dereference
|
||||||
|
(&m -> authenticator,
|
||||||
|
"omapi_message_set_value");
|
||||||
|
omapi_typed_data_reference (&m -> authenticator,
|
||||||
|
value,
|
||||||
|
"omapi_message_set_value");
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
|
||||||
|
/* Can set authid, but it has to be an integer. */
|
||||||
|
} else if (!omapi_ds_strcmp (name, "authid")) {
|
||||||
|
if (value -> type != omapi_datatype_int)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m -> authid = value -> u.integer;
|
||||||
|
|
||||||
|
/* Can set op, but it has to be an integer. */
|
||||||
|
} else if (!omapi_ds_strcmp (name, "op")) {
|
||||||
|
if (value -> type != omapi_datatype_int)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m -> op = value -> u.integer;
|
||||||
|
|
||||||
|
/* Handle also has to be an integer. */
|
||||||
|
} else if (!omapi_ds_strcmp (name, "handle")) {
|
||||||
|
if (value -> type != omapi_datatype_int)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m -> h = value -> u.integer;
|
||||||
|
|
||||||
|
/* Transaction ID has to be an integer. */
|
||||||
|
} else if (!omapi_ds_strcmp (name, "id")) {
|
||||||
|
if (value -> type != omapi_datatype_int)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m -> id = value -> u.integer;
|
||||||
|
|
||||||
|
/* Remote transaction ID has to be an integer. */
|
||||||
|
} else if (!omapi_ds_strcmp (name, "rid")) {
|
||||||
|
if (value -> type != omapi_datatype_int)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m -> rid = value -> u.integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to find some inner object that can take the value. */
|
||||||
|
if (h -> inner && h -> inner -> type -> set_value) {
|
||||||
|
status = ((*(h -> inner -> type -> set_value))
|
||||||
|
(h -> inner, id, name, value));
|
||||||
|
if (status == ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_message_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
if (h -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m = (omapi_message_object_t *)h;
|
||||||
|
|
||||||
|
/* Look for values that are in the message data structure. */
|
||||||
|
if (!omapi_ds_strcmp (name, "authlen"))
|
||||||
|
return omapi_make_int_value (value, name, m -> authlen,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
else if (!omapi_ds_strcmp (name, "authenticator")) {
|
||||||
|
if (m -> authenticator)
|
||||||
|
return omapi_make_value (value,
|
||||||
|
name, m -> authenticator,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
else
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
} else if (!omapi_ds_strcmp (name, "authid")) {
|
||||||
|
return omapi_make_int_value (value, name, m -> authid,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
} else if (!omapi_ds_strcmp (name, "op")) {
|
||||||
|
return omapi_make_int_value (value, name, m -> op,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
} else if (!omapi_ds_strcmp (name, "handle")) {
|
||||||
|
return omapi_make_int_value (value, name, m -> handle,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
} else if (!omapi_ds_strcmp (name, "id")) {
|
||||||
|
return omapi_make_int_value (value, name, m -> id,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
} else if (!omapi_ds_strcmp (name, "rid")) {
|
||||||
|
return omapi_make_int_value (value, name, m -> rid,
|
||||||
|
"omapi_message_get_value");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if there's an inner object that has the value. */
|
||||||
|
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_message_destroy (omapi_object_t *h, char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
if (h -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
if (m -> authenticator) {
|
||||||
|
omapi_typed_data_dereference (&m -> authenticator, name);
|
||||||
|
}
|
||||||
|
if (!m -> prev && omapi_registered_messages != m)
|
||||||
|
omapi_message_unregister (h);
|
||||||
|
if (m -> prev)
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m -> prev, name);
|
||||||
|
if (m -> next)
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m -> next, name);
|
||||||
|
if (m -> id_object)
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m -> id_object,
|
||||||
|
name);
|
||||||
|
if (m -> object)
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m -> object,
|
||||||
|
name);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_message_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_message)
|
||||||
|
return ISC_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_message_stuff_values (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *m)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (m -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (m -> inner && m -> inner -> type -> stuff_values)
|
||||||
|
return (*(m -> inner -> type -> stuff_values)) (c, id,
|
||||||
|
m -> inner);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_message_register (omapi_object_t *mo)
|
||||||
|
{
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
|
||||||
|
if (mo -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m = (omapi_message_object_t *)mo;
|
||||||
|
|
||||||
|
/* Already registered? */
|
||||||
|
if (m -> prev || m -> next || omapi_registered_messages == m)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (omapi_registered_messages) {
|
||||||
|
omapi_object_reference
|
||||||
|
((omapi_object_t **)&m -> next,
|
||||||
|
(omapi_object_t *)omapi_registered_messages,
|
||||||
|
"omapi_message_register");
|
||||||
|
omapi_object_reference
|
||||||
|
((omapi_object_t **)&omapi_registered_messages -> prev,
|
||||||
|
(omapi_object_t *)m, "omapi_message_register");
|
||||||
|
omapi_object_dereference
|
||||||
|
((omapi_object_t **)&omapi_registered_messages,
|
||||||
|
"omapi_message_register");
|
||||||
|
}
|
||||||
|
omapi_object_reference
|
||||||
|
((omapi_object_t **)&omapi_registered_messages,
|
||||||
|
(omapi_object_t *)m, "omapi_message_register");
|
||||||
|
return ISC_R_SUCCESS;;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_message_unregister (omapi_object_t *mo)
|
||||||
|
{
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
omapi_message_object_t *n;
|
||||||
|
|
||||||
|
if (mo -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
m = (omapi_message_object_t *)mo;
|
||||||
|
|
||||||
|
/* Not registered? */
|
||||||
|
if (!m -> prev && omapi_registered_messages != m)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
n = (omapi_message_object_t *)0;
|
||||||
|
if (m -> next) {
|
||||||
|
omapi_object_reference ((omapi_object_t **)&n,
|
||||||
|
(omapi_object_t *)m -> next,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m -> next,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
}
|
||||||
|
if (m -> prev) {
|
||||||
|
omapi_message_object_t *tmp = (omapi_message_object_t *)0;
|
||||||
|
omapi_object_reference ((omapi_object_t **)&tmp,
|
||||||
|
(omapi_object_t *)m -> prev,
|
||||||
|
"omapi_message_register");
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&m -> prev,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
if (tmp -> next)
|
||||||
|
omapi_object_dereference
|
||||||
|
((omapi_object_t **)&tmp -> next,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
if (n)
|
||||||
|
omapi_object_reference
|
||||||
|
((omapi_object_t **)&tmp -> next,
|
||||||
|
(omapi_object_t *)n,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&tmp,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
} else {
|
||||||
|
omapi_object_dereference
|
||||||
|
((omapi_object_t **)&omapi_registered_messages,
|
||||||
|
"omapi_unregister_message");
|
||||||
|
if (n)
|
||||||
|
omapi_object_reference
|
||||||
|
((omapi_object_t **)&omapi_registered_messages,
|
||||||
|
(omapi_object_t *)n,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
}
|
||||||
|
if (n)
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&n,
|
||||||
|
"omapi_message_unregister");
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
0
omapip/omapi.3
Normal file
0
omapip/omapi.3
Normal file
639
omapip/protocol.c
Normal file
639
omapip/protocol.c
Normal file
@@ -0,0 +1,639 @@
|
|||||||
|
/* protocol.c
|
||||||
|
|
||||||
|
Functions supporting the object management protocol... */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_connect (omapi_object_t *h,
|
||||||
|
char *server_name,
|
||||||
|
int port,
|
||||||
|
omapi_object_t *authinfo)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_protocol_object_t *obj;
|
||||||
|
|
||||||
|
obj = (omapi_protocol_object_t *)malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (obj, 0, sizeof *obj);
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_protocol;
|
||||||
|
|
||||||
|
status = omapi_connect ((omapi_object_t *)obj, server_name, port);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = omapi_object_reference (&obj -> inner, h,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the introductory message. */
|
||||||
|
status = omapi_protocol_send_intro ((omapi_object_t *)obj,
|
||||||
|
OMAPI_PROTOCOL_VERSION,
|
||||||
|
sizeof (omapi_protocol_header_t));
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authinfo)
|
||||||
|
omapi_object_reference (&obj -> authinfo, authinfo,
|
||||||
|
"omapi_protocol_connect");
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_accept");
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the protocol introduction message. */
|
||||||
|
isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
|
||||||
|
int ver,
|
||||||
|
int hsize)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_protocol_object_t *p;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_protocol)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
p = (omapi_protocol_object_t *)h;
|
||||||
|
|
||||||
|
if (!h -> outer || h -> outer -> type != omapi_type_connection)
|
||||||
|
return ISC_R_NOTCONNECTED;
|
||||||
|
|
||||||
|
status = omapi_connection_put_uint32 (h -> outer, ver);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_connection_put_uint32 (h -> outer, hsize);
|
||||||
|
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* Require the other end to send an intro - this kicks off the
|
||||||
|
protocol input state machine. */
|
||||||
|
p -> state = omapi_protocol_intro_wait;
|
||||||
|
status = omapi_connection_require (h -> outer, 8);
|
||||||
|
if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* Make up an initial transaction ID for this connection. */
|
||||||
|
p -> next_xid = random ();
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_send_message (omapi_object_t *po,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *mo,
|
||||||
|
omapi_object_t *omo)
|
||||||
|
{
|
||||||
|
omapi_protocol_object_t *p;
|
||||||
|
omapi_object_t *c;
|
||||||
|
omapi_message_object_t *m;
|
||||||
|
omapi_message_object_t *om;
|
||||||
|
isc_result_t status;
|
||||||
|
u_int32_t foo;
|
||||||
|
|
||||||
|
if (po -> type != omapi_type_protocol ||
|
||||||
|
!po -> outer || po -> outer -> type != omapi_type_connection ||
|
||||||
|
mo -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
if (omo && omo -> type != omapi_type_message)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
p = (omapi_protocol_object_t *)po;
|
||||||
|
c = (omapi_object_t *)(po -> outer);
|
||||||
|
m = (omapi_message_object_t *)mo;
|
||||||
|
om = (omapi_message_object_t *)omo;
|
||||||
|
|
||||||
|
/* XXX Write the authenticator length */
|
||||||
|
status = omapi_connection_put_uint32 (c, 0);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
/* XXX Write the ID of the authentication key we're using. */
|
||||||
|
status = omapi_connection_put_uint32 (c, 0);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the opcode. */
|
||||||
|
status = omapi_connection_put_uint32 (c, m -> op);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the handle. If we've been given an explicit handle, use
|
||||||
|
that. Otherwise, use the handle of the object we're sending.
|
||||||
|
The caller is responsible for arranging for one of these handles
|
||||||
|
to be set (or not). */
|
||||||
|
status = omapi_connection_put_uint32 (c, (m -> h
|
||||||
|
? m -> h
|
||||||
|
: m -> object -> handle));
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set and write the transaction ID. */
|
||||||
|
m -> id = p -> next_xid++;
|
||||||
|
status = omapi_connection_put_uint32 (c, m -> id);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the transaction ID of the message to which this is a
|
||||||
|
response, if there is such a message. */
|
||||||
|
status = omapi_connection_put_uint32 (c, om ? om -> id : 0);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now stuff out all the published name/value pairs associated
|
||||||
|
with the message. */
|
||||||
|
status = omapi_stuff_values (c, id, m -> object);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the zero-length name that terminates the list of name/value
|
||||||
|
pairs. */
|
||||||
|
status = omapi_connection_put_uint16 (c, 0);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX Write the authenticator... */
|
||||||
|
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_protocol_object_t *p;
|
||||||
|
omapi_object_t *c;
|
||||||
|
u_int16_t nlen;
|
||||||
|
u_int32_t vlen;
|
||||||
|
|
||||||
|
if (h -> type != omapi_type_protocol) {
|
||||||
|
/* XXX shouldn't happen. Put an assert here? */
|
||||||
|
return ISC_R_UNEXPECTED;
|
||||||
|
}
|
||||||
|
p = (omapi_protocol_object_t *)h;
|
||||||
|
|
||||||
|
/* Not a signal we recognize? */
|
||||||
|
if (strcmp (name, "ready")) {
|
||||||
|
if (p -> inner && p -> inner -> type -> signal_handler)
|
||||||
|
return (*(p -> inner -> type -> signal_handler)) (h,
|
||||||
|
name,
|
||||||
|
ap);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p -> outer || p -> outer -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
c = p -> outer;
|
||||||
|
|
||||||
|
/* We get here because we requested that we be woken up after
|
||||||
|
some number of bytes were read, and that number of bytes
|
||||||
|
has in fact been read. */
|
||||||
|
switch (p -> state) {
|
||||||
|
case omapi_protocol_intro_wait:
|
||||||
|
/* Get protocol version and header size in network
|
||||||
|
byte order. */
|
||||||
|
omapi_connection_get_uint32 (c, &p -> protocol_version);
|
||||||
|
omapi_connection_get_uint32 (c, &p -> header_size);
|
||||||
|
|
||||||
|
/* We currently only support the current protocol version. */
|
||||||
|
if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return ISC_R_VERSIONMISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p -> header_size < sizeof (omapi_protocol_header_t)) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return ISC_R_PROTOCOLERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_signal_in (h -> inner, "ready");
|
||||||
|
|
||||||
|
to_header_wait:
|
||||||
|
/* The next thing we're expecting is a message header. */
|
||||||
|
p -> state = omapi_protocol_header_wait;
|
||||||
|
|
||||||
|
/* Register a need for the number of bytes in a
|
||||||
|
header, and if we already have that many, process
|
||||||
|
them immediately. */
|
||||||
|
if ((omapi_connection_require
|
||||||
|
(c, p -> header_size)) != ISC_R_SUCCESS)
|
||||||
|
break;
|
||||||
|
/* If we already have the data, fall through. */
|
||||||
|
|
||||||
|
case omapi_protocol_header_wait:
|
||||||
|
status = omapi_message_new ((omapi_object_t **)&p -> message,
|
||||||
|
"omapi_protocol_signal_handler");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need a generic object to hang off of the
|
||||||
|
incoming message. */
|
||||||
|
status = omapi_generic_new (&p -> message -> object,
|
||||||
|
"omapi_protocol_signal_handler");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap in the header... */
|
||||||
|
omapi_connection_get_uint32 (c, &p -> message -> authid);
|
||||||
|
|
||||||
|
/* XXX bind the authenticator here! */
|
||||||
|
omapi_connection_get_uint32 (c, &p -> message -> authlen);
|
||||||
|
omapi_connection_get_uint32 (c, &p -> message -> op);
|
||||||
|
omapi_connection_get_uint32 (c, &p -> message -> handle);
|
||||||
|
omapi_connection_get_uint32 (c, &p -> message -> id);
|
||||||
|
omapi_connection_get_uint32 (c, &p -> message -> rid);
|
||||||
|
|
||||||
|
/* If there was any extra header data, skip over it. */
|
||||||
|
if (p -> header_size > sizeof (omapi_protocol_header_t)) {
|
||||||
|
omapi_connection_copyout
|
||||||
|
(0, c, (p -> header_size -
|
||||||
|
sizeof (omapi_protocol_header_t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX must compute partial signature across the
|
||||||
|
XXX preceding bytes. Also, if authenticator
|
||||||
|
specifies encryption as well as signing, we may
|
||||||
|
have to decrypt the data on the way in. */
|
||||||
|
|
||||||
|
need_name_length:
|
||||||
|
/* The next thing we're expecting is length of the
|
||||||
|
first name. */
|
||||||
|
p -> state = omapi_protocol_name_length_wait;
|
||||||
|
|
||||||
|
/* Wait for a 16-bit length. */
|
||||||
|
if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
|
||||||
|
break;
|
||||||
|
/* If it's already here, fall through. */
|
||||||
|
|
||||||
|
case omapi_protocol_name_length_wait:
|
||||||
|
omapi_connection_get_uint16 (c, &nlen);
|
||||||
|
/* A zero-length name means that we're done reading name+value
|
||||||
|
pairs. */
|
||||||
|
if (nlen == 0) {
|
||||||
|
/* If the authenticator length is zero, there's no
|
||||||
|
signature to read in, so go straight to processing
|
||||||
|
the message. */
|
||||||
|
if (p -> message -> authlen == 0)
|
||||||
|
goto message_done;
|
||||||
|
|
||||||
|
/* The next thing we're expecting is the
|
||||||
|
message signature. */
|
||||||
|
p -> state = omapi_protocol_signature_wait;
|
||||||
|
|
||||||
|
/* Wait for the number of bytes specified for
|
||||||
|
the authenticator. If we already have it,
|
||||||
|
go read it in. */
|
||||||
|
if (omapi_connection_require
|
||||||
|
(c, p -> message -> authlen) == ISC_R_SUCCESS)
|
||||||
|
goto signature_wait;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a buffer for the name. */
|
||||||
|
status = (omapi_data_string_new
|
||||||
|
(&p -> name, nlen, "omapi_protocol_signal_handler"));
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
}
|
||||||
|
if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
|
||||||
|
break;
|
||||||
|
/* If it's already here, fall through. */
|
||||||
|
|
||||||
|
case omapi_protocol_name_wait:
|
||||||
|
omapi_connection_copyout (p -> name -> value, c,
|
||||||
|
p -> name -> len);
|
||||||
|
/* Wait for a 32-bit length. */
|
||||||
|
if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
|
||||||
|
break;
|
||||||
|
/* If it's already here, fall through. */
|
||||||
|
|
||||||
|
case omapi_protocol_value_length_wait:
|
||||||
|
omapi_connection_get_uint32 (c, &vlen);
|
||||||
|
|
||||||
|
/* Zero-length values are allowed - if we get one, we
|
||||||
|
don't have to read any data for the value - just
|
||||||
|
get the next one, if there is a next one. */
|
||||||
|
if (!vlen)
|
||||||
|
goto insert_new_value;
|
||||||
|
|
||||||
|
status = (omapi_typed_data_new
|
||||||
|
(&p -> value, omapi_datatype_data, nlen,
|
||||||
|
"omapi_protocol_signal_handler"));
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
|
||||||
|
break;
|
||||||
|
/* If it's already here, fall through. */
|
||||||
|
|
||||||
|
case omapi_protocol_value_wait:
|
||||||
|
omapi_connection_copyout (p -> value -> u.buffer.value, c,
|
||||||
|
p -> value -> u.buffer.len);
|
||||||
|
|
||||||
|
insert_new_value:
|
||||||
|
status = (omapi_set_value
|
||||||
|
((omapi_object_t *)p -> message -> object,
|
||||||
|
p -> message -> id_object, p -> name, p -> value));
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
omapi_data_string_dereference
|
||||||
|
(&p -> name, "omapi_protocol_signal_handler");
|
||||||
|
omapi_typed_data_dereference (&p -> value,
|
||||||
|
"omapi_protocol_signal_handler");
|
||||||
|
goto need_name_length;
|
||||||
|
|
||||||
|
signature_wait:
|
||||||
|
case omapi_protocol_signature_wait:
|
||||||
|
status = omapi_typed_data_new (&p -> message -> authenticator,
|
||||||
|
omapi_datatype_data,
|
||||||
|
p -> message -> authlen);
|
||||||
|
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
}
|
||||||
|
omapi_connection_copyout
|
||||||
|
(p -> message -> authenticator -> u.buffer.value, c,
|
||||||
|
p -> message -> authlen);
|
||||||
|
/* XXX now do something to verify the signature. */
|
||||||
|
|
||||||
|
message_done:
|
||||||
|
/* XXX process the message. */
|
||||||
|
/* XXX unbind the authenticator. */
|
||||||
|
|
||||||
|
/* Now wait for the next message. */
|
||||||
|
goto to_header_wait;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* XXX should never get here. Assertion? */
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_protocol)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> set_value)
|
||||||
|
return (*(h -> inner -> type -> set_value))
|
||||||
|
(h -> inner, id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_protocol)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
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_protocol_destroy (omapi_object_t *h, char *name)
|
||||||
|
{
|
||||||
|
omapi_protocol_object_t *p;
|
||||||
|
if (h -> type != omapi_type_protocol)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
p = (omapi_protocol_object_t *)h;
|
||||||
|
if (p -> message)
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&p -> message,
|
||||||
|
name);
|
||||||
|
if (p -> authinfo)
|
||||||
|
return omapi_object_dereference (&p -> authinfo, name);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write all the published values associated with the object through the
|
||||||
|
specified connection. */
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (p -> type != omapi_type_protocol)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (p -> inner && p -> inner -> type -> stuff_values)
|
||||||
|
return (*(p -> inner -> type -> stuff_values)) (c, id,
|
||||||
|
p -> inner);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a listener for the omapi protocol. The handle stored points to
|
||||||
|
a listener object, not a protocol object. */
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_listen (omapi_object_t *h,
|
||||||
|
int port,
|
||||||
|
int max)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_protocol_listener_object_t *obj;
|
||||||
|
|
||||||
|
obj = (omapi_protocol_listener_object_t *)malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (obj, 0, sizeof *obj);
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_protocol_listener;
|
||||||
|
|
||||||
|
status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = omapi_object_reference (&obj -> inner, h,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_listen ((omapi_object_t *)obj, port, max);
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_listen");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal handler for protocol listener - if we get a connect signal,
|
||||||
|
create a new protocol connection, otherwise pass the signal down. */
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
|
||||||
|
char *name, va_list ap)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
omapi_object_t *c;
|
||||||
|
omapi_protocol_object_t *obj;
|
||||||
|
omapi_protocol_listener_object_t *p;
|
||||||
|
|
||||||
|
if (!o || o -> type != omapi_type_protocol_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
p = (omapi_protocol_listener_object_t *)o;
|
||||||
|
|
||||||
|
/* Not a signal we recognize? */
|
||||||
|
if (strcmp (name, "connect")) {
|
||||||
|
if (p -> inner && p -> inner -> type -> signal_handler)
|
||||||
|
return (*(p -> inner -> type -> signal_handler))
|
||||||
|
(p -> inner, name, ap);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = va_arg (ap, omapi_object_t *);
|
||||||
|
if (!c || c -> type != omapi_type_connection)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
obj = (omapi_protocol_object_t *)malloc (sizeof *obj);
|
||||||
|
if (!obj)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (obj, 0, sizeof *obj);
|
||||||
|
obj -> refcnt = 1;
|
||||||
|
obj -> type = omapi_type_protocol;
|
||||||
|
|
||||||
|
status = omapi_object_reference (&obj -> outer, c,
|
||||||
|
"omapi_protocol_accept");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
lose:
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_accept");
|
||||||
|
omapi_disconnect (c, 1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = omapi_object_reference (&c -> inner, (omapi_object_t *)obj,
|
||||||
|
"omapi_protocol_accept");
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
goto lose;
|
||||||
|
|
||||||
|
/* Send the introductory message. */
|
||||||
|
status = omapi_protocol_send_intro ((omapi_object_t *)obj,
|
||||||
|
OMAPI_PROTOCOL_VERSION,
|
||||||
|
sizeof (omapi_protocol_header_t));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
goto lose;
|
||||||
|
|
||||||
|
omapi_object_dereference ((omapi_object_t **)&obj,
|
||||||
|
"omapi_protocol_accept");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_protocol_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (h -> inner && h -> inner -> type -> set_value)
|
||||||
|
return (*(h -> inner -> type -> set_value))
|
||||||
|
(h -> inner, id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_protocol_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
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_protocol_listener_destroy (omapi_object_t *h, char *name)
|
||||||
|
{
|
||||||
|
if (h -> type != omapi_type_protocol_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write all the published values associated with the object through the
|
||||||
|
specified connection. */
|
||||||
|
|
||||||
|
isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (p -> type != omapi_type_protocol_listener)
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
|
||||||
|
if (p -> inner && p -> inner -> type -> stuff_values)
|
||||||
|
return (*(p -> inner -> type -> stuff_values)) (c, id,
|
||||||
|
p -> inner);
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
76
omapip/result.c
Normal file
76
omapip/result.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* result.c
|
||||||
|
|
||||||
|
Cheap knock-off of libisc result table code. This is just a place-holder
|
||||||
|
until the actual libisc merge. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
static char *text[ISC_R_NRESULTS] = {
|
||||||
|
"success", /* 0 */
|
||||||
|
"out of memory", /* 1 */
|
||||||
|
"timed out", /* 2 */
|
||||||
|
"no available threads", /* 3 */
|
||||||
|
"address not available", /* 4 */
|
||||||
|
"address in use", /* 5 */
|
||||||
|
"permission denied", /* 6 */
|
||||||
|
"no pending connections", /* 7 */
|
||||||
|
"network unreachable", /* 8 */
|
||||||
|
"host unreachable", /* 9 */
|
||||||
|
"network down", /* 10 */
|
||||||
|
"host down", /* 11 */
|
||||||
|
"connection refused", /* 12 */
|
||||||
|
"not enough free resources", /* 13 */
|
||||||
|
"end of file", /* 14 */
|
||||||
|
"socket already bound", /* 15 */
|
||||||
|
"task is done", /* 16 */
|
||||||
|
"lock busy", /* 17 */
|
||||||
|
"already exists", /* 18 */
|
||||||
|
"ran out of space", /* 19 */
|
||||||
|
"operation canceled", /* 20 */
|
||||||
|
"sending events is not allowed", /* 21 */
|
||||||
|
"shutting down", /* 22 */
|
||||||
|
"not found", /* 23 */
|
||||||
|
"unexpected end of input", /* 24 */
|
||||||
|
"failure", /* 25 */
|
||||||
|
"I/O error", /* 26 */
|
||||||
|
"not implemented", /* 27 */
|
||||||
|
"unbalanced parentheses", /* 28 */
|
||||||
|
"no more", /* 29 */
|
||||||
|
"invalid file", /* 30 */
|
||||||
|
"bad base64 encoding", /* 31 */
|
||||||
|
"unexpected token", /* 32 */
|
||||||
|
"quota reached", /* 33 */
|
||||||
|
"unexpected error", /* 34 */
|
||||||
|
"already running", /* 35 */
|
||||||
|
"host unknown", /* 36 */
|
||||||
|
"protocol version mismatch", /* 37 */
|
||||||
|
"protocol error", /* 38 */
|
||||||
|
"invalid argument", /* 39 */
|
||||||
|
"not connected", /* 40 */
|
||||||
|
"data not yet available", /* 41 */
|
||||||
|
};
|
||||||
|
|
||||||
|
char *isc_result_totext (isc_result_t result)
|
||||||
|
{
|
||||||
|
if (result >= ISC_R_SUCCESS && result < ISC_R_NRESULTS)
|
||||||
|
return text [result];
|
||||||
|
return "unknown error.";
|
||||||
|
}
|
380
omapip/support.c
Normal file
380
omapip/support.c
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
/* support.c
|
||||||
|
|
||||||
|
Subroutines providing general support for objects. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
omapi_object_type_t *omapi_type_connection;
|
||||||
|
omapi_object_type_t *omapi_type_listener;
|
||||||
|
omapi_object_type_t *omapi_type_io_object;
|
||||||
|
omapi_object_type_t *omapi_type_datagram;
|
||||||
|
omapi_object_type_t *omapi_type_generic;
|
||||||
|
omapi_object_type_t *omapi_type_protocol;
|
||||||
|
omapi_object_type_t *omapi_type_protocol_listener;
|
||||||
|
omapi_object_type_t *omapi_type_waiter;
|
||||||
|
omapi_object_type_t *omapi_type_remote;
|
||||||
|
omapi_object_type_t *omapi_type_message;
|
||||||
|
|
||||||
|
omapi_object_type_t *omapi_object_types;
|
||||||
|
int omapi_object_type_count;
|
||||||
|
static int ot_max;
|
||||||
|
|
||||||
|
isc_result_t omapi_init (void)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
/* Register all the standard object types... */
|
||||||
|
status = omapi_object_type_register (&omapi_type_connection,
|
||||||
|
"connection",
|
||||||
|
omapi_connection_set_value,
|
||||||
|
omapi_connection_get_value,
|
||||||
|
omapi_connection_destroy,
|
||||||
|
omapi_connection_signal_handler,
|
||||||
|
omapi_connection_stuff_values);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_listener,
|
||||||
|
"listener",
|
||||||
|
omapi_listener_set_value,
|
||||||
|
omapi_listener_get_value,
|
||||||
|
omapi_listener_destroy,
|
||||||
|
omapi_listener_signal_handler,
|
||||||
|
omapi_listener_stuff_values);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_io_object,
|
||||||
|
"io",
|
||||||
|
omapi_io_set_value,
|
||||||
|
omapi_io_get_value,
|
||||||
|
omapi_io_destroy,
|
||||||
|
omapi_io_signal_handler,
|
||||||
|
omapi_io_stuff_values);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_generic,
|
||||||
|
"generic",
|
||||||
|
omapi_generic_set_value,
|
||||||
|
omapi_generic_get_value,
|
||||||
|
omapi_generic_destroy,
|
||||||
|
omapi_generic_signal_handler,
|
||||||
|
omapi_generic_stuff_values);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_protocol,
|
||||||
|
"protocol",
|
||||||
|
omapi_protocol_set_value,
|
||||||
|
omapi_protocol_get_value,
|
||||||
|
omapi_protocol_destroy,
|
||||||
|
omapi_protocol_signal_handler,
|
||||||
|
omapi_protocol_stuff_values);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_protocol_listener,
|
||||||
|
"protocol-listener",
|
||||||
|
omapi_protocol_listener_set_value,
|
||||||
|
omapi_protocol_listener_get_value,
|
||||||
|
omapi_protocol_listener_destroy,
|
||||||
|
omapi_protocol_listener_signal,
|
||||||
|
omapi_protocol_listener_stuff);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_message,
|
||||||
|
"message",
|
||||||
|
omapi_message_set_value,
|
||||||
|
omapi_message_get_value,
|
||||||
|
omapi_message_destroy,
|
||||||
|
omapi_message_signal_handler,
|
||||||
|
omapi_message_stuff_values);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_object_type_register (&omapi_type_waiter,
|
||||||
|
"waiter",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
omapi_waiter_signal_handler, 0);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* This seems silly, but leave it. */
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_object_type_register (omapi_object_type_t **type,
|
||||||
|
char *name,
|
||||||
|
isc_result_t (*set_value)
|
||||||
|
(omapi_object_t *,
|
||||||
|
omapi_object_t *,
|
||||||
|
omapi_data_string_t *,
|
||||||
|
omapi_typed_data_t *),
|
||||||
|
isc_result_t (*get_value)
|
||||||
|
(omapi_object_t *,
|
||||||
|
omapi_object_t *,
|
||||||
|
omapi_data_string_t *,
|
||||||
|
omapi_value_t **),
|
||||||
|
isc_result_t (*destroy)
|
||||||
|
(omapi_object_t *, char *),
|
||||||
|
isc_result_t (*signal_handler)
|
||||||
|
(omapi_object_t *,
|
||||||
|
char *, va_list),
|
||||||
|
isc_result_t (*stuff_values)
|
||||||
|
(omapi_object_t *,
|
||||||
|
omapi_object_t *,
|
||||||
|
omapi_object_t *))
|
||||||
|
{
|
||||||
|
omapi_object_type_t *t;
|
||||||
|
|
||||||
|
if (!omapi_object_types) {
|
||||||
|
ot_max = 10;
|
||||||
|
omapi_object_types = malloc (ot_max *
|
||||||
|
sizeof *omapi_object_types);
|
||||||
|
if (!omapi_object_types)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memset (omapi_object_types, 0, (ot_max *
|
||||||
|
sizeof *omapi_object_types));
|
||||||
|
} else if (omapi_object_type_count == ot_max) {
|
||||||
|
t = malloc (2 *ot_max * sizeof *t);
|
||||||
|
if (!t)
|
||||||
|
return ISC_R_NOMEMORY;
|
||||||
|
memcpy (t, omapi_object_types, ot_max *sizeof *t);
|
||||||
|
memset (t + ot_max, 0, ot_max * sizeof *t);
|
||||||
|
free (omapi_object_types);
|
||||||
|
omapi_object_types = t;
|
||||||
|
}
|
||||||
|
omapi_object_types [omapi_object_type_count].name = name;
|
||||||
|
omapi_object_types [omapi_object_type_count].set_value = set_value;
|
||||||
|
omapi_object_types [omapi_object_type_count].get_value = get_value;
|
||||||
|
omapi_object_types [omapi_object_type_count].destroy = destroy;
|
||||||
|
omapi_object_types [omapi_object_type_count].signal_handler =
|
||||||
|
signal_handler;
|
||||||
|
omapi_object_types [omapi_object_type_count].stuff_values =
|
||||||
|
stuff_values;
|
||||||
|
if (type)
|
||||||
|
*type = &omapi_object_types [omapi_object_type_count];
|
||||||
|
omapi_object_type_count++;
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_signal (omapi_object_t *handle, char *name, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
omapi_object_t *outer;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
va_start (ap, name);
|
||||||
|
for (outer = handle; outer -> outer; outer = outer -> outer)
|
||||||
|
;
|
||||||
|
if (outer -> type -> signal_handler)
|
||||||
|
status = (*(outer -> type -> signal_handler)) (outer,
|
||||||
|
name, ap);
|
||||||
|
else
|
||||||
|
status = ISC_R_NOTFOUND;
|
||||||
|
va_end (ap);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_signal_in (omapi_object_t *handle, char *name, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
omapi_object_t *outer;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
va_start (ap, name);
|
||||||
|
|
||||||
|
if (handle -> type -> signal_handler)
|
||||||
|
status = (*(handle -> type -> signal_handler)) (handle,
|
||||||
|
name, ap);
|
||||||
|
else
|
||||||
|
status = ISC_R_NOTFOUND;
|
||||||
|
va_end (ap);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_set_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value)
|
||||||
|
{
|
||||||
|
omapi_object_t *outer;
|
||||||
|
|
||||||
|
for (outer = h; outer -> outer; outer = outer -> outer)
|
||||||
|
;
|
||||||
|
if (outer -> type -> set_value)
|
||||||
|
return (*(outer -> type -> set_value)) (outer,
|
||||||
|
id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_get_value (omapi_object_t *h,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
omapi_value_t **value)
|
||||||
|
{
|
||||||
|
omapi_object_t *outer;
|
||||||
|
|
||||||
|
for (outer = h; outer -> outer; outer = outer -> outer)
|
||||||
|
;
|
||||||
|
if (outer -> type -> get_value)
|
||||||
|
return (*(outer -> type -> get_value)) (outer,
|
||||||
|
id, name, value);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_stuff_values (omapi_object_t *c,
|
||||||
|
omapi_object_t *id,
|
||||||
|
omapi_object_t *o)
|
||||||
|
{
|
||||||
|
omapi_object_t *outer;
|
||||||
|
|
||||||
|
for (outer = o; outer -> outer; outer = outer -> outer)
|
||||||
|
;
|
||||||
|
if (outer -> type -> stuff_values)
|
||||||
|
return (*(outer -> type -> stuff_values)) (c, id, outer);
|
||||||
|
return ISC_R_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int omapi_data_string_cmp (omapi_data_string_t *s1, omapi_data_string_t *s2)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (s1 -> len > s2 -> len)
|
||||||
|
len = s2 -> len;
|
||||||
|
else
|
||||||
|
len = s1 -> len;
|
||||||
|
rv = memcmp (s1 -> value, s2 -> value, len);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
if (s1 -> len > s2 -> len)
|
||||||
|
return 1;
|
||||||
|
else if (s1 -> len < s2 -> len)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int omapi_ds_strcmp (omapi_data_string_t *s1, char *s2)
|
||||||
|
{
|
||||||
|
int len, slen;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
slen = strlen (s2);
|
||||||
|
if (slen > s1 -> len)
|
||||||
|
len = s1 -> len;
|
||||||
|
else
|
||||||
|
len = slen;
|
||||||
|
rv = memcmp (s1 -> value, s2, len);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
if (s1 -> len > slen)
|
||||||
|
return 1;
|
||||||
|
else if (s1 -> len < slen)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_make_value (omapi_value_t **vp, omapi_data_string_t *name,
|
||||||
|
omapi_typed_data_t *value, char *caller)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
status = omapi_value_new (vp, caller);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_data_string_reference (&(*vp) -> name, name, caller);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_value_dereference (vp, caller);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
status = omapi_typed_data_reference (&(*vp) -> value,
|
||||||
|
value, caller);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_value_dereference (vp, caller);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_make_const_value (omapi_value_t **vp,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
u_int8_t *value, int len, char *caller)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
status = omapi_value_new (vp, caller);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_data_string_reference (&(*vp) -> name, name, caller);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_value_dereference (vp, caller);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
status = omapi_typed_data_new (&(*vp) -> value,
|
||||||
|
omapi_datatype_data, len);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_value_dereference (vp, caller);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
memcpy ((*vp) -> value -> u.buffer.value, value, len);
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t omapi_make_int_value (omapi_value_t **vp,
|
||||||
|
omapi_data_string_t *name,
|
||||||
|
int value, char *caller)
|
||||||
|
{
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
status = omapi_value_new (vp, caller);
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = omapi_data_string_reference (&(*vp) -> name, name, caller);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_value_dereference (vp, caller);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
status = omapi_typed_data_new (&(*vp) -> value,
|
||||||
|
omapi_datatype_int);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
omapi_value_dereference (vp, caller);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
(*vp) -> value -> u.integer = value;
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
80
omapip/test.c
Normal file
80
omapip/test.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* test.c
|
||||||
|
|
||||||
|
Test code for omapip... */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996-1999 Internet Software Consortium.
|
||||||
|
* Use is subject to license terms which appear in the file named
|
||||||
|
* ISC-LICENSE that should have accompanied this file when you
|
||||||
|
* received it. If a file named ISC-LICENSE did not accompany this
|
||||||
|
* file, or you are not sure the one you have is correct, you may
|
||||||
|
* obtain an applicable copy of the license at:
|
||||||
|
*
|
||||||
|
* http://www.isc.org/isc-license-1.0.html.
|
||||||
|
*
|
||||||
|
* This file is part of the ISC DHCP distribution. The documentation
|
||||||
|
* associated with this file is listed in the file DOCUMENTATION,
|
||||||
|
* included in the top-level directory of this release.
|
||||||
|
*
|
||||||
|
* Support and other services are available for ISC products - see
|
||||||
|
* http://www.isc.org for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <omapip/omapip.h>
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
omapi_object_t listener = (omapi_object_t)0;
|
||||||
|
omapi_object_t connection = (omapi_object_t)0;
|
||||||
|
isc_result_t status;
|
||||||
|
|
||||||
|
omapi_init ();
|
||||||
|
|
||||||
|
if (argc > 1 && !strcmp (argv [1], "listen")) {
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf (stderr, "Usage: test listen port\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
status = omapi_generic_new (&listener, "main");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
fprintf (stderr, "omapi_generic_new: %s\n",
|
||||||
|
isc_result_totext (status));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
status = omapi_protocol_listen (listener,
|
||||||
|
atoi (argv [2]), 1);
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
fprintf (stderr, "omapi_listen: %s\n",
|
||||||
|
isc_result_totext (status));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
omapi_dispatch (0);
|
||||||
|
} else if (argc > 1 && !strcmp (argv [1], "connect")) {
|
||||||
|
if (argc < 4) {
|
||||||
|
fprintf (stderr, "Usage: test listen address port\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
status = omapi_generic_new (&connection, "main");
|
||||||
|
if (status != ISC_R_SUCCESS) {
|
||||||
|
fprintf (stderr, "omapi_generic_new: %s\n",
|
||||||
|
isc_result_totext (status));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
status = omapi_protocol_connect (connection,
|
||||||
|
argv [2], atoi (argv [3]), 0);
|
||||||
|
fprintf (stderr, "connect: %s\n", isc_result_totext (status));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
exit (1);
|
||||||
|
status = omapi_wait_for_completion (connection, 0);
|
||||||
|
fprintf (stderr, "completion: %s\n",
|
||||||
|
isc_result_totext (status));
|
||||||
|
if (status != ISC_R_SUCCESS)
|
||||||
|
exit (1);
|
||||||
|
/* ... */
|
||||||
|
} else {
|
||||||
|
fprintf (stderr, "Usage: test [listen | connect] ...\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user