2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-30 05:47:45 +00:00

Omapi library, initial checkin

This commit is contained in:
Ted Lemon 1999-09-02 00:32:56 +00:00
parent a40cbc2b96
commit 61b844bfd7
14 changed files with 3886 additions and 0 deletions

79
omapip/Makefile.dist Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

639
omapip/protocol.c Normal file
View 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
View 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
View 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
View 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;
}