Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / omapip / dispatch.c
blobc004fe305edfe16996de17731ea201bea025be9f
1 /* $NetBSD: dispatch.c,v 1.4 2014/07/12 12:09:37 spz Exp $ */
2 /* dispatch.c
4 I/O dispatcher. */
6 /*
7 * Copyright (c) 2004,2007-2009,2013-2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1999-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
23 * 950 Charter Street
24 * Redwood City, CA 94063
25 * <info@isc.org>
26 * https://www.isc.org/
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: dispatch.c,v 1.4 2014/07/12 12:09:37 spz Exp $");
33 #include "dhcpd.h"
35 #include <omapip/omapip_p.h>
36 #include <sys/time.h>
38 static omapi_io_object_t omapi_io_states;
39 struct timeval cur_tv;
41 struct eventqueue *rw_queue_empty;
43 OMAPI_OBJECT_ALLOC (omapi_io,
44 omapi_io_object_t, omapi_type_io_object)
45 OMAPI_OBJECT_ALLOC (omapi_waiter,
46 omapi_waiter_object_t, omapi_type_waiter)
48 void
49 register_eventhandler(struct eventqueue **queue, void (*handler)(void *))
51 struct eventqueue *t, *q;
53 /* traverse to end of list */
54 t = NULL;
55 for (q = *queue ; q ; q = q->next) {
56 if (q->handler == handler)
57 return; /* handler already registered */
58 t = q;
61 q = ((struct eventqueue *)dmalloc(sizeof(struct eventqueue), MDL));
62 if (!q)
63 log_fatal("register_eventhandler: no memory!");
64 memset(q, 0, sizeof *q);
65 if (t)
66 t->next = q;
67 else
68 *queue = q;
69 q->handler = handler;
70 return;
73 void
74 unregister_eventhandler(struct eventqueue **queue, void (*handler)(void *))
76 struct eventqueue *t, *q;
78 /* traverse to end of list */
79 t= NULL;
80 for (q = *queue ; q ; q = q->next) {
81 if (q->handler == handler) {
82 if (t)
83 t->next = q->next;
84 else
85 *queue = q->next;
86 dfree(q, MDL); /* Don't access q after this!*/
87 break;
89 t = q;
91 return;
94 void
95 trigger_event(struct eventqueue **queue)
97 struct eventqueue *q;
99 for (q=*queue ; q ; q=q->next) {
100 if (q->handler)
101 (*q->handler)(NULL);
106 * Callback routine to connect the omapi I/O object and socket with
107 * the isc socket code. The isc socket code will call this routine
108 * which will then call the correct local routine to process the bytes.
110 * Currently we are always willing to read more data, this should be modified
111 * so that on connections we don't read more if we already have enough.
113 * If we have more bytes to write we ask the library to call us when
114 * we can write more. If we indicate we don't have more to write we need
115 * to poke the library via isc_socket_fdwatchpoke.
119 * sockdelete indicates if we are deleting the socket or leaving it in place
120 * 1 is delete, 0 is leave in place
122 #define SOCKDELETE 1
123 static int
124 omapi_iscsock_cb(isc_task_t *task,
125 isc_socket_t *socket,
126 void *cbarg,
127 int flags)
129 omapi_io_object_t *obj;
130 isc_result_t status;
132 /* Get the current time... */
133 gettimeofday (&cur_tv, (struct timezone *)0);
135 /* isc socket stuff */
136 #if SOCKDELETE
138 * walk through the io states list, if our object is on there
139 * service it. if not ignore it.
141 for (obj = omapi_io_states.next;
142 (obj != NULL) && (obj->next != NULL);
143 obj = obj->next) {
144 if (obj == cbarg)
145 break;
147 if (obj == NULL) {
148 return(0);
150 #else
151 /* Not much to be done if we have the wrong type of object. */
152 if (((omapi_object_t *)cbarg) -> type != omapi_type_io_object) {
153 log_fatal ("Incorrect object type, must be of type io_object");
155 obj = (omapi_io_object_t *)cbarg;
158 * If the object is marked as closed don't try and process
159 * anything just indicate that we don't want any more.
161 * This should be a temporary fix until we arrange to properly
162 * close the socket.
164 if (obj->closed == ISC_TRUE) {
165 return(0);
167 #endif
169 if ((flags == ISC_SOCKFDWATCH_READ) &&
170 (obj->reader != NULL) &&
171 (obj->inner != NULL)) {
172 status = obj->reader(obj->inner);
174 * If we are shutting down (basically tried to
175 * read and got no bytes) we don't need to try
176 * again.
178 if (status == ISC_R_SHUTTINGDOWN)
179 return (0);
180 /* Otherwise We always ask for more when reading */
181 return (1);
182 } else if ((flags == ISC_SOCKFDWATCH_WRITE) &&
183 (obj->writer != NULL) &&
184 (obj->inner != NULL)) {
185 status = obj->writer(obj->inner);
186 /* If the writer has more to write they should return
187 * ISC_R_INPROGRESS */
188 if (status == ISC_R_INPROGRESS) {
189 return (1);
194 * We get here if we either had an error (inconsistent
195 * structures etc) or no more to write, tell the socket
196 * lib we don't have more to do right now.
198 return (0);
201 /* Register an I/O handle so that we can do asynchronous I/O on it. */
203 isc_result_t omapi_register_io_object (omapi_object_t *h,
204 int (*readfd) (omapi_object_t *),
205 int (*writefd) (omapi_object_t *),
206 isc_result_t (*reader)
207 (omapi_object_t *),
208 isc_result_t (*writer)
209 (omapi_object_t *),
210 isc_result_t (*reaper)
211 (omapi_object_t *))
213 isc_result_t status;
214 omapi_io_object_t *obj, *p;
215 int fd_flags = 0, fd = 0;
217 /* omapi_io_states is a static object. If its reference count
218 is zero, this is the first I/O handle to be registered, so
219 we need to initialize it. Because there is no inner or outer
220 pointer on this object, and we're setting its refcnt to 1, it
221 will never be freed. */
222 if (!omapi_io_states.refcnt) {
223 omapi_io_states.refcnt = 1;
224 omapi_io_states.type = omapi_type_io_object;
227 obj = (omapi_io_object_t *)0;
228 status = omapi_io_allocate (&obj, MDL);
229 if (status != ISC_R_SUCCESS)
230 return status;
231 obj->closed = ISC_FALSE; /* mark as open */
233 status = omapi_object_reference (&obj -> inner, h, MDL);
234 if (status != ISC_R_SUCCESS) {
235 omapi_io_dereference (&obj, MDL);
236 return status;
239 status = omapi_object_reference (&h -> outer,
240 (omapi_object_t *)obj, MDL);
241 if (status != ISC_R_SUCCESS) {
242 omapi_io_dereference (&obj, MDL);
243 return status;
247 * Attach the I/O object to the isc socket library via the
248 * fdwatch function. This allows the socket library to watch
249 * over a socket that we built. If there are both a read and
250 * a write socket we asssume they are the same socket.
253 if (readfd) {
254 fd_flags |= ISC_SOCKFDWATCH_READ;
255 fd = readfd(h);
258 if (writefd) {
259 fd_flags |= ISC_SOCKFDWATCH_WRITE;
260 fd = writefd(h);
263 if (fd_flags != 0) {
264 status = isc_socket_fdwatchcreate(dhcp_gbl_ctx.socketmgr,
265 fd, fd_flags,
266 omapi_iscsock_cb,
267 obj,
268 dhcp_gbl_ctx.task,
269 &obj->fd);
270 if (status != ISC_R_SUCCESS) {
271 log_error("Unable to register fd with library %s",
272 isc_result_totext(status));
274 /*sar*/
275 /* is this the cleanup we need? */
276 omapi_object_dereference(&h->outer, MDL);
277 omapi_io_dereference (&obj, MDL);
278 return (status);
283 /* Find the last I/O state, if there are any. */
284 for (p = omapi_io_states.next;
285 p && p -> next; p = p -> next)
287 if (p)
288 omapi_io_reference (&p -> next, obj, MDL);
289 else
290 omapi_io_reference (&omapi_io_states.next, obj, MDL);
292 obj -> readfd = readfd;
293 obj -> writefd = writefd;
294 obj -> reader = reader;
295 obj -> writer = writer;
296 obj -> reaper = reaper;
298 omapi_io_dereference(&obj, MDL);
299 return ISC_R_SUCCESS;
303 * ReRegister an I/O handle so that we can do asynchronous I/O on it.
304 * If the handle doesn't exist we call the register routine to build it.
305 * If it does exist we change the functions associated with it, and
306 * repoke the fd code to make it happy. Neither the objects nor the
307 * fd are allowed to have changed.
310 isc_result_t omapi_reregister_io_object (omapi_object_t *h,
311 int (*readfd) (omapi_object_t *),
312 int (*writefd) (omapi_object_t *),
313 isc_result_t (*reader)
314 (omapi_object_t *),
315 isc_result_t (*writer)
316 (omapi_object_t *),
317 isc_result_t (*reaper)
318 (omapi_object_t *))
320 omapi_io_object_t *obj;
321 int fd_flags = 0;
323 if ((!h -> outer) || (h -> outer -> type != omapi_type_io_object)) {
325 * If we don't have an object or if the type isn't what
326 * we expect do the normal registration (which will overwrite
327 * an incorrect type, that's what we did historically, may
328 * want to change that)
330 return (omapi_register_io_object (h, readfd, writefd,
331 reader, writer, reaper));
334 /* We have an io object of the correct type, try to update it */
335 /*sar*/
336 /* Should we validate that the fd matches the previous one?
337 * It's suppossed to, that's a requirement, don't bother yet */
339 obj = (omapi_io_object_t *)h->outer;
341 obj->readfd = readfd;
342 obj->writefd = writefd;
343 obj->reader = reader;
344 obj->writer = writer;
345 obj->reaper = reaper;
347 if (readfd) {
348 fd_flags |= ISC_SOCKFDWATCH_READ;
351 if (writefd) {
352 fd_flags |= ISC_SOCKFDWATCH_WRITE;
355 isc_socket_fdwatchpoke(obj->fd, fd_flags);
357 return (ISC_R_SUCCESS);
360 isc_result_t omapi_unregister_io_object (omapi_object_t *h)
362 omapi_io_object_t *obj, *ph;
363 #if SOCKDELETE
364 omapi_io_object_t *p, *last;
365 #endif
367 if (!h -> outer || h -> outer -> type != omapi_type_io_object)
368 return DHCP_R_INVALIDARG;
369 obj = (omapi_io_object_t *)h -> outer;
370 ph = (omapi_io_object_t *)0;
371 omapi_io_reference (&ph, obj, MDL);
373 #if SOCKDELETE
375 * For now we leave this out. We can't clean up the isc socket
376 * structure cleanly yet so we need to leave the io object in place.
377 * By leaving it on the io states list we avoid it being freed.
378 * We also mark it as closed to avoid using it.
381 /* remove from the list of I/O states */
382 last = &omapi_io_states;
383 for (p = omapi_io_states.next; p; p = p -> next) {
384 if (p == obj) {
385 omapi_io_dereference (&last -> next, MDL);
386 omapi_io_reference (&last -> next, p -> next, MDL);
387 break;
389 last = p;
391 if (obj -> next)
392 omapi_io_dereference (&obj -> next, MDL);
393 #endif
395 if (obj -> outer) {
396 if (obj -> outer -> inner == (omapi_object_t *)obj)
397 omapi_object_dereference (&obj -> outer -> inner,
398 MDL);
399 omapi_object_dereference (&obj -> outer, MDL);
401 omapi_object_dereference (&obj -> inner, MDL);
402 omapi_object_dereference (&h -> outer, MDL);
404 #if SOCKDELETE
405 /* remove isc socket associations */
406 if (obj->fd != NULL) {
407 isc_socket_cancel(obj->fd, dhcp_gbl_ctx.task,
408 ISC_SOCKCANCEL_ALL);
409 isc_socket_detach(&obj->fd);
411 #else
412 obj->closed = ISC_TRUE;
413 #endif
415 omapi_io_dereference (&ph, MDL);
416 return ISC_R_SUCCESS;
419 isc_result_t omapi_dispatch (struct timeval *t)
421 return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
425 isc_result_t omapi_wait_for_completion (omapi_object_t *object,
426 struct timeval *t)
428 isc_result_t status;
429 omapi_waiter_object_t *waiter;
430 omapi_object_t *inner;
432 if (object) {
433 waiter = (omapi_waiter_object_t *)0;
434 status = omapi_waiter_allocate (&waiter, MDL);
435 if (status != ISC_R_SUCCESS)
436 return status;
438 /* Paste the waiter object onto the inner object we're
439 waiting on. */
440 for (inner = object; inner -> inner; inner = inner -> inner)
443 status = omapi_object_reference (&waiter -> outer, inner, MDL);
444 if (status != ISC_R_SUCCESS) {
445 omapi_waiter_dereference (&waiter, MDL);
446 return status;
449 status = omapi_object_reference (&inner -> inner,
450 (omapi_object_t *)waiter,
451 MDL);
452 if (status != ISC_R_SUCCESS) {
453 omapi_waiter_dereference (&waiter, MDL);
454 return status;
456 } else
457 waiter = (omapi_waiter_object_t *)0;
459 do {
460 status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
461 if (status != ISC_R_SUCCESS)
462 return status;
463 } while (!waiter || !waiter -> ready);
465 if (waiter -> outer) {
466 if (waiter -> outer -> inner) {
467 omapi_object_dereference (&waiter -> outer -> inner,
468 MDL);
469 if (waiter -> inner)
470 omapi_object_reference
471 (&waiter -> outer -> inner,
472 waiter -> inner, MDL);
474 omapi_object_dereference (&waiter -> outer, MDL);
476 if (waiter -> inner)
477 omapi_object_dereference (&waiter -> inner, MDL);
479 status = waiter -> waitstatus;
480 omapi_waiter_dereference (&waiter, MDL);
481 return status;
484 isc_result_t omapi_one_dispatch (omapi_object_t *wo,
485 struct timeval *t)
487 fd_set r, w, x, rr, ww, xx;
488 int max = 0;
489 int count;
490 int desc;
491 struct timeval now, to;
492 omapi_io_object_t *io, *prev, *next;
493 omapi_waiter_object_t *waiter;
494 omapi_object_t *tmp = (omapi_object_t *)0;
496 if (!wo || wo -> type != omapi_type_waiter)
497 waiter = (omapi_waiter_object_t *)0;
498 else
499 waiter = (omapi_waiter_object_t *)wo;
501 FD_ZERO (&x);
503 /* First, see if the timeout has expired, and if so return. */
504 if (t) {
505 gettimeofday (&now, (struct timezone *)0);
506 cur_tv.tv_sec = now.tv_sec;
507 cur_tv.tv_usec = now.tv_usec;
508 if (now.tv_sec > t -> tv_sec ||
509 (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
510 return ISC_R_TIMEDOUT;
512 /* We didn't time out, so figure out how long until
513 we do. */
514 to.tv_sec = t -> tv_sec - now.tv_sec;
515 to.tv_usec = t -> tv_usec - now.tv_usec;
516 if (to.tv_usec < 0) {
517 to.tv_usec += 1000000;
518 to.tv_sec--;
521 /* It is possible for the timeout to get set larger than
522 the largest time select() is willing to accept.
523 Restricting the timeout to a maximum of one day should
524 work around this. -DPN. (Ref: Bug #416) */
525 if (to.tv_sec > (60 * 60 * 24))
526 to.tv_sec = 60 * 60 * 24;
529 /* If the object we're waiting on has reached completion,
530 return now. */
531 if (waiter && waiter -> ready)
532 return ISC_R_SUCCESS;
534 again:
535 /* If we have no I/O state, we can't proceed. */
536 if (!(io = omapi_io_states.next))
537 return ISC_R_NOMORE;
539 /* Set up the read and write masks. */
540 FD_ZERO (&r);
541 FD_ZERO (&w);
543 for (; io; io = io -> next) {
544 /* Check for a read socket. If we shouldn't be
545 trying to read for this I/O object, either there
546 won't be a readfd function, or it'll return -1. */
547 if (io -> readfd && io -> inner &&
548 (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
549 FD_SET (desc, &r);
550 if (desc > max)
551 max = desc;
554 /* Same deal for write fdets. */
555 if (io -> writefd && io -> inner &&
556 (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
557 FD_SET (desc, &w);
558 if (desc > max)
559 max = desc;
563 /* poll if all reader are dry */
564 now.tv_sec = 0;
565 now.tv_usec = 0;
566 rr=r;
567 ww=w;
568 xx=x;
570 /* poll once */
571 count = select(max + 1, &r, &w, &x, &now);
572 if (!count) {
573 /* We are dry now */
574 trigger_event(&rw_queue_empty);
575 /* Wait for a packet or a timeout... XXX */
576 r = rr;
577 w = ww;
578 x = xx;
579 count = select(max + 1, &r, &w, &x, t ? &to : NULL);
582 /* Get the current time... */
583 gettimeofday (&cur_tv, (struct timezone *)0);
585 /* We probably have a bad file descriptor. Figure out which one.
586 When we find it, call the reaper function on it, which will
587 maybe make it go away, and then try again. */
588 if (count < 0) {
589 struct timeval t0;
590 omapi_io_object_t *prev = (omapi_io_object_t *)0;
591 io = (omapi_io_object_t *)0;
592 if (omapi_io_states.next)
593 omapi_io_reference (&io, omapi_io_states.next, MDL);
595 while (io) {
596 omapi_object_t *obj;
597 FD_ZERO (&r);
598 FD_ZERO (&w);
599 t0.tv_sec = t0.tv_usec = 0;
601 if (io -> readfd && io -> inner &&
602 (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
603 FD_SET (desc, &r);
604 count = select (desc + 1, &r, &w, &x, &t0);
605 bogon:
606 if (count < 0) {
607 log_error ("Bad descriptor %d.", desc);
608 for (obj = (omapi_object_t *)io;
609 obj -> outer;
610 obj = obj -> outer)
612 for (; obj; obj = obj -> inner) {
613 omapi_value_t *ov;
614 int len;
615 const char *s;
616 ov = (omapi_value_t *)0;
617 omapi_get_value_str (obj,
618 (omapi_object_t *)0,
619 "name", &ov);
620 if (ov && ov -> value &&
621 (ov -> value -> type ==
622 omapi_datatype_string)) {
623 s = (char *)
624 ov -> value -> u.buffer.value;
625 len = ov -> value -> u.buffer.len;
626 } else {
627 s = "";
628 len = 0;
630 log_error ("Object %lx %s%s%.*s",
631 (unsigned long)obj,
632 obj -> type -> name,
633 len ? " " : "",
634 len, s);
635 if (len)
636 omapi_value_dereference (&ov, MDL);
638 (*(io -> reaper)) (io -> inner);
639 if (prev) {
640 omapi_io_dereference (&prev -> next, MDL);
641 if (io -> next)
642 omapi_io_reference (&prev -> next,
643 io -> next, MDL);
644 } else {
645 omapi_io_dereference
646 (&omapi_io_states.next, MDL);
647 if (io -> next)
648 omapi_io_reference
649 (&omapi_io_states.next,
650 io -> next, MDL);
652 omapi_io_dereference (&io, MDL);
653 goto again;
657 FD_ZERO (&r);
658 FD_ZERO (&w);
659 t0.tv_sec = t0.tv_usec = 0;
661 /* Same deal for write fdets. */
662 if (io -> writefd && io -> inner &&
663 (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
664 FD_SET (desc, &w);
665 count = select (desc + 1, &r, &w, &x, &t0);
666 if (count < 0)
667 goto bogon;
669 if (prev)
670 omapi_io_dereference (&prev, MDL);
671 omapi_io_reference (&prev, io, MDL);
672 omapi_io_dereference (&io, MDL);
673 if (prev -> next)
674 omapi_io_reference (&io, prev -> next, MDL);
676 if (prev)
677 omapi_io_dereference (&prev, MDL);
681 for (io = omapi_io_states.next; io; io = io -> next) {
682 if (!io -> inner)
683 continue;
684 omapi_object_reference (&tmp, io -> inner, MDL);
685 /* Check for a read descriptor, and if there is one,
686 see if we got input on that socket. */
687 if (io -> readfd &&
688 (desc = (*(io -> readfd)) (tmp)) >= 0) {
689 if (FD_ISSET (desc, &r))
690 ((*(io -> reader)) (tmp));
693 /* Same deal for write descriptors. */
694 if (io -> writefd &&
695 (desc = (*(io -> writefd)) (tmp)) >= 0)
697 if (FD_ISSET (desc, &w))
698 ((*(io -> writer)) (tmp));
700 omapi_object_dereference (&tmp, MDL);
703 /* Now check for I/O handles that are no longer valid,
704 and remove them from the list. */
705 prev = NULL;
706 io = NULL;
707 if (omapi_io_states.next != NULL) {
708 omapi_io_reference(&io, omapi_io_states.next, MDL);
710 while (io != NULL) {
711 if ((io->inner == NULL) ||
712 ((io->reaper != NULL) &&
713 ((io->reaper)(io->inner) != ISC_R_SUCCESS)))
716 omapi_io_object_t *tmp = NULL;
717 /* Save a reference to the next
718 pointer, if there is one. */
719 if (io->next != NULL) {
720 omapi_io_reference(&tmp, io->next, MDL);
721 omapi_io_dereference(&io->next, MDL);
723 if (prev != NULL) {
724 omapi_io_dereference(&prev->next, MDL);
725 if (tmp != NULL)
726 omapi_io_reference(&prev->next,
727 tmp, MDL);
728 } else {
729 omapi_io_dereference(&omapi_io_states.next,
730 MDL);
731 if (tmp != NULL)
732 omapi_io_reference
733 (&omapi_io_states.next,
734 tmp, MDL);
735 else
736 omapi_signal_in(
737 (omapi_object_t *)
738 &omapi_io_states,
739 "ready");
741 if (tmp != NULL)
742 omapi_io_dereference(&tmp, MDL);
744 } else {
746 if (prev != NULL) {
747 omapi_io_dereference(&prev, MDL);
749 omapi_io_reference(&prev, io, MDL);
753 * Equivalent to:
754 * io = io->next
755 * But using our reference counting voodoo.
757 next = NULL;
758 if (io->next != NULL) {
759 omapi_io_reference(&next, io->next, MDL);
761 omapi_io_dereference(&io, MDL);
762 if (next != NULL) {
763 omapi_io_reference(&io, next, MDL);
764 omapi_io_dereference(&next, MDL);
767 if (prev != NULL) {
768 omapi_io_dereference(&prev, MDL);
771 return ISC_R_SUCCESS;
774 isc_result_t omapi_io_set_value (omapi_object_t *h,
775 omapi_object_t *id,
776 omapi_data_string_t *name,
777 omapi_typed_data_t *value)
779 if (h -> type != omapi_type_io_object)
780 return DHCP_R_INVALIDARG;
782 if (h -> inner && h -> inner -> type -> set_value)
783 return (*(h -> inner -> type -> set_value))
784 (h -> inner, id, name, value);
785 return ISC_R_NOTFOUND;
788 isc_result_t omapi_io_get_value (omapi_object_t *h,
789 omapi_object_t *id,
790 omapi_data_string_t *name,
791 omapi_value_t **value)
793 if (h -> type != omapi_type_io_object)
794 return DHCP_R_INVALIDARG;
796 if (h -> inner && h -> inner -> type -> get_value)
797 return (*(h -> inner -> type -> get_value))
798 (h -> inner, id, name, value);
799 return ISC_R_NOTFOUND;
802 /* omapi_io_destroy (object, MDL);
804 * Find the requested IO [object] and remove it from the list of io
805 * states, causing the cleanup functions to destroy it. Note that we must
806 * hold a reference on the object while moving its ->next reference and
807 * removing the reference in the chain to the target object...otherwise it
808 * may be cleaned up from under us.
810 isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
812 omapi_io_object_t *obj = NULL, *p, *last = NULL, **holder;
814 if (h -> type != omapi_type_io_object)
815 return DHCP_R_INVALIDARG;
817 /* remove from the list of I/O states */
818 for (p = omapi_io_states.next; p; p = p -> next) {
819 if (p == (omapi_io_object_t *)h) {
820 omapi_io_reference (&obj, p, MDL);
822 if (last)
823 holder = &last -> next;
824 else
825 holder = &omapi_io_states.next;
827 omapi_io_dereference (holder, MDL);
829 if (obj -> next) {
830 omapi_io_reference (holder, obj -> next, MDL);
831 omapi_io_dereference (&obj -> next, MDL);
834 return omapi_io_dereference (&obj, MDL);
836 last = p;
839 return ISC_R_NOTFOUND;
842 isc_result_t omapi_io_signal_handler (omapi_object_t *h,
843 const char *name, va_list ap)
845 if (h -> type != omapi_type_io_object)
846 return DHCP_R_INVALIDARG;
848 if (h -> inner && h -> inner -> type -> signal_handler)
849 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
850 name, ap);
851 return ISC_R_NOTFOUND;
854 isc_result_t omapi_io_stuff_values (omapi_object_t *c,
855 omapi_object_t *id,
856 omapi_object_t *i)
858 if (i -> type != omapi_type_io_object)
859 return DHCP_R_INVALIDARG;
861 if (i -> inner && i -> inner -> type -> stuff_values)
862 return (*(i -> inner -> type -> stuff_values)) (c, id,
863 i -> inner);
864 return ISC_R_SUCCESS;
867 isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
868 const char *name, va_list ap)
870 omapi_waiter_object_t *waiter;
872 if (h -> type != omapi_type_waiter)
873 return DHCP_R_INVALIDARG;
875 if (!strcmp (name, "ready")) {
876 waiter = (omapi_waiter_object_t *)h;
877 waiter -> ready = 1;
878 waiter -> waitstatus = ISC_R_SUCCESS;
879 return ISC_R_SUCCESS;
882 if (!strcmp(name, "status")) {
883 waiter = (omapi_waiter_object_t *)h;
884 waiter->ready = 1;
885 waiter->waitstatus = va_arg(ap, isc_result_t);
886 return ISC_R_SUCCESS;
889 if (!strcmp (name, "disconnect")) {
890 waiter = (omapi_waiter_object_t *)h;
891 waiter -> ready = 1;
892 waiter -> waitstatus = DHCP_R_CONNRESET;
893 return ISC_R_SUCCESS;
896 if (h -> inner && h -> inner -> type -> signal_handler)
897 return (*(h -> inner -> type -> signal_handler)) (h -> inner,
898 name, ap);
899 return ISC_R_NOTFOUND;
902 /** @brief calls a given function on every object
904 * @param func function to be called
905 * @param p parameter to be passed to each function instance
907 * @return result (ISC_R_SUCCESS if successful, error code otherwise)
909 isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *,
910 void *),
911 void *p)
913 omapi_io_object_t *io = NULL;
914 isc_result_t status;
915 omapi_io_object_t *next = NULL;
918 * This just calls func on every inner object on the list. It would
919 * be much simpler in general case, but one of the operations could be
920 * release of the objects. Therefore we need to ref count the io and
921 * io->next pointers.
924 if (omapi_io_states.next) {
925 omapi_object_reference((omapi_object_t**)&io,
926 (omapi_object_t*)omapi_io_states.next,
927 MDL);
930 while(io) {
931 /* If there's a next object, save it */
932 if (io->next) {
933 omapi_object_reference((omapi_object_t**)&next,
934 (omapi_object_t*)io->next, MDL);
936 if (io->inner) {
937 status = (*func) (io->inner, p);
938 if (status != ISC_R_SUCCESS) {
939 /* Something went wrong. Let's stop using io & next pointer
940 * and bail out */
941 omapi_object_dereference((omapi_object_t**)&io, MDL);
942 if (next) {
943 omapi_object_dereference((omapi_object_t**)&next, MDL);
945 return status;
948 /* Update the io pointer and free the next pointer */
949 omapi_object_dereference((omapi_object_t**)&io, MDL);
950 if (next) {
951 omapi_object_reference((omapi_object_t**)&io,
952 (omapi_object_t*)next,
953 MDL);
954 omapi_object_dereference((omapi_object_t**)&next, MDL);
959 * The only way to get here is when next is NULL. There's no need
960 * to dereference it.
962 return ISC_R_SUCCESS;