1 /* $NetBSD: dispatch.c,v 1.4 2014/07/12 12:09:37 spz Exp $ */
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.
24 * Redwood City, CA 94063
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 $");
35 #include <omapip/omapip_p.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
)
49 register_eventhandler(struct eventqueue
**queue
, void (*handler
)(void *))
51 struct eventqueue
*t
, *q
;
53 /* traverse to end of list */
55 for (q
= *queue
; q
; q
= q
->next
) {
56 if (q
->handler
== handler
)
57 return; /* handler already registered */
61 q
= ((struct eventqueue
*)dmalloc(sizeof(struct eventqueue
), MDL
));
63 log_fatal("register_eventhandler: no memory!");
64 memset(q
, 0, sizeof *q
);
74 unregister_eventhandler(struct eventqueue
**queue
, void (*handler
)(void *))
76 struct eventqueue
*t
, *q
;
78 /* traverse to end of list */
80 for (q
= *queue
; q
; q
= q
->next
) {
81 if (q
->handler
== handler
) {
86 dfree(q
, MDL
); /* Don't access q after this!*/
95 trigger_event(struct eventqueue
**queue
)
99 for (q
=*queue
; q
; q
=q
->next
) {
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
124 omapi_iscsock_cb(isc_task_t
*task
,
125 isc_socket_t
*socket
,
129 omapi_io_object_t
*obj
;
132 /* Get the current time... */
133 gettimeofday (&cur_tv
, (struct timezone
*)0);
135 /* isc socket stuff */
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
);
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
164 if (obj
->closed
== ISC_TRUE
) {
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
178 if (status
== ISC_R_SHUTTINGDOWN
)
180 /* Otherwise We always ask for more when reading */
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
) {
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.
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
)
208 isc_result_t (*writer
)
210 isc_result_t (*reaper
)
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
)
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
);
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
);
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.
254 fd_flags
|= ISC_SOCKFDWATCH_READ
;
259 fd_flags
|= ISC_SOCKFDWATCH_WRITE
;
264 status
= isc_socket_fdwatchcreate(dhcp_gbl_ctx
.socketmgr
,
270 if (status
!= ISC_R_SUCCESS
) {
271 log_error("Unable to register fd with library %s",
272 isc_result_totext(status
));
275 /* is this the cleanup we need? */
276 omapi_object_dereference(&h
->outer
, MDL
);
277 omapi_io_dereference (&obj
, MDL
);
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
)
288 omapi_io_reference (&p
-> next
, obj
, MDL
);
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
)
315 isc_result_t (*writer
)
317 isc_result_t (*reaper
)
320 omapi_io_object_t
*obj
;
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 */
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
;
348 fd_flags
|= ISC_SOCKFDWATCH_READ
;
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
;
364 omapi_io_object_t
*p
, *last
;
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
);
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
) {
385 omapi_io_dereference (&last
-> next
, MDL
);
386 omapi_io_reference (&last
-> next
, p
-> next
, MDL
);
392 omapi_io_dereference (&obj
-> next
, MDL
);
396 if (obj
-> outer
-> inner
== (omapi_object_t
*)obj
)
397 omapi_object_dereference (&obj
-> outer
-> inner
,
399 omapi_object_dereference (&obj
-> outer
, MDL
);
401 omapi_object_dereference (&obj
-> inner
, MDL
);
402 omapi_object_dereference (&h
-> outer
, MDL
);
405 /* remove isc socket associations */
406 if (obj
->fd
!= NULL
) {
407 isc_socket_cancel(obj
->fd
, dhcp_gbl_ctx
.task
,
409 isc_socket_detach(&obj
->fd
);
412 obj
->closed
= ISC_TRUE
;
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
,
429 omapi_waiter_object_t
*waiter
;
430 omapi_object_t
*inner
;
433 waiter
= (omapi_waiter_object_t
*)0;
434 status
= omapi_waiter_allocate (&waiter
, MDL
);
435 if (status
!= ISC_R_SUCCESS
)
438 /* Paste the waiter object onto the inner object we're
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
);
449 status
= omapi_object_reference (&inner
-> inner
,
450 (omapi_object_t
*)waiter
,
452 if (status
!= ISC_R_SUCCESS
) {
453 omapi_waiter_dereference (&waiter
, MDL
);
457 waiter
= (omapi_waiter_object_t
*)0;
460 status
= omapi_one_dispatch ((omapi_object_t
*)waiter
, t
);
461 if (status
!= ISC_R_SUCCESS
)
463 } while (!waiter
|| !waiter
-> ready
);
465 if (waiter
-> outer
) {
466 if (waiter
-> outer
-> inner
) {
467 omapi_object_dereference (&waiter
-> outer
-> inner
,
470 omapi_object_reference
471 (&waiter
-> outer
-> inner
,
472 waiter
-> inner
, MDL
);
474 omapi_object_dereference (&waiter
-> outer
, MDL
);
477 omapi_object_dereference (&waiter
-> inner
, MDL
);
479 status
= waiter
-> waitstatus
;
480 omapi_waiter_dereference (&waiter
, MDL
);
484 isc_result_t
omapi_one_dispatch (omapi_object_t
*wo
,
487 fd_set r
, w
, x
, rr
, ww
, xx
;
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;
499 waiter
= (omapi_waiter_object_t
*)wo
;
503 /* First, see if the timeout has expired, and if so return. */
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
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;
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,
531 if (waiter
&& waiter
-> ready
)
532 return ISC_R_SUCCESS
;
535 /* If we have no I/O state, we can't proceed. */
536 if (!(io
= omapi_io_states
.next
))
539 /* Set up the read and write masks. */
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) {
554 /* Same deal for write fdets. */
555 if (io
-> writefd
&& io
-> inner
&&
556 (desc
= (*(io
-> writefd
)) (io
-> inner
)) >= 0) {
563 /* poll if all reader are dry */
571 count
= select(max
+ 1, &r
, &w
, &x
, &now
);
574 trigger_event(&rw_queue_empty
);
575 /* Wait for a packet or a timeout... XXX */
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. */
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
);
599 t0
.tv_sec
= t0
.tv_usec
= 0;
601 if (io
-> readfd
&& io
-> inner
&&
602 (desc
= (*(io
-> readfd
)) (io
-> inner
)) >= 0) {
604 count
= select (desc
+ 1, &r
, &w
, &x
, &t0
);
607 log_error ("Bad descriptor %d.", desc
);
608 for (obj
= (omapi_object_t
*)io
;
612 for (; obj
; obj
= obj
-> inner
) {
616 ov
= (omapi_value_t
*)0;
617 omapi_get_value_str (obj
,
620 if (ov
&& ov
-> value
&&
621 (ov
-> value
-> type
==
622 omapi_datatype_string
)) {
624 ov
-> value
-> u
.buffer
.value
;
625 len
= ov
-> value
-> u
.buffer
.len
;
630 log_error ("Object %lx %s%s%.*s",
636 omapi_value_dereference (&ov
, MDL
);
638 (*(io
-> reaper
)) (io
-> inner
);
640 omapi_io_dereference (&prev
-> next
, MDL
);
642 omapi_io_reference (&prev
-> next
,
646 (&omapi_io_states
.next
, MDL
);
649 (&omapi_io_states
.next
,
652 omapi_io_dereference (&io
, MDL
);
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) {
665 count
= select (desc
+ 1, &r
, &w
, &x
, &t0
);
670 omapi_io_dereference (&prev
, MDL
);
671 omapi_io_reference (&prev
, io
, MDL
);
672 omapi_io_dereference (&io
, MDL
);
674 omapi_io_reference (&io
, prev
-> next
, MDL
);
677 omapi_io_dereference (&prev
, MDL
);
681 for (io
= omapi_io_states
.next
; io
; io
= io
-> next
) {
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. */
688 (desc
= (*(io
-> readfd
)) (tmp
)) >= 0) {
689 if (FD_ISSET (desc
, &r
))
690 ((*(io
-> reader
)) (tmp
));
693 /* Same deal for write descriptors. */
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. */
707 if (omapi_io_states
.next
!= NULL
) {
708 omapi_io_reference(&io
, omapi_io_states
.next
, MDL
);
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
);
724 omapi_io_dereference(&prev
->next
, MDL
);
726 omapi_io_reference(&prev
->next
,
729 omapi_io_dereference(&omapi_io_states
.next
,
733 (&omapi_io_states
.next
,
742 omapi_io_dereference(&tmp
, MDL
);
747 omapi_io_dereference(&prev
, MDL
);
749 omapi_io_reference(&prev
, io
, MDL
);
755 * But using our reference counting voodoo.
758 if (io
->next
!= NULL
) {
759 omapi_io_reference(&next
, io
->next
, MDL
);
761 omapi_io_dereference(&io
, MDL
);
763 omapi_io_reference(&io
, next
, MDL
);
764 omapi_io_dereference(&next
, MDL
);
768 omapi_io_dereference(&prev
, MDL
);
771 return ISC_R_SUCCESS
;
774 isc_result_t
omapi_io_set_value (omapi_object_t
*h
,
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
,
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
);
823 holder
= &last
-> next
;
825 holder
= &omapi_io_states
.next
;
827 omapi_io_dereference (holder
, MDL
);
830 omapi_io_reference (holder
, obj
-> next
, MDL
);
831 omapi_io_dereference (&obj
-> next
, MDL
);
834 return omapi_io_dereference (&obj
, MDL
);
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
,
851 return ISC_R_NOTFOUND
;
854 isc_result_t
omapi_io_stuff_values (omapi_object_t
*c
,
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
,
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
;
878 waiter
-> waitstatus
= ISC_R_SUCCESS
;
879 return ISC_R_SUCCESS
;
882 if (!strcmp(name
, "status")) {
883 waiter
= (omapi_waiter_object_t
*)h
;
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
;
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
,
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
*,
913 omapi_io_object_t
*io
= NULL
;
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
924 if (omapi_io_states
.next
) {
925 omapi_object_reference((omapi_object_t
**)&io
,
926 (omapi_object_t
*)omapi_io_states
.next
,
931 /* If there's a next object, save it */
933 omapi_object_reference((omapi_object_t
**)&next
,
934 (omapi_object_t
*)io
->next
, MDL
);
937 status
= (*func
) (io
->inner
, p
);
938 if (status
!= ISC_R_SUCCESS
) {
939 /* Something went wrong. Let's stop using io & next pointer
941 omapi_object_dereference((omapi_object_t
**)&io
, MDL
);
943 omapi_object_dereference((omapi_object_t
**)&next
, MDL
);
948 /* Update the io pointer and free the next pointer */
949 omapi_object_dereference((omapi_object_t
**)&io
, MDL
);
951 omapi_object_reference((omapi_object_t
**)&io
,
952 (omapi_object_t
*)next
,
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
962 return ISC_R_SUCCESS
;