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