6 * Copyright (c) 2004,2007-2009,2013 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1999-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
37 #include <omapip/omapip_p.h>
40 static omapi_io_object_t omapi_io_states
;
41 struct timeval cur_tv
;
43 struct eventqueue
*rw_queue_empty
;
45 OMAPI_OBJECT_ALLOC (omapi_io
,
46 omapi_io_object_t
, omapi_type_io_object
)
47 OMAPI_OBJECT_ALLOC (omapi_waiter
,
48 omapi_waiter_object_t
, omapi_type_waiter
)
51 register_eventhandler(struct eventqueue
**queue
, void (*handler
)(void *))
53 struct eventqueue
*t
, *q
;
55 /* traverse to end of list */
57 for (q
= *queue
; q
; q
= q
->next
) {
58 if (q
->handler
== handler
)
59 return; /* handler already registered */
63 q
= ((struct eventqueue
*)dmalloc(sizeof(struct eventqueue
), MDL
));
65 log_fatal("register_eventhandler: no memory!");
66 memset(q
, 0, sizeof *q
);
76 unregister_eventhandler(struct eventqueue
**queue
, void (*handler
)(void *))
78 struct eventqueue
*t
, *q
;
80 /* traverse to end of list */
82 for (q
= *queue
; q
; q
= q
->next
) {
83 if (q
->handler
== handler
) {
88 dfree(q
, MDL
); /* Don't access q after this!*/
97 trigger_event(struct eventqueue
**queue
)
101 for (q
=*queue
; q
; q
=q
->next
) {
108 * Callback routine to connect the omapi I/O object and socket with
109 * the isc socket code. The isc socket code will call this routine
110 * which will then call the correct local routine to process the bytes.
112 * Currently we are always willing to read more data, this should be modified
113 * so that on connections we don't read more if we already have enough.
115 * If we have more bytes to write we ask the library to call us when
116 * we can write more. If we indicate we don't have more to write we need
117 * to poke the library via isc_socket_fdwatchpoke.
121 * sockdelete indicates if we are deleting the socket or leaving it in place
122 * 1 is delete, 0 is leave in place
126 omapi_iscsock_cb(isc_task_t
*task
,
127 isc_socket_t
*socket
,
131 omapi_io_object_t
*obj
;
134 /* Get the current time... */
135 gettimeofday (&cur_tv
, (struct timezone
*)0);
137 /* isc socket stuff */
140 * walk through the io states list, if our object is on there
141 * service it. if not ignore it.
143 for (obj
= omapi_io_states
.next
;
144 (obj
!= NULL
) && (obj
->next
!= NULL
);
153 /* Not much to be done if we have the wrong type of object. */
154 if (((omapi_object_t
*)cbarg
) -> type
!= omapi_type_io_object
) {
155 log_fatal ("Incorrect object type, must be of type io_object");
157 obj
= (omapi_io_object_t
*)cbarg
;
160 * If the object is marked as closed don't try and process
161 * anything just indicate that we don't want any more.
163 * This should be a temporary fix until we arrange to properly
166 if (obj
->closed
== ISC_TRUE
) {
171 if ((flags
== ISC_SOCKFDWATCH_READ
) &&
172 (obj
->reader
!= NULL
) &&
173 (obj
->inner
!= NULL
)) {
174 status
= obj
->reader(obj
->inner
);
176 * If we are shutting down (basically tried to
177 * read and got no bytes) we don't need to try
180 if (status
== ISC_R_SHUTTINGDOWN
)
182 /* Otherwise We always ask for more when reading */
184 } else if ((flags
== ISC_SOCKFDWATCH_WRITE
) &&
185 (obj
->writer
!= NULL
) &&
186 (obj
->inner
!= NULL
)) {
187 status
= obj
->writer(obj
->inner
);
188 /* If the writer has more to write they should return
189 * ISC_R_INPROGRESS */
190 if (status
== ISC_R_INPROGRESS
) {
196 * We get here if we either had an error (inconsistent
197 * structures etc) or no more to write, tell the socket
198 * lib we don't have more to do right now.
203 /* Register an I/O handle so that we can do asynchronous I/O on it. */
205 isc_result_t
omapi_register_io_object (omapi_object_t
*h
,
206 int (*readfd
) (omapi_object_t
*),
207 int (*writefd
) (omapi_object_t
*),
208 isc_result_t (*reader
)
210 isc_result_t (*writer
)
212 isc_result_t (*reaper
)
216 omapi_io_object_t
*obj
, *p
;
217 int fd_flags
= 0, fd
= 0;
219 /* omapi_io_states is a static object. If its reference count
220 is zero, this is the first I/O handle to be registered, so
221 we need to initialize it. Because there is no inner or outer
222 pointer on this object, and we're setting its refcnt to 1, it
223 will never be freed. */
224 if (!omapi_io_states
.refcnt
) {
225 omapi_io_states
.refcnt
= 1;
226 omapi_io_states
.type
= omapi_type_io_object
;
229 obj
= (omapi_io_object_t
*)0;
230 status
= omapi_io_allocate (&obj
, MDL
);
231 if (status
!= ISC_R_SUCCESS
)
233 obj
->closed
= ISC_FALSE
; /* mark as open */
235 status
= omapi_object_reference (&obj
-> inner
, h
, MDL
);
236 if (status
!= ISC_R_SUCCESS
) {
237 omapi_io_dereference (&obj
, MDL
);
241 status
= omapi_object_reference (&h
-> outer
,
242 (omapi_object_t
*)obj
, MDL
);
243 if (status
!= ISC_R_SUCCESS
) {
244 omapi_io_dereference (&obj
, MDL
);
249 * Attach the I/O object to the isc socket library via the
250 * fdwatch function. This allows the socket library to watch
251 * over a socket that we built. If there are both a read and
252 * a write socket we asssume they are the same socket.
256 fd_flags
|= ISC_SOCKFDWATCH_READ
;
261 fd_flags
|= ISC_SOCKFDWATCH_WRITE
;
266 status
= isc_socket_fdwatchcreate(dhcp_gbl_ctx
.socketmgr
,
272 if (status
!= ISC_R_SUCCESS
) {
273 log_error("Unable to register fd with library %s",
274 isc_result_totext(status
));
277 /* is this the cleanup we need? */
278 omapi_object_dereference(&h
->outer
, MDL
);
279 omapi_io_dereference (&obj
, MDL
);
285 /* Find the last I/O state, if there are any. */
286 for (p
= omapi_io_states
.next
;
287 p
&& p
-> next
; p
= p
-> next
)
290 omapi_io_reference (&p
-> next
, obj
, MDL
);
292 omapi_io_reference (&omapi_io_states
.next
, obj
, MDL
);
294 obj
-> readfd
= readfd
;
295 obj
-> writefd
= writefd
;
296 obj
-> reader
= reader
;
297 obj
-> writer
= writer
;
298 obj
-> reaper
= reaper
;
300 omapi_io_dereference(&obj
, MDL
);
301 return ISC_R_SUCCESS
;
305 * ReRegister an I/O handle so that we can do asynchronous I/O on it.
306 * If the handle doesn't exist we call the register routine to build it.
307 * If it does exist we change the functions associated with it, and
308 * repoke the fd code to make it happy. Neither the objects nor the
309 * fd are allowed to have changed.
312 isc_result_t
omapi_reregister_io_object (omapi_object_t
*h
,
313 int (*readfd
) (omapi_object_t
*),
314 int (*writefd
) (omapi_object_t
*),
315 isc_result_t (*reader
)
317 isc_result_t (*writer
)
319 isc_result_t (*reaper
)
322 omapi_io_object_t
*obj
;
325 if ((!h
-> outer
) || (h
-> outer
-> type
!= omapi_type_io_object
)) {
327 * If we don't have an object or if the type isn't what
328 * we expect do the normal registration (which will overwrite
329 * an incorrect type, that's what we did historically, may
330 * want to change that)
332 return (omapi_register_io_object (h
, readfd
, writefd
,
333 reader
, writer
, reaper
));
336 /* We have an io object of the correct type, try to update it */
338 /* Should we validate that the fd matches the previous one?
339 * It's suppossed to, that's a requirement, don't bother yet */
341 obj
= (omapi_io_object_t
*)h
->outer
;
343 obj
->readfd
= readfd
;
344 obj
->writefd
= writefd
;
345 obj
->reader
= reader
;
346 obj
->writer
= writer
;
347 obj
->reaper
= reaper
;
350 fd_flags
|= ISC_SOCKFDWATCH_READ
;
354 fd_flags
|= ISC_SOCKFDWATCH_WRITE
;
357 isc_socket_fdwatchpoke(obj
->fd
, fd_flags
);
359 return (ISC_R_SUCCESS
);
362 isc_result_t
omapi_unregister_io_object (omapi_object_t
*h
)
364 omapi_io_object_t
*obj
, *ph
;
366 omapi_io_object_t
*p
, *last
;
369 if (!h
-> outer
|| h
-> outer
-> type
!= omapi_type_io_object
)
370 return DHCP_R_INVALIDARG
;
371 obj
= (omapi_io_object_t
*)h
-> outer
;
372 ph
= (omapi_io_object_t
*)0;
373 omapi_io_reference (&ph
, obj
, MDL
);
377 * For now we leave this out. We can't clean up the isc socket
378 * structure cleanly yet so we need to leave the io object in place.
379 * By leaving it on the io states list we avoid it being freed.
380 * We also mark it as closed to avoid using it.
383 /* remove from the list of I/O states */
384 last
= &omapi_io_states
;
385 for (p
= omapi_io_states
.next
; p
; p
= p
-> next
) {
387 omapi_io_dereference (&last
-> next
, MDL
);
388 omapi_io_reference (&last
-> next
, p
-> next
, MDL
);
394 omapi_io_dereference (&obj
-> next
, MDL
);
398 if (obj
-> outer
-> inner
== (omapi_object_t
*)obj
)
399 omapi_object_dereference (&obj
-> outer
-> inner
,
401 omapi_object_dereference (&obj
-> outer
, MDL
);
403 omapi_object_dereference (&obj
-> inner
, MDL
);
404 omapi_object_dereference (&h
-> outer
, MDL
);
407 /* remove isc socket associations */
408 if (obj
->fd
!= NULL
) {
409 isc_socket_cancel(obj
->fd
, dhcp_gbl_ctx
.task
,
411 isc_socket_detach(&obj
->fd
);
414 obj
->closed
= ISC_TRUE
;
417 omapi_io_dereference (&ph
, MDL
);
418 return ISC_R_SUCCESS
;
421 isc_result_t
omapi_dispatch (struct timeval
*t
)
423 return omapi_wait_for_completion ((omapi_object_t
*)&omapi_io_states
,
427 isc_result_t
omapi_wait_for_completion (omapi_object_t
*object
,
431 omapi_waiter_object_t
*waiter
;
432 omapi_object_t
*inner
;
435 waiter
= (omapi_waiter_object_t
*)0;
436 status
= omapi_waiter_allocate (&waiter
, MDL
);
437 if (status
!= ISC_R_SUCCESS
)
440 /* Paste the waiter object onto the inner object we're
442 for (inner
= object
; inner
-> inner
; inner
= inner
-> inner
)
445 status
= omapi_object_reference (&waiter
-> outer
, inner
, MDL
);
446 if (status
!= ISC_R_SUCCESS
) {
447 omapi_waiter_dereference (&waiter
, MDL
);
451 status
= omapi_object_reference (&inner
-> inner
,
452 (omapi_object_t
*)waiter
,
454 if (status
!= ISC_R_SUCCESS
) {
455 omapi_waiter_dereference (&waiter
, MDL
);
459 waiter
= (omapi_waiter_object_t
*)0;
462 status
= omapi_one_dispatch ((omapi_object_t
*)waiter
, t
);
463 if (status
!= ISC_R_SUCCESS
)
465 } while (!waiter
|| !waiter
-> ready
);
467 if (waiter
-> outer
) {
468 if (waiter
-> outer
-> inner
) {
469 omapi_object_dereference (&waiter
-> outer
-> inner
,
472 omapi_object_reference
473 (&waiter
-> outer
-> inner
,
474 waiter
-> inner
, MDL
);
476 omapi_object_dereference (&waiter
-> outer
, MDL
);
479 omapi_object_dereference (&waiter
-> inner
, MDL
);
481 status
= waiter
-> waitstatus
;
482 omapi_waiter_dereference (&waiter
, MDL
);
486 isc_result_t
omapi_one_dispatch (omapi_object_t
*wo
,
489 fd_set r
, w
, x
, rr
, ww
, xx
;
493 struct timeval now
, to
;
494 omapi_io_object_t
*io
, *prev
, *next
;
495 omapi_waiter_object_t
*waiter
;
496 omapi_object_t
*tmp
= (omapi_object_t
*)0;
498 if (!wo
|| wo
-> type
!= omapi_type_waiter
)
499 waiter
= (omapi_waiter_object_t
*)0;
501 waiter
= (omapi_waiter_object_t
*)wo
;
505 /* First, see if the timeout has expired, and if so return. */
507 gettimeofday (&now
, (struct timezone
*)0);
508 cur_tv
.tv_sec
= now
.tv_sec
;
509 cur_tv
.tv_usec
= now
.tv_usec
;
510 if (now
.tv_sec
> t
-> tv_sec
||
511 (now
.tv_sec
== t
-> tv_sec
&& now
.tv_usec
>= t
-> tv_usec
))
512 return ISC_R_TIMEDOUT
;
514 /* We didn't time out, so figure out how long until
516 to
.tv_sec
= t
-> tv_sec
- now
.tv_sec
;
517 to
.tv_usec
= t
-> tv_usec
- now
.tv_usec
;
518 if (to
.tv_usec
< 0) {
519 to
.tv_usec
+= 1000000;
523 /* It is possible for the timeout to get set larger than
524 the largest time select() is willing to accept.
525 Restricting the timeout to a maximum of one day should
526 work around this. -DPN. (Ref: Bug #416) */
527 if (to
.tv_sec
> (60 * 60 * 24))
528 to
.tv_sec
= 60 * 60 * 24;
531 /* If the object we're waiting on has reached completion,
533 if (waiter
&& waiter
-> ready
)
534 return ISC_R_SUCCESS
;
537 /* If we have no I/O state, we can't proceed. */
538 if (!(io
= omapi_io_states
.next
))
541 /* Set up the read and write masks. */
545 for (; io
; io
= io
-> next
) {
546 /* Check for a read socket. If we shouldn't be
547 trying to read for this I/O object, either there
548 won't be a readfd function, or it'll return -1. */
549 if (io
-> readfd
&& io
-> inner
&&
550 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
556 /* Same deal for write fdets. */
557 if (io
-> writefd
&& io
-> inner
&&
558 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0) {
565 /* poll if all reader are dry */
573 count
= select(max
+ 1, &r
, &w
, &x
, &now
);
576 trigger_event(&rw_queue_empty
);
577 /* Wait for a packet or a timeout... XXX */
581 count
= select(max
+ 1, &r
, &w
, &x
, t
? &to
: NULL
);
584 /* Get the current time... */
585 gettimeofday (&cur_tv
, (struct timezone
*)0);
587 /* We probably have a bad file descriptor. Figure out which one.
588 When we find it, call the reaper function on it, which will
589 maybe make it go away, and then try again. */
592 omapi_io_object_t
*prev
= (omapi_io_object_t
*)0;
593 io
= (omapi_io_object_t
*)0;
594 if (omapi_io_states
.next
)
595 omapi_io_reference (&io
, omapi_io_states
.next
, MDL
);
601 t0
.tv_sec
= t0
.tv_usec
= 0;
603 if (io
-> readfd
&& io
-> inner
&&
604 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
606 count
= select (desc
+ 1, &r
, &w
, &x
, &t0
);
609 log_error ("Bad descriptor %d.", desc
);
610 for (obj
= (omapi_object_t
*)io
;
614 for (; obj
; obj
= obj
-> inner
) {
618 ov
= (omapi_value_t
*)0;
619 omapi_get_value_str (obj
,
622 if (ov
&& ov
-> value
&&
623 (ov
-> value
-> type
==
624 omapi_datatype_string
)) {
626 ov
-> value
-> u
.buffer
.value
;
627 len
= ov
-> value
-> u
.buffer
.len
;
632 log_error ("Object %lx %s%s%.*s",
638 omapi_value_dereference (&ov
, MDL
);
640 (*(io
-> reaper
)) (io
-> inner
);
642 omapi_io_dereference (&prev
-> next
, MDL
);
644 omapi_io_reference (&prev
-> next
,
648 (&omapi_io_states
.next
, MDL
);
651 (&omapi_io_states
.next
,
654 omapi_io_dereference (&io
, MDL
);
661 t0
.tv_sec
= t0
.tv_usec
= 0;
663 /* Same deal for write fdets. */
664 if (io
-> writefd
&& io
-> inner
&&
665 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0) {
667 count
= select (desc
+ 1, &r
, &w
, &x
, &t0
);
672 omapi_io_dereference (&prev
, MDL
);
673 omapi_io_reference (&prev
, io
, MDL
);
674 omapi_io_dereference (&io
, MDL
);
676 omapi_io_reference (&io
, prev
-> next
, MDL
);
679 omapi_io_dereference (&prev
, MDL
);
683 for (io
= omapi_io_states
.next
; io
; io
= io
-> next
) {
686 omapi_object_reference (&tmp
, io
-> inner
, MDL
);
687 /* Check for a read descriptor, and if there is one,
688 see if we got input on that socket. */
690 (desc
= (*(io
-> readfd
)) (tmp
)) >= 0) {
691 if (FD_ISSET (desc
, &r
))
692 ((*(io
-> reader
)) (tmp
));
695 /* Same deal for write descriptors. */
697 (desc
= (*(io
-> writefd
)) (tmp
)) >= 0)
699 if (FD_ISSET (desc
, &w
))
700 ((*(io
-> writer
)) (tmp
));
702 omapi_object_dereference (&tmp
, MDL
);
705 /* Now check for I/O handles that are no longer valid,
706 and remove them from the list. */
709 if (omapi_io_states
.next
!= NULL
) {
710 omapi_io_reference(&io
, omapi_io_states
.next
, MDL
);
713 if ((io
->inner
== NULL
) ||
714 ((io
->reaper
!= NULL
) &&
715 ((io
->reaper
)(io
->inner
) != ISC_R_SUCCESS
)))
718 omapi_io_object_t
*tmp
= NULL
;
719 /* Save a reference to the next
720 pointer, if there is one. */
721 if (io
->next
!= NULL
) {
722 omapi_io_reference(&tmp
, io
->next
, MDL
);
723 omapi_io_dereference(&io
->next
, MDL
);
726 omapi_io_dereference(&prev
->next
, MDL
);
728 omapi_io_reference(&prev
->next
,
731 omapi_io_dereference(&omapi_io_states
.next
,
735 (&omapi_io_states
.next
,
744 omapi_io_dereference(&tmp
, MDL
);
749 omapi_io_dereference(&prev
, MDL
);
751 omapi_io_reference(&prev
, io
, MDL
);
757 * But using our reference counting voodoo.
760 if (io
->next
!= NULL
) {
761 omapi_io_reference(&next
, io
->next
, MDL
);
763 omapi_io_dereference(&io
, MDL
);
765 omapi_io_reference(&io
, next
, MDL
);
766 omapi_io_dereference(&next
, MDL
);
770 omapi_io_dereference(&prev
, MDL
);
773 return ISC_R_SUCCESS
;
776 isc_result_t
omapi_io_set_value (omapi_object_t
*h
,
778 omapi_data_string_t
*name
,
779 omapi_typed_data_t
*value
)
781 if (h
-> type
!= omapi_type_io_object
)
782 return DHCP_R_INVALIDARG
;
784 if (h
-> inner
&& h
-> inner
-> type
-> set_value
)
785 return (*(h
-> inner
-> type
-> set_value
))
786 (h
-> inner
, id
, name
, value
);
787 return ISC_R_NOTFOUND
;
790 isc_result_t
omapi_io_get_value (omapi_object_t
*h
,
792 omapi_data_string_t
*name
,
793 omapi_value_t
**value
)
795 if (h
-> type
!= omapi_type_io_object
)
796 return DHCP_R_INVALIDARG
;
798 if (h
-> inner
&& h
-> inner
-> type
-> get_value
)
799 return (*(h
-> inner
-> type
-> get_value
))
800 (h
-> inner
, id
, name
, value
);
801 return ISC_R_NOTFOUND
;
804 /* omapi_io_destroy (object, MDL);
806 * Find the requested IO [object] and remove it from the list of io
807 * states, causing the cleanup functions to destroy it. Note that we must
808 * hold a reference on the object while moving its ->next reference and
809 * removing the reference in the chain to the target object...otherwise it
810 * may be cleaned up from under us.
812 isc_result_t
omapi_io_destroy (omapi_object_t
*h
, const char *file
, int line
)
814 omapi_io_object_t
*obj
= NULL
, *p
, *last
= NULL
, **holder
;
816 if (h
-> type
!= omapi_type_io_object
)
817 return DHCP_R_INVALIDARG
;
819 /* remove from the list of I/O states */
820 for (p
= omapi_io_states
.next
; p
; p
= p
-> next
) {
821 if (p
== (omapi_io_object_t
*)h
) {
822 omapi_io_reference (&obj
, p
, MDL
);
825 holder
= &last
-> next
;
827 holder
= &omapi_io_states
.next
;
829 omapi_io_dereference (holder
, MDL
);
832 omapi_io_reference (holder
, obj
-> next
, MDL
);
833 omapi_io_dereference (&obj
-> next
, MDL
);
836 return omapi_io_dereference (&obj
, MDL
);
841 return ISC_R_NOTFOUND
;
844 isc_result_t
omapi_io_signal_handler (omapi_object_t
*h
,
845 const char *name
, va_list ap
)
847 if (h
-> type
!= omapi_type_io_object
)
848 return DHCP_R_INVALIDARG
;
850 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
851 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
853 return ISC_R_NOTFOUND
;
856 isc_result_t
omapi_io_stuff_values (omapi_object_t
*c
,
860 if (i
-> type
!= omapi_type_io_object
)
861 return DHCP_R_INVALIDARG
;
863 if (i
-> inner
&& i
-> inner
-> type
-> stuff_values
)
864 return (*(i
-> inner
-> type
-> stuff_values
)) (c
, id
,
866 return ISC_R_SUCCESS
;
869 isc_result_t
omapi_waiter_signal_handler (omapi_object_t
*h
,
870 const char *name
, va_list ap
)
872 omapi_waiter_object_t
*waiter
;
874 if (h
-> type
!= omapi_type_waiter
)
875 return DHCP_R_INVALIDARG
;
877 if (!strcmp (name
, "ready")) {
878 waiter
= (omapi_waiter_object_t
*)h
;
880 waiter
-> waitstatus
= ISC_R_SUCCESS
;
881 return ISC_R_SUCCESS
;
884 if (!strcmp(name
, "status")) {
885 waiter
= (omapi_waiter_object_t
*)h
;
887 waiter
->waitstatus
= va_arg(ap
, isc_result_t
);
888 return ISC_R_SUCCESS
;
891 if (!strcmp (name
, "disconnect")) {
892 waiter
= (omapi_waiter_object_t
*)h
;
894 waiter
-> waitstatus
= DHCP_R_CONNRESET
;
895 return ISC_R_SUCCESS
;
898 if (h
-> inner
&& h
-> inner
-> type
-> signal_handler
)
899 return (*(h
-> inner
-> type
-> signal_handler
)) (h
-> inner
,
901 return ISC_R_NOTFOUND
;
904 /** @brief calls a given function on every object
906 * @param func function to be called
907 * @param p parameter to be passed to each function instance
909 * @return result (ISC_R_SUCCESS if successful, error code otherwise)
911 isc_result_t
omapi_io_state_foreach (isc_result_t (*func
) (omapi_object_t
*,
915 omapi_io_object_t
*io
= NULL
;
917 omapi_io_object_t
*next
= NULL
;
920 * This just calls func on every inner object on the list. It would
921 * be much simpler in general case, but one of the operations could be
922 * release of the objects. Therefore we need to ref count the io and
926 if (omapi_io_states
.next
) {
927 omapi_object_reference((omapi_object_t
**)&io
,
928 (omapi_object_t
*)omapi_io_states
.next
,
933 /* If there's a next object, save it */
935 omapi_object_reference((omapi_object_t
**)&next
,
936 (omapi_object_t
*)io
->next
, MDL
);
939 status
= (*func
) (io
->inner
, p
);
940 if (status
!= ISC_R_SUCCESS
) {
941 /* Something went wrong. Let's stop using io & next pointer
943 omapi_object_dereference((omapi_object_t
**)&io
, MDL
);
945 omapi_object_dereference((omapi_object_t
**)&next
, MDL
);
950 /* Update the io pointer and free the next pointer */
951 omapi_object_dereference((omapi_object_t
**)&io
, MDL
);
953 omapi_object_reference((omapi_object_t
**)&io
,
954 (omapi_object_t
*)next
,
956 omapi_object_dereference((omapi_object_t
**)&next
, MDL
);
961 * The only way to get here is when next is NULL. There's no need
964 return ISC_R_SUCCESS
;