initial copy from the DHCP source pool

This commit is contained in:
David Lawrence
1999-10-27 22:24:32 +00:00
parent a61063ca9c
commit f3ff03fc48
13 changed files with 4902 additions and 0 deletions

85
bin/tests/omapi_test.c Normal file
View File

@@ -0,0 +1,85 @@
/* 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <isc/result.h>
#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;
}

451
lib/omapi/alloc.c Normal file
View File

@@ -0,0 +1,451 @@
/* 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_p.h>
isc_result_t omapi_object_reference (omapi_object_t **r,
omapi_object_t *h,
const 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,
const 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,
const 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);
(*h) -> head = sizeof ((*h) -> buf) - 1;
return status;
}
isc_result_t omapi_buffer_reference (omapi_buffer_t **r,
omapi_buffer_t *h,
const 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,
const 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;
unsigned len;
unsigned val;
int intval;
char *s;
isc_result_t status;
va_start (l, type);
switch (type) {
case omapi_datatype_int:
len = OMAPI_TYPED_DATA_INT_LEN;
intval = va_arg (l, int);
break;
case omapi_datatype_string:
s = va_arg (l, char *);
val = strlen (s);
len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
break;
case omapi_datatype_data:
val = va_arg (l, unsigned);
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 = intval;
break;
case omapi_datatype_string:
memcpy (new -> u.buffer.value, s, val);
new -> u.buffer.len = val;
break;
case omapi_datatype_data:
new -> u.buffer.len = val;
break;
case omapi_datatype_object:
status = omapi_object_reference (&new -> u.object,
va_arg (l, omapi_object_t *),
"omapi_datatype_new");
if (status != ISC_R_SUCCESS) {
free (new);
return status;
}
break;
}
new -> type = type;
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,
const 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,
const 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,
unsigned len, const 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,
const 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,
const 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,
const 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,
const 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,
const 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;
}

499
lib/omapi/buffer.c Normal file
View File

@@ -0,0 +1,499 @@
/* 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_p.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;
unsigned read_len;
int read_status;
omapi_connection_object_t *c;
unsigned 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_FREE (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_FREE (buffer);
while (bytes_to_read) {
if (buffer -> tail > buffer -> head)
read_len = sizeof (buffer -> buf) - buffer -> tail;
else
read_len = buffer -> head - buffer -> tail;
read_status = read (c -> socket,
&buffer -> buf [buffer -> tail], read_len);
if (read_status < 0) {
if (errno == EWOULDBLOCK)
break;
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 we got a zero-length read, as opposed to EWOULDBLOCK,
the remote end closed the connection. */
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,
const unsigned char *bufp,
unsigned len)
{
omapi_buffer_t *buffer;
isc_result_t status;
int bytes_copied = 0;
unsigned 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_FREE (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 = sizeof (buffer -> buf) - buffer -> tail;
else
copy_len = buffer -> head - buffer -> tail;
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. */
isc_result_t omapi_connection_copyout (unsigned char *buf,
omapi_object_t *h,
unsigned size)
{
unsigned bytes_remaining;
unsigned bytes_this_copy;
unsigned first_byte;
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 (BYTES_IN_BUFFER (buffer)) {
if (buffer -> head == (sizeof buffer -> buf) - 1)
first_byte = 0;
else
first_byte = buffer -> head + 1;
if (first_byte > buffer -> tail) {
bytes_this_copy = (sizeof buffer -> buf -
first_byte);
} else {
bytes_this_copy =
buffer -> tail - first_byte;
}
if (bytes_this_copy > bytes_remaining)
bytes_this_copy = bytes_remaining;
if (bufp) {
memcpy (bufp, &buffer -> buf [first_byte],
bytes_this_copy);
bufp += bytes_this_copy;
}
bytes_remaining -= bytes_this_copy;
buffer -> head = first_byte + bytes_this_copy - 1;
c -> in_bytes -= bytes_this_copy;
}
if (!BYTES_IN_BUFFER (buffer))
buffer = buffer -> next;
}
/* Get rid of any input buffers that we emptied. */
buffer = (omapi_buffer_t *)0;
while (c -> inbufs &&
!BYTES_IN_BUFFER (c -> inbufs)) {
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");
if (buffer) {
omapi_buffer_reference
(&c -> inbufs, buffer,
"omapi_private_buffer_copyout");
omapi_buffer_dereference
(&buffer, "omapi_private_buffer_copyout");
}
}
return ISC_R_SUCCESS;
}
isc_result_t omapi_connection_writer (omapi_object_t *h)
{
unsigned bytes_this_write;
unsigned bytes_written;
unsigned first_byte;
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 (BYTES_IN_BUFFER (buffer)) {
if (buffer -> head == (sizeof buffer -> buf) - 1)
first_byte = 0;
else
first_byte = buffer -> head + 1;
if (first_byte > buffer -> tail) {
bytes_this_write = (sizeof buffer -> buf -
first_byte);
} else {
bytes_this_write =
buffer -> tail - first_byte;
}
bytes_written = write (c -> socket,
&buffer -> buf [first_byte],
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 = first_byte + bytes_written - 1;
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 (!BYTES_IN_BUFFER (buffer))
buffer = buffer -> next;
}
/* Get rid of any output buffers we emptied. */
buffer = (omapi_buffer_t *)0;
while (c -> outbufs &&
!BYTES_IN_BUFFER (c -> outbufs)) {
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_int32_t value)
{
u_int16_t inbuf;
isc_result_t status;
inbuf = htons (value);
return omapi_connection_copyin (c, (unsigned char *)&inbuf,
sizeof inbuf);
}
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, ((u_int32_t)
(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;
if (data -> u.buffer.len)
return omapi_connection_copyin
(c, data -> u.buffer.value,
data -> u.buffer.len);
return ISC_R_SUCCESS;
case omapi_datatype_object:
if (data -> u.object) {
status = omapi_object_handle (&handle,
data -> u.object);
if (status != ISC_R_SUCCESS)
return status;
} else
handle = 0;
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;
}
isc_result_t omapi_connection_put_name (omapi_object_t *c, const char *name)
{
isc_result_t status;
unsigned len = strlen (name);
status = omapi_connection_put_uint16 (c, len);
if (status != ISC_R_SUCCESS)
return status;
return omapi_connection_copyin (c, (const unsigned char *)name, len);
}
isc_result_t omapi_connection_put_string (omapi_object_t *c,
const char *string)
{
isc_result_t status;
unsigned len;
if (string)
len = strlen (string);
else
len = 0;
status = omapi_connection_put_uint32 (c, len);
if (status != ISC_R_SUCCESS)
return status;
if (len)
return omapi_connection_copyin
(c, (const unsigned char *)string, len);
return ISC_R_SUCCESS;
}
isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h)
{
isc_result_t status;
omapi_handle_t handle;
if (h) {
status = omapi_object_handle (&handle, h);
if (status != ISC_R_SUCCESS)
return status;
} else
handle = 0; /* The null handle. */
status = omapi_connection_put_uint32 (c, sizeof handle);
if (status != ISC_R_SUCCESS)
return status;
return omapi_connection_put_uint32 (c, handle);
}

337
lib/omapi/connection.c Normal file
View File

@@ -0,0 +1,337 @@
/* 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_p.h>
isc_result_t omapi_connect (omapi_object_t *c,
const char *server_name,
int port)
{
struct hostent *he;
int hix;
isc_result_t status;
omapi_connection_object_t *obj;
int flag;
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;
#if defined (HAVE_SA_LEN)
obj -> remote_addr.sin_len =
sizeof (struct sockaddr_in);
#endif
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;
}
/* Set the SO_REUSEADDR flag (this should not fail). */
flag = 1;
if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof flag) < 0) {
omapi_object_dereference ((omapi_object_t **)&obj,
"omapi_connect");
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, unsigned 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;
c = (omapi_connection_object_t *)h;
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, const 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,
const 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;
}

402
lib/omapi/dispatch.c Normal file
View File

@@ -0,0 +1,402 @@
/* 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_p.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 ((omapi_object_t *)waiter, t);
if (status != ISC_R_SUCCESS)
return status;
} while (!waiter || !waiter -> ready);
if (waiter -> outer) {
if (waiter -> outer -> inner) {
omapi_object_dereference (&waiter -> outer -> inner,
"omapi_wait_for_completion");
if (waiter -> inner)
omapi_object_reference
(&waiter -> outer -> inner,
waiter -> inner,
"omapi_wait_for_completion");
}
omapi_object_dereference (&waiter -> outer,
"omapi_wait_for_completion");
}
if (waiter -> inner)
omapi_object_dereference (&waiter -> inner,
"omapi_wait_for_completion");
omapi_object_dereference ((omapi_object_t **)&waiter,
"omapi_wait_for_completion");
return ISC_R_SUCCESS;
}
isc_result_t omapi_one_dispatch (omapi_object_t *wo,
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;
omapi_waiter_object_t *waiter;
if (!wo || wo -> type != omapi_type_waiter)
waiter = (omapi_waiter_object_t *)0;
else
waiter = (omapi_waiter_object_t *)wo;
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, const 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,
const 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,
const 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;
}

251
lib/omapi/generic.c Normal file
View File

@@ -0,0 +1,251 @@
/* 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_p.h>
isc_result_t omapi_generic_new (omapi_object_t **gen, const 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;
g -> va_max = vm_new;
}
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, const 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,
const 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_copyin
(c, src -> values [i] -> name -> value,
src -> values [i] -> name -> len));
if (status != ISC_R_SUCCESS)
return status;
status = (omapi_connection_write_typed_data
(c, src -> values [i] -> value));
if (status != ISC_R_SUCCESS)
return status;
}
}
if (g -> inner && g -> inner -> type -> stuff_values)
return (*(g -> inner -> type -> stuff_values)) (c, id,
g -> inner);
return ISC_R_SUCCESS;
}

283
lib/omapi/handle.c Normal file
View File

@@ -0,0 +1,283 @@
/* 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_p.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 (new, 0, sizeof *new);
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);
}
/* For looking up objects based on handles that have been sent on the wire. */
isc_result_t omapi_handle_td_lookup (omapi_object_t **obj,
omapi_typed_data_t *handle)
{
isc_result_t status;
omapi_handle_t h;
if (handle -> type == omapi_datatype_int)
h = handle -> u.integer;
else if (handle -> type == omapi_datatype_data &&
handle -> u.buffer.len == sizeof h) {
memcpy (&h, handle -> u.buffer.value, sizeof h);
h = ntohl (h);
} else
return ISC_R_INVALIDARG;
return omapi_handle_lookup (obj, h);
}

254
lib/omapi/listener.c Normal file
View File

@@ -0,0 +1,254 @@
/* 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_p.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;
memset (obj, 0, sizeof *obj);
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;
}
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_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 ISC_R_INVALIDARG;
listener = (omapi_listener_object_t *)h;
/* Get the handle. */
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;
/* Accept the connection. */
len = sizeof obj -> remote_addr;
obj -> socket =
accept (listener -> socket,
((struct sockaddr *)
&(obj -> remote_addr)), &len);
if (obj -> socket < 0) {
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, const 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,
const 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;
}

675
lib/omapi/message.c Normal file
View File

@@ -0,0 +1,675 @@
/* 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_p.h>
omapi_message_object_t *omapi_registered_messages;
isc_result_t omapi_message_new (omapi_object_t **o, const char *name)
{
omapi_message_object_t *m;
omapi_object_t *g;
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;
g = (omapi_object_t *)0;
status = omapi_generic_new (&g, name);
if (status != ISC_R_SUCCESS) {
free (m);
return status;
}
status = omapi_object_reference (&m -> inner, g, name);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&m, name);
omapi_object_dereference (&g, name);
return status;
}
status = omapi_object_reference (&g -> outer,
(omapi_object_t *)m, name);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference ((omapi_object_t **)&m, name);
omapi_object_dereference (&g, name);
return status;
}
status = omapi_object_reference (o, (omapi_object_t *)m, name);
omapi_object_dereference ((omapi_object_t **)&m, name);
omapi_object_dereference (&g, name);
if (status != ISC_R_SUCCESS)
return status;
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;
} else if (!omapi_ds_strcmp (name, "object")) {
if (value -> type != omapi_datatype_object)
return ISC_R_INVALIDARG;
if (m -> object)
omapi_object_dereference
(&m -> object,
"omapi_message_set_value");
omapi_object_reference (&m -> object,
value -> u.object,
"omapi_message_set_value");
return ISC_R_SUCCESS;
} else if (!omapi_ds_strcmp (name, "notify-object")) {
if (value -> type != omapi_datatype_object)
return ISC_R_INVALIDARG;
if (m -> notify_object)
omapi_object_dereference
(&m -> notify_object,
"omapi_message_set_value");
omapi_object_reference (&m -> notify_object,
value -> u.object,
"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;
return ISC_R_SUCCESS;
/* 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;
return ISC_R_SUCCESS;
/* 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;
return ISC_R_SUCCESS;
/* 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;
return ISC_R_SUCCESS;
/* 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;
return ISC_R_SUCCESS;
}
/* 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, (int)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, (int)m -> authid,
"omapi_message_get_value");
} else if (!omapi_ds_strcmp (name, "op")) {
return omapi_make_int_value (value, name, (int)m -> op,
"omapi_message_get_value");
} else if (!omapi_ds_strcmp (name, "handle")) {
return omapi_make_int_value (value, name, (int)m -> handle,
"omapi_message_get_value");
} else if (!omapi_ds_strcmp (name, "id")) {
return omapi_make_int_value (value, name, (int)m -> id,
"omapi_message_get_value");
} else if (!omapi_ds_strcmp (name, "rid")) {
return omapi_make_int_value (value, name, (int)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, const 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,
const char *name, va_list ap)
{
omapi_message_object_t *m;
if (h -> type != omapi_type_message)
return ISC_R_INVALIDARG;
m = (omapi_message_object_t *)h;
if (!strcmp (name, "status") &&
(m -> object || m -> notify_object)) {
if (m -> object)
return ((m -> object -> type -> signal_handler))
(m -> object, name, ap);
else
return ((m -> notify_object -> type -> signal_handler))
(m -> notify_object, name, ap);
}
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;
}
isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
{
omapi_message_object_t *message, *m;
omapi_object_t *object = (omapi_object_t *)0;
omapi_value_t *tv = (omapi_value_t *)0;
unsigned long create, update, exclusive;
unsigned long wsi;
isc_result_t status, waitstatus;
omapi_object_type_t *type;
if (mo -> type != omapi_type_message)
return ISC_R_INVALIDARG;
message = (omapi_message_object_t *)mo;
if (message -> rid) {
for (m = omapi_registered_messages; m; m = m -> next)
if (m -> id == message -> rid)
break;
/* If we don't have a real message corresponding to
the message ID to which this message claims it is a
response, something's fishy. */
if (!m)
return ISC_R_NOTFOUND;
} else
m = (omapi_message_object_t *)0;
switch (message -> op) {
case OMAPI_OP_OPEN:
if (m) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0, ISC_R_INVALIDARG,
message -> id, "OPEN can't be a response");
}
/* Get the type of the requested object, if one was
specified. */
status = omapi_get_value_str (mo, (omapi_object_t *)0,
"type", &tv);
if (status == ISC_R_SUCCESS &&
(tv -> value -> type == omapi_datatype_data ||
tv -> value -> type == omapi_datatype_string)) {
for (type = omapi_object_types;
type; type = type -> next)
if (!omapi_td_strcmp (tv -> value,
type -> name))
break;
} else
type = (omapi_object_type_t *)0;
if (tv)
omapi_value_dereference (&tv,
"omapi_message_process");
/* Get the create flag. */
status = omapi_get_value_str (mo,
(omapi_object_t *)0,
"create", &tv);
if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&create, tv -> value);
omapi_value_dereference (&tv,
"omapi_message_process");
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"invalid create flag value");
}
} else
create = 0;
/* Get the update flag. */
status = omapi_get_value_str (mo,
(omapi_object_t *)0,
"update", &tv);
if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&update, tv -> value);
omapi_value_dereference (&tv,
"omapi_message_process");
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"invalid update flag value");
}
} else
update = 0;
/* Get the exclusive flag. */
status = omapi_get_value_str (mo,
(omapi_object_t *)0,
"exclusive", &tv);
if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&exclusive, tv -> value);
omapi_value_dereference (&tv,
"omapi_message_process");
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"invalid exclusive flag value");
}
} else
exclusive = 0;
/* If we weren't given a type, look the object up with
the handle. */
if (!type) {
if (create) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
ISC_R_INVALIDARG, message -> id,
"type required on create");
}
goto refresh;
}
/* If the type doesn't provide a lookup method, we can't
look up the object. */
if (!type -> lookup) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
ISC_R_NOTIMPLEMENTED, message -> id,
"unsearchable object type");
}
if (!message -> object) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
ISC_R_NOTFOUND, message -> id,
"no lookup key specified");
}
status = (*(type -> lookup)) (&object, (omapi_object_t *)0,
message -> object);
if (status != ISC_R_SUCCESS &&
status != ISC_R_NOTFOUND &&
status != ISC_R_NOKEYS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"object lookup failed");
}
/* If we didn't find the object and we aren't supposed to
create it, return an error. */
if (status == ISC_R_NOTFOUND && !create) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
ISC_R_NOTFOUND, message -> id,
"no object matches specification");
}
/* If we found an object, we're supposed to be creating an
object, and we're not supposed to have found an object,
return an error. */
if (status == ISC_R_SUCCESS && create && exclusive) {
omapi_object_dereference
(&object, "omapi_message_process");
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
ISC_R_EXISTS, message -> id,
"specified object already exists");
}
/* If we're creating the object, do it now. */
if (!object) {
status = omapi_object_create (&object,
(omapi_object_t *)0,
type);
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"can't create new object");
}
}
/* If we're updating it, do so now. */
if (create || update) {
status = omapi_object_update (object,
(omapi_object_t *)0,
message -> object,
message -> handle);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference
(&object, "omapi_message_process");
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"can't update object");
}
}
/* Now send the new contents of the object back in
response. */
goto send;
case OMAPI_OP_REFRESH:
refresh:
status = omapi_handle_lookup (&object,
message -> handle);
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"no matching handle");
}
send:
status = omapi_protocol_send_update (po, (omapi_object_t *)0,
message -> id, object);
omapi_object_dereference (&object,
"omapi_message_process");
return status;
case OMAPI_OP_UPDATE:
if (m -> object) {
omapi_object_reference (&object, m -> object,
"omapi_message_process");
} else {
status = omapi_handle_lookup (&object,
message -> handle);
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"no matching handle");
}
}
status = omapi_object_update (object, (omapi_object_t *)0,
message -> object,
message -> handle);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference
(&object, "omapi_message_process");
if (!message -> rid)
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"can't update object");
if (m)
omapi_signal ((omapi_object_t *)m,
"status", status,
(omapi_typed_data_t *)0);
return ISC_R_SUCCESS;
}
if (!message -> rid)
status = omapi_protocol_send_status
(po, (omapi_object_t *)0, ISC_R_SUCCESS,
message -> id, (char *)0);
if (m)
omapi_signal ((omapi_object_t *)m,
"status", ISC_R_SUCCESS,
(omapi_typed_data_t *)0);
return status;
case OMAPI_OP_NOTIFY:
return omapi_protocol_send_status
(po, (omapi_object_t *)0, ISC_R_NOTIMPLEMENTED,
message -> id, "notify not implemented yet");
case OMAPI_OP_STATUS:
/* The return status of a request. */
if (!m)
return ISC_R_UNEXPECTED;
/* Get the wait status. */
status = omapi_get_value_str (mo,
(omapi_object_t *)0,
"result", &tv);
if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&wsi, tv -> value);
waitstatus = wsi;
omapi_value_dereference (&tv,
"omapi_message_process");
if (status != ISC_R_SUCCESS)
waitstatus = ISC_R_UNEXPECTED;
} else
waitstatus = ISC_R_UNEXPECTED;
status = omapi_get_value_str (mo,
(omapi_object_t *)0,
"message", &tv);
omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv);
if (status == ISC_R_SUCCESS)
omapi_value_dereference (&tv, "omapi_message_process");
return ISC_R_SUCCESS;
case OMAPI_OP_DELETE:
status = omapi_handle_lookup (&object,
message -> handle);
if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
status, message -> id,
"no matching handle");
}
if (!object -> type -> remove)
return omapi_protocol_send_status
(po, (omapi_object_t *)0,
ISC_R_NOTIMPLEMENTED, message -> id,
"no remove method for object");
status = (*(object -> type -> remove)) (object,
(omapi_object_t *)0);
omapi_object_dereference (&object,
"omapi_message_process");
return omapi_protocol_send_status (po, (omapi_object_t *)0,
status, message -> id,
(char *)0);
}
return ISC_R_NOTIMPLEMENTED;
}

817
lib/omapi/protocol.c Normal file
View File

@@ -0,0 +1,817 @@
/* 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_p.h>
isc_result_t omapi_protocol_connect (omapi_object_t *h,
const 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,
unsigned ver,
unsigned 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
? m -> object -> handle
: 0)));
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 : m -> rid);
if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1);
return status;
}
/* Stuff out the name/value pairs specific to this message. */
status = omapi_stuff_values (c, id, (omapi_object_t *)m);
if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1);
return status;
}
/* Write the zero-length name that terminates the list of name/value
pairs specific to the message. */
status = omapi_connection_put_uint16 (c, 0);
if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1);
return status;
}
/* Stuff out all the published name/value pairs in the object that's
being sent in the message, if there is one. */
if (m -> object) {
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 for the associated object. */
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,
const 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, (u_int32_t *)&p -> protocol_version);
omapi_connection_get_uint32
(c, (u_int32_t *)&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;
}
/* Swap in the header... */
omapi_connection_get_uint32
(c, (u_int32_t *)&p -> message -> authid);
/* XXX bind the authenticator here! */
omapi_connection_get_uint32
(c, (u_int32_t *)&p -> message -> authlen);
omapi_connection_get_uint32
(c, (u_int32_t *)&p -> message -> op);
omapi_connection_get_uint32
(c, (u_int32_t *)&p -> message -> handle);
omapi_connection_get_uint32
(c, (u_int32_t *)&p -> message -> id);
omapi_connection_get_uint32
(c, (u_int32_t *)&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. */
/* First we read in message-specific values, then object
values. */
p -> reading_message_values = 1;
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 we've already read in the object, we are
done reading the message, but if we've just
finished reading in the values associated
with the message, we need to read the
object. */
if (p -> reading_message_values) {
p -> reading_message_values = 0;
goto need_name_length;
}
/* 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;
}
p -> state = omapi_protocol_name_wait;
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. */
p -> state = omapi_protocol_value_length_wait;
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, vlen,
"omapi_protocol_signal_handler"));
if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1);
return ISC_R_NOMEMORY;
}
p -> state = omapi_protocol_value_wait;
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:
if (p -> reading_message_values) {
status = (omapi_set_value
((omapi_object_t *)p -> message,
p -> message -> id_object,
p -> name, p -> value));
} else {
if (!p -> message -> object) {
/* 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;
}
}
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. */
/* Process the message. */
message_done:
status = omapi_message_process ((omapi_object_t *)p -> message,
h);
if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1);
return ISC_R_NOMEMORY;
}
/* XXX unbind the authenticator. */
auth_unbind:
omapi_object_dereference ((omapi_object_t **)&p -> message,
"omapi_protocol_signal_handler");
/* Now wait for the next message. */
goto to_header_wait;
default:
/* XXX should never get here. Assertion? */
break;
}
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, const 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,
const 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,
const 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;
}
isc_result_t omapi_protocol_send_status (omapi_object_t *po,
omapi_object_t *id,
isc_result_t waitstatus,
unsigned rid, const char *msg)
{
isc_result_t status;
omapi_object_t *message = (omapi_object_t *)0;
if (po -> type != omapi_type_protocol)
return ISC_R_INVALIDARG;
status = omapi_message_new (&message, "omapi_protocol_send_status");
if (status != ISC_R_SUCCESS)
return status;
status = omapi_set_int_value (message, (omapi_object_t *)0,
"op", OMAPI_OP_STATUS);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&message,
"omapi_protocol_send_status");
return status;
}
status = omapi_set_int_value (message, (omapi_object_t *)0,
"rid", (int)rid);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&message,
"omapi_protocol_send_status");
return status;
}
status = omapi_set_int_value (message, (omapi_object_t *)0,
"result", (int)waitstatus);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&message,
"omapi_protocol_send_status");
return status;
}
/* If a message has been provided, send it. */
if (msg) {
status = omapi_set_string_value (message, (omapi_object_t *)0,
"message", msg);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference
(&message, "omapi_protocol_send_status");
return status;
}
}
return omapi_protocol_send_message (po,
id, message, (omapi_object_t *)0);
}
isc_result_t omapi_protocol_send_update (omapi_object_t *po,
omapi_object_t *id,
unsigned rid,
omapi_object_t *object)
{
isc_result_t status;
omapi_object_t *message = (omapi_object_t *)0;
if (po -> type != omapi_type_protocol)
return ISC_R_INVALIDARG;
status = omapi_message_new (&message, "omapi_protocol_send_update");
if (status != ISC_R_SUCCESS)
return status;
status = omapi_set_int_value (message, (omapi_object_t *)0,
"op", OMAPI_OP_UPDATE);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&message,
"omapi_protocol_send_update");
return status;
}
if (rid) {
omapi_handle_t handle;
status = omapi_set_int_value (message, (omapi_object_t *)0,
"rid", (int)rid);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference
(&message, "omapi_protocol_send_update");
return status;
}
status = omapi_object_handle (&handle, object);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference
(&message, "omapi_protocol_send_update");
return status;
}
status = omapi_set_int_value (message, (omapi_object_t *)0,
"handle", (int)handle);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference
(&message, "omapi_protocol_send_update");
return status;
}
}
status = omapi_set_object_value (message, (omapi_object_t *)0,
"object", object);
if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&message, "dhcpctl_open_object");
return status;
}
return omapi_protocol_send_message (po,
id, message, (omapi_object_t *)0);
}

81
lib/omapi/result.c Normal file
View File

@@ -0,0 +1,81 @@
/* 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_p.h>
static const 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 */
"object unchanged", /* 42 */
"more than one object matches key", /* 43 */
"key conflict", /* 44 */
"parse error(s) occurred", /* 45 */
"no key specified", /* 46 */
};
const char *isc_result_totext (isc_result_t result)
{
if (result >= ISC_R_SUCCESS && result < ISC_R_NRESULTS)
return text [result];
return "unknown error.";
}

682
lib/omapi/support.c Normal file
View File

@@ -0,0 +1,682 @@
/* 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_p.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,
0, 0, 0);
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,
0, 0, 0);
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,
0, 0, 0);
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,
0, 0, 0);
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,
0, 0, 0);
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,
0, 0, 0);
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,
0, 0, 0);
if (status != ISC_R_SUCCESS)
return status;
status = omapi_object_type_register (&omapi_type_waiter,
"waiter",
0,
0,
0,
omapi_waiter_signal_handler, 0,
0, 0, 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,
const 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 *,
const char *),
isc_result_t (*signal_handler)
(omapi_object_t *,
const char *, va_list),
isc_result_t (*stuff_values)
(omapi_object_t *,
omapi_object_t *,
omapi_object_t *),
isc_result_t (*lookup)
(omapi_object_t **,
omapi_object_t *,
omapi_object_t *),
isc_result_t (*create)
(omapi_object_t **,
omapi_object_t *),
isc_result_t (*remove)
(omapi_object_t *,
omapi_object_t *))
{
omapi_object_type_t *t;
t = malloc (sizeof *t);
if (!t)
return ISC_R_NOMEMORY;
memset (t, 0, sizeof *t);
t -> name = name;
t -> set_value = set_value;
t -> get_value = get_value;
t -> destroy = destroy;
t -> signal_handler = signal_handler;
t -> stuff_values = stuff_values;
t -> lookup = lookup;
t -> create = create;
t -> remove = remove;
t -> next = omapi_object_types;
omapi_object_types = t;
if (type)
*type = t;
return ISC_R_SUCCESS;
}
isc_result_t omapi_signal (omapi_object_t *handle, const 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, const 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_set_value_str (omapi_object_t *h,
omapi_object_t *id,
const char *name,
omapi_typed_data_t *value)
{
omapi_object_t *outer;
omapi_data_string_t *nds;
isc_result_t status;
nds = (omapi_data_string_t *)0;
status = omapi_data_string_new (&nds, strlen (name),
"omapi_set_value_str");
if (status != ISC_R_SUCCESS)
return status;
memcpy (nds -> value, name, strlen (name));
return omapi_set_value (h, id, nds, value);
}
isc_result_t omapi_set_boolean_value (omapi_object_t *h, omapi_object_t *id,
const char *name, int value)
{
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *n = (omapi_data_string_t *)0;
int len;
int ip;
status = omapi_data_string_new (&n, strlen (name),
"omapi_set_boolean_value");
if (status != ISC_R_SUCCESS)
return status;
memcpy (n -> value, name, strlen (name));
status = omapi_typed_data_new (&tv, omapi_datatype_int, value);
if (status != ISC_R_SUCCESS) {
omapi_data_string_dereference (&n,
"omapi_set_boolean_value");
return status;
}
status = omapi_set_value (h, id, n, tv);
omapi_data_string_dereference (&n, "omapi_set_boolean_value");
omapi_typed_data_dereference (&tv, "omapi_set_boolean_value");
return status;
}
isc_result_t omapi_set_int_value (omapi_object_t *h, omapi_object_t *id,
const char *name, int value)
{
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *n = (omapi_data_string_t *)0;
int len;
int ip;
status = omapi_data_string_new (&n, strlen (name),
"omapi_set_int_value");
if (status != ISC_R_SUCCESS)
return status;
memcpy (n -> value, name, strlen (name));
status = omapi_typed_data_new (&tv, omapi_datatype_int, value);
if (status != ISC_R_SUCCESS) {
omapi_data_string_dereference (&n,
"omapi_set_int_value");
return status;
}
status = omapi_set_value (h, id, n, tv);
omapi_data_string_dereference (&n, "omapi_set_int_value");
omapi_typed_data_dereference (&tv, "omapi_set_int_value");
return status;
}
isc_result_t omapi_set_object_value (omapi_object_t *h, omapi_object_t *id,
const char *name, omapi_object_t *value)
{
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *n = (omapi_data_string_t *)0;
int len;
int ip;
status = omapi_data_string_new (&n, strlen (name),
"omapi_set_object_value");
if (status != ISC_R_SUCCESS)
return status;
memcpy (n -> value, name, strlen (name));
status = omapi_typed_data_new (&tv, omapi_datatype_object, value);
if (status != ISC_R_SUCCESS) {
omapi_data_string_dereference (&n,
"omapi_set_object_value");
return status;
}
status = omapi_set_value (h, id, n, tv);
omapi_data_string_dereference (&n, "omapi_set_object_value");
omapi_typed_data_dereference (&tv, "omapi_set_object_value");
return status;
}
isc_result_t omapi_set_string_value (omapi_object_t *h, omapi_object_t *id,
const char *name, const char *value)
{
isc_result_t status;
omapi_typed_data_t *tv = (omapi_typed_data_t *)0;
omapi_data_string_t *n = (omapi_data_string_t *)0;
int len;
int ip;
status = omapi_data_string_new (&n, strlen (name),
"omapi_set_string_value");
if (status != ISC_R_SUCCESS)
return status;
memcpy (n -> value, name, strlen (name));
status = omapi_typed_data_new (&tv, omapi_datatype_string, value);
if (status != ISC_R_SUCCESS) {
omapi_data_string_dereference (&n,
"omapi_set_string_value");
return status;
}
status = omapi_set_value (h, id, n, tv);
omapi_data_string_dereference (&n, "omapi_set_string_value");
omapi_typed_data_dereference (&tv, "omapi_set_string_value");
return status;
}
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_get_value_str (omapi_object_t *h,
omapi_object_t *id,
const char *name,
omapi_value_t **value)
{
omapi_object_t *outer;
omapi_data_string_t *nds;
isc_result_t status;
nds = (omapi_data_string_t *)0;
status = omapi_data_string_new (&nds, strlen (name),
"omapi_get_value_str");
if (status != ISC_R_SUCCESS)
return status;
memcpy (nds -> value, name, strlen (name));
for (outer = h; outer -> outer; outer = outer -> outer)
;
if (outer -> type -> get_value)
return (*(outer -> type -> get_value)) (outer,
id, nds, 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;
}
isc_result_t omapi_object_create (omapi_object_t **obj, omapi_object_t *id,
omapi_object_type_t *type)
{
if (!type -> create)
return ISC_R_NOTIMPLEMENTED;
return (*(type -> create)) (obj, id);
}
isc_result_t omapi_object_update (omapi_object_t *obj, omapi_object_t *id,
omapi_object_t *src, omapi_handle_t handle)
{
omapi_generic_object_t *gsrc;
isc_result_t status;
int i;
if (!src)
return ISC_R_INVALIDARG;
if (src -> type != omapi_type_generic)
return ISC_R_NOTIMPLEMENTED;
gsrc = (omapi_generic_object_t *)src;
for (i = 0; i < gsrc -> nvalues; i++) {
status = omapi_set_value (obj, id,
gsrc -> values [i] -> name,
gsrc -> values [i] -> value);
if (status != ISC_R_SUCCESS)
return status;
}
if (handle)
omapi_set_int_value (obj, id, "remote-handle", (int)handle);
status = omapi_signal (obj, "updated");
if (status != ISC_R_NOTFOUND)
return status;
return ISC_R_SUCCESS;
}
int omapi_data_string_cmp (omapi_data_string_t *s1, omapi_data_string_t *s2)
{
unsigned 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, const char *s2)
{
unsigned 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;
}
int omapi_td_strcmp (omapi_typed_data_t *s1, const char *s2)
{
unsigned len, slen;
int rv;
/* If the data type is not compatible, never equal. */
if (s1 -> type != omapi_datatype_data &&
s1 -> type != omapi_datatype_string)
return -1;
slen = strlen (s2);
if (slen > s1 -> u.buffer.len)
len = s1 -> u.buffer.len;
else
len = slen;
rv = memcmp (s1 -> u.buffer.value, s2, len);
if (rv)
return rv;
if (s1 -> u.buffer.len > slen)
return 1;
else if (s1 -> u.buffer.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, const 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,
const unsigned char *value,
unsigned len, const 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, const 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;
}
isc_result_t omapi_make_handle_value (omapi_value_t **vp,
omapi_data_string_t *name,
omapi_object_t *value,
const 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;
}
status = (omapi_object_handle
((omapi_handle_t *)&(*vp) -> value -> u.integer,
value));
if (status != ISC_R_SUCCESS) {
omapi_value_dereference (vp, caller);
return status;
}
}
return ISC_R_SUCCESS;
}
isc_result_t omapi_make_string_value (omapi_value_t **vp,
omapi_data_string_t *name,
char *value, const 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_string, value);
if (status != ISC_R_SUCCESS) {
omapi_value_dereference (vp, caller);
return status;
}
}
return ISC_R_SUCCESS;
}
isc_result_t omapi_get_int_value (unsigned long *v, omapi_typed_data_t *t)
{
u_int32_t rv;
if (t -> type == omapi_datatype_int) {
*v = t -> u.integer;
return ISC_R_SUCCESS;
} else if (t -> type == omapi_datatype_string ||
t -> type == omapi_datatype_data) {
if (t -> u.buffer.len != sizeof (rv))
return ISC_R_INVALIDARG;
memcpy (&rv, t -> u.buffer.value, sizeof rv);
*v = ntohl (rv);
return ISC_R_SUCCESS;
}
return ISC_R_INVALIDARG;
}

85
lib/omapi/test.c Normal file
View File

@@ -0,0 +1,85 @@
/* 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <isc/result.h>
#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;
}