aboutsummaryrefslogtreecommitdiff
path: root/contrib/isc-dhcp/omapip/dispatch.c
diff options
context:
space:
mode:
authorMurray Stokely <murray@FreeBSD.org>2002-02-19 11:04:34 +0000
committerMurray Stokely <murray@FreeBSD.org>2002-02-19 11:04:34 +0000
commitce99b771f886a2c842db7aa803c9a5a5918f42c8 (patch)
tree229464d9b3244ab78e2784c9a0a1f78de317089a /contrib/isc-dhcp/omapip/dispatch.c
parent7657fb140fbd218ea326d55bd3c43c4077f03d9a (diff)
downloadsrc-ce99b771f886a2c842db7aa803c9a5a5918f42c8.tar.gz
src-ce99b771f886a2c842db7aa803c9a5a5918f42c8.zip
Import ISC DHCP 3.0.1 RC6 client.
Notes
Notes: svn path=/vendor/isc-dhcp/dist/; revision=90908
Diffstat (limited to 'contrib/isc-dhcp/omapip/dispatch.c')
-rw-r--r--contrib/isc-dhcp/omapip/dispatch.c604
1 files changed, 604 insertions, 0 deletions
diff --git a/contrib/isc-dhcp/omapip/dispatch.c b/contrib/isc-dhcp/omapip/dispatch.c
new file mode 100644
index 000000000000..02bab7cc3019
--- /dev/null
+++ b/contrib/isc-dhcp/omapip/dispatch.c
@@ -0,0 +1,604 @@
+/* dispatch.c
+
+ I/O dispatcher. */
+
+/*
+ * Copyright (c) 1999-2000 Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
+ */
+
+#include <omapip/omapip_p.h>
+
+static omapi_io_object_t omapi_io_states;
+u_int32_t cur_time;
+
+OMAPI_OBJECT_ALLOC (omapi_io,
+ omapi_io_object_t, omapi_type_io_object)
+OMAPI_OBJECT_ALLOC (omapi_waiter,
+ omapi_waiter_object_t, omapi_type_waiter)
+
+/* 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 = (omapi_io_object_t *)0;
+ status = omapi_io_allocate (&obj, MDL);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ status = omapi_object_reference (&obj -> inner, h, MDL);
+ if (status != ISC_R_SUCCESS) {
+ omapi_io_dereference (&obj, MDL);
+ return status;
+ }
+
+ status = omapi_object_reference (&h -> outer,
+ (omapi_object_t *)obj, MDL);
+ if (status != ISC_R_SUCCESS) {
+ omapi_io_dereference (&obj, MDL);
+ 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)
+ omapi_io_reference (&p -> next, obj, MDL);
+ else
+ omapi_io_reference (&omapi_io_states.next, obj, MDL);
+
+ obj -> readfd = readfd;
+ obj -> writefd = writefd;
+ obj -> reader = reader;
+ obj -> writer = writer;
+ obj -> reaper = reaper;
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t omapi_unregister_io_object (omapi_object_t *h)
+{
+ omapi_io_object_t *p, *obj, *last, *ph;
+
+ if (!h -> outer || h -> outer -> type != omapi_type_io_object)
+ return ISC_R_INVALIDARG;
+ obj = (omapi_io_object_t *)h -> outer;
+ ph = (omapi_io_object_t *)0;
+ omapi_io_reference (&ph, obj, MDL);
+
+ /* remove from the list of I/O states */
+ last = &omapi_io_states;
+ for (p = omapi_io_states.next; p; p = p -> next) {
+ if (p == obj) {
+ omapi_io_dereference (&last -> next, MDL);
+ omapi_io_reference (&last -> next, p -> next, MDL);
+ break;
+ }
+ last = p;
+ }
+ if (obj -> next)
+ omapi_io_dereference (&obj -> next, MDL);
+
+ if (obj -> outer) {
+ if (obj -> outer -> inner == (omapi_object_t *)obj)
+ omapi_object_dereference (&obj -> outer -> inner,
+ MDL);
+ omapi_object_dereference (&obj -> outer, MDL);
+ }
+ omapi_object_dereference (&obj -> inner, MDL);
+ omapi_object_dereference (&h -> outer, MDL);
+ omapi_io_dereference (&ph, MDL);
+ 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 = (omapi_waiter_object_t *)0;
+ status = omapi_waiter_allocate (&waiter, MDL);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ /* 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, MDL);
+ if (status != ISC_R_SUCCESS) {
+ omapi_waiter_dereference (&waiter, MDL);
+ return status;
+ }
+
+ status = omapi_object_reference (&inner -> inner,
+ (omapi_object_t *)waiter,
+ MDL);
+ if (status != ISC_R_SUCCESS) {
+ omapi_waiter_dereference (&waiter, MDL);
+ 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,
+ MDL);
+ if (waiter -> inner)
+ omapi_object_reference
+ (&waiter -> outer -> inner,
+ waiter -> inner, MDL);
+ }
+ omapi_object_dereference (&waiter -> outer, MDL);
+ }
+ if (waiter -> inner)
+ omapi_object_dereference (&waiter -> inner, MDL);
+
+ status = waiter -> waitstatus;
+ omapi_waiter_dereference (&waiter, MDL);
+ return status;
+}
+
+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;
+ omapi_object_t *tmp = (omapi_object_t *)0;
+
+ 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--;
+ }
+
+ /* It is possible for the timeout to get set larger than
+ the largest time select() is willing to accept.
+ Restricting the timeout to a maximum of one day should
+ work around this. -DPN. (Ref: Bug #416) */
+ if (to.tv_sec > (60 * 60 * 24))
+ to.tv_sec = 60 * 60 * 24;
+ }
+
+ /* If the object we're waiting on has reached completion,
+ return now. */
+ if (waiter && waiter -> ready)
+ return ISC_R_SUCCESS;
+
+ again:
+ /* 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 && io -> inner &&
+ (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
+ FD_SET (desc, &r);
+ if (desc > max)
+ max = desc;
+ }
+
+ /* Same deal for write fdets. */
+ if (io -> writefd && io -> inner &&
+ (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
+ FD_SET (desc, &w);
+ if (desc > max)
+ max = desc;
+ }
+ }
+
+ /* Wait for a packet or a timeout... XXX */
+#if 0
+#if defined (__linux__)
+#define fds_bits __fds_bits
+#endif
+ log_error ("dispatch: %d %lx %lx", max,
+ (unsigned long)r.fds_bits [0],
+ (unsigned long)w.fds_bits [0]);
+#endif
+ 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;
+
+ /* We probably have a bad file descriptor. Figure out which one.
+ When we find it, call the reaper function on it, which will
+ maybe make it go away, and then try again. */
+ if (count < 0) {
+ struct timeval t0;
+ omapi_io_object_t *prev = (omapi_io_object_t *)0;
+ io = (omapi_io_object_t *)0;
+ if (omapi_io_states.next)
+ omapi_io_reference (&io, omapi_io_states.next, MDL);
+
+ while (io) {
+ omapi_object_t *obj;
+ FD_ZERO (&r);
+ FD_ZERO (&w);
+ t0.tv_sec = t0.tv_usec = 0;
+
+ if (io -> readfd && io -> inner &&
+ (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
+ FD_SET (desc, &r);
+#if 0
+ log_error ("read check: %d %lx %lx", max,
+ (unsigned long)r.fds_bits [0],
+ (unsigned long)w.fds_bits [0]);
+#endif
+ count = select (desc + 1, &r, &w, &x, &t0);
+ bogon:
+ if (count < 0) {
+ log_error ("Bad descriptor %d.", desc);
+ for (obj = (omapi_object_t *)io;
+ obj -> outer;
+ obj = obj -> outer)
+ ;
+ for (; obj; obj = obj -> inner) {
+ omapi_value_t *ov;
+ int len;
+ const char *s;
+ ov = (omapi_value_t *)0;
+ omapi_get_value_str (obj,
+ (omapi_object_t *)0,
+ "name", &ov);
+ if (ov && ov -> value &&
+ (ov -> value -> type ==
+ omapi_datatype_string)) {
+ s = (char *)
+ ov -> value -> u.buffer.value;
+ len = ov -> value -> u.buffer.len;
+ } else {
+ s = "";
+ len = 0;
+ }
+ log_error ("Object %lx %s%s%.*s",
+ (unsigned long)obj,
+ obj -> type -> name,
+ len ? " " : "",
+ len, s);
+ if (len)
+ omapi_value_dereference (&ov, MDL);
+ }
+ status = (*(io -> reaper)) (io -> inner);
+ if (prev) {
+ omapi_io_dereference (&prev -> next, MDL);
+ if (io -> next)
+ omapi_io_reference (&prev -> next,
+ io -> next, MDL);
+ } else {
+ omapi_io_dereference
+ (&omapi_io_states.next, MDL);
+ if (io -> next)
+ omapi_io_reference
+ (&omapi_io_states.next,
+ io -> next, MDL);
+ }
+ omapi_io_dereference (&io, MDL);
+ goto again;
+ }
+ }
+
+ FD_ZERO (&r);
+ FD_ZERO (&w);
+ t0.tv_sec = t0.tv_usec = 0;
+
+ /* Same deal for write fdets. */
+ if (io -> writefd && io -> inner &&
+ (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
+ FD_SET (desc, &w);
+ count = select (desc + 1, &r, &w, &x, &t0);
+ if (count < 0)
+ goto bogon;
+ }
+ if (prev)
+ omapi_io_dereference (&prev, MDL);
+ omapi_io_reference (&prev, io, MDL);
+ omapi_io_dereference (&io, MDL);
+ if (prev -> next)
+ omapi_io_reference (&io, prev -> next, MDL);
+ }
+ if (prev)
+ omapi_io_dereference (&prev, MDL);
+
+ }
+
+ for (io = omapi_io_states.next; io; io = io -> next) {
+ if (!io -> inner)
+ continue;
+ omapi_object_reference (&tmp, io -> inner, MDL);
+ /* Check for a read descriptor, and if there is one,
+ see if we got input on that socket. */
+ if (io -> readfd &&
+ (desc = (*(io -> readfd)) (tmp)) >= 0) {
+ if (FD_ISSET (desc, &r))
+ status = ((*(io -> reader)) (tmp));
+ /* XXX what to do with status? */
+ }
+
+ /* Same deal for write descriptors. */
+ if (io -> writefd &&
+ (desc = (*(io -> writefd)) (tmp)) >= 0)
+ {
+ if (FD_ISSET (desc, &w))
+ status = ((*(io -> writer)) (tmp));
+ /* XXX what to do with status? */
+ }
+ omapi_object_dereference (&tmp, MDL);
+ }
+
+ /* 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) {
+ if (io -> inner)
+ status = (*(io -> reaper)) (io -> inner);
+ if (!io -> inner || 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_io_reference (&tmp,
+ io -> next, MDL);
+ if (prev) {
+ omapi_io_dereference (&prev -> next,
+ MDL);
+ if (tmp)
+ omapi_io_reference
+ (&prev -> next,
+ tmp, MDL);
+ } else {
+ omapi_io_dereference
+ (&omapi_io_states.next, MDL);
+ if (tmp)
+ omapi_io_reference
+ (&omapi_io_states.next,
+ tmp, MDL);
+ else
+ omapi_signal_in
+ ((omapi_object_t *)
+ &omapi_io_states,
+ "ready");
+ }
+ if (tmp)
+ omapi_io_dereference (&tmp, MDL);
+ }
+ }
+ 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 *file, int line)
+{
+ omapi_io_object_t *obj, *p, *last;
+
+ if (h -> type != omapi_type_io_object)
+ return ISC_R_INVALIDARG;
+
+ obj = (omapi_io_object_t *)h;
+
+ /* remove from the list of I/O states */
+ for (p = omapi_io_states.next; p; p = p -> next) {
+ if (p == obj) {
+ omapi_io_dereference (&last -> next, MDL);
+ omapi_io_reference (&last -> next, p -> next, MDL);
+ omapi_io_dereference (&p, MDL);
+ break;
+ }
+ last = p;
+ }
+
+ 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;
+ waiter -> waitstatus = ISC_R_SUCCESS;
+ return ISC_R_SUCCESS;
+ }
+
+ if (!strcmp (name, "status")) {
+ waiter = (omapi_waiter_object_t *)h;
+ waiter -> ready = 1;
+ waiter -> waitstatus = va_arg (ap, isc_result_t);
+ return ISC_R_SUCCESS;
+ }
+
+ if (!strcmp (name, "disconnect")) {
+ waiter = (omapi_waiter_object_t *)h;
+ waiter -> ready = 1;
+ waiter -> waitstatus = ISC_R_CONNRESET;
+ 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;
+}
+
+isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *,
+ void *),
+ void *p)
+{
+ omapi_io_object_t *io;
+ isc_result_t status;
+
+ for (io = omapi_io_states.next; io; io = io -> next) {
+ if (io -> inner) {
+ status = (*func) (io -> inner, p);
+ if (status != ISC_R_SUCCESS)
+ return status;
+ }
+ }
+ return ISC_R_SUCCESS;
+}