~ubuntu-branches/ubuntu/oneiric/isc-dhcp/oneiric-security

« back to all changes in this revision

Viewing changes to omapip/dispatch.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Pollock
  • Date: 2009-09-02 22:34:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090902223425-nypo7bkftxffq41m
Tags: upstream-4.1.0
ImportĀ upstreamĀ versionĀ 4.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* dispatch.c
 
2
 
 
3
   I/O dispatcher. */
 
4
 
 
5
/*
 
6
 * Copyright (c) 2004,2007-2008 by Internet Systems Consortium, Inc. ("ISC")
 
7
 * Copyright (c) 1999-2003 by Internet Software Consortium
 
8
 *
 
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.
 
12
 *
 
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.
 
20
 *
 
21
 *   Internet Systems Consortium, Inc.
 
22
 *   950 Charter Street
 
23
 *   Redwood City, CA 94063
 
24
 *   <info@isc.org>
 
25
 *   http://www.isc.org/
 
26
 *
 
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
 * ``http://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''.
 
33
 */
 
34
 
 
35
#include "dhcpd.h"
 
36
 
 
37
#include <omapip/omapip_p.h>
 
38
#include <sys/time.h>
 
39
 
 
40
static omapi_io_object_t omapi_io_states;
 
41
struct timeval cur_tv;
 
42
 
 
43
struct eventqueue *rw_queue_empty;
 
44
 
 
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)
 
49
 
 
50
void
 
51
register_eventhandler(struct eventqueue **queue, void (*handler)(void *))
 
52
{
 
53
        struct eventqueue *t, *q;
 
54
 
 
55
        /* traverse to end of list */
 
56
        t = NULL;
 
57
        for (q = *queue ; q ; q = q->next) {
 
58
                if (q->handler == handler)
 
59
                        return; /* handler already registered */
 
60
                t = q;
 
61
        }
 
62
                
 
63
        q = ((struct eventqueue *)dmalloc(sizeof(struct eventqueue), MDL));
 
64
        if (!q)
 
65
                log_fatal("register_eventhandler: no memory!");
 
66
        memset(q, 0, sizeof *q);
 
67
        if (t)
 
68
                t->next = q;
 
69
        else 
 
70
                *queue  = q;
 
71
        q->handler = handler;
 
72
        return;
 
73
}
 
74
 
 
75
void
 
76
unregister_eventhandler(struct eventqueue **queue, void (*handler)(void *))
 
77
{
 
78
        struct eventqueue *t, *q;
 
79
        
 
80
        /* traverse to end of list */
 
81
        t= NULL;
 
82
        for (q = *queue ; q ; q = q->next) {
 
83
                if (q->handler == handler) {
 
84
                        if (t)
 
85
                                t->next = q->next;
 
86
                        else
 
87
                                *queue = q->next;
 
88
                        dfree(q, MDL); /* Don't access q after this!*/
 
89
                        break;
 
90
                }
 
91
                t = q;
 
92
        }
 
93
        return;
 
94
}
 
95
 
 
96
void
 
97
trigger_event(struct eventqueue **queue)
 
98
{
 
99
        struct eventqueue *q;
 
100
 
 
101
        for (q=*queue ; q ; q=q->next) {
 
102
                if (q->handler) 
 
103
                        (*q->handler)(NULL);
 
104
        }
 
105
}
 
106
 
 
107
 
 
108
/* Register an I/O handle so that we can do asynchronous I/O on it. */
 
109
 
 
110
isc_result_t omapi_register_io_object (omapi_object_t *h,
 
111
                                       int (*readfd) (omapi_object_t *),
 
112
                                       int (*writefd) (omapi_object_t *),
 
113
                                       isc_result_t (*reader)
 
114
                                                (omapi_object_t *),
 
115
                                       isc_result_t (*writer)
 
116
                                                (omapi_object_t *),
 
117
                                       isc_result_t (*reaper)
 
118
                                                (omapi_object_t *))
 
119
{
 
120
        isc_result_t status;
 
121
        omapi_io_object_t *obj, *p;
 
122
 
 
123
        /* omapi_io_states is a static object.   If its reference count
 
124
           is zero, this is the first I/O handle to be registered, so
 
125
           we need to initialize it.   Because there is no inner or outer
 
126
           pointer on this object, and we're setting its refcnt to 1, it
 
127
           will never be freed. */
 
128
        if (!omapi_io_states.refcnt) {
 
129
                omapi_io_states.refcnt = 1;
 
130
                omapi_io_states.type = omapi_type_io_object;
 
131
        }
 
132
                
 
133
        obj = (omapi_io_object_t *)0;
 
134
        status = omapi_io_allocate (&obj, MDL);
 
135
        if (status != ISC_R_SUCCESS)
 
136
                return status;
 
137
 
 
138
        status = omapi_object_reference (&obj -> inner, h, MDL);
 
139
        if (status != ISC_R_SUCCESS) {
 
140
                omapi_io_dereference (&obj, MDL);
 
141
                return status;
 
142
        }
 
143
 
 
144
        status = omapi_object_reference (&h -> outer,
 
145
                                         (omapi_object_t *)obj, MDL);
 
146
        if (status != ISC_R_SUCCESS) {
 
147
                omapi_io_dereference (&obj, MDL);
 
148
                return status;
 
149
        }
 
150
 
 
151
        /* Find the last I/O state, if there are any. */
 
152
        for (p = omapi_io_states.next;
 
153
             p && p -> next; p = p -> next)
 
154
                ;
 
155
        if (p)
 
156
                omapi_io_reference (&p -> next, obj, MDL);
 
157
        else
 
158
                omapi_io_reference (&omapi_io_states.next, obj, MDL);
 
159
 
 
160
        obj -> readfd = readfd;
 
161
        obj -> writefd = writefd;
 
162
        obj -> reader = reader;
 
163
        obj -> writer = writer;
 
164
        obj -> reaper = reaper;
 
165
 
 
166
        omapi_io_dereference(&obj, MDL);
 
167
        return ISC_R_SUCCESS;
 
168
}
 
169
 
 
170
isc_result_t omapi_unregister_io_object (omapi_object_t *h)
 
171
{
 
172
        omapi_io_object_t *p, *obj, *last, *ph;
 
173
 
 
174
        if (!h -> outer || h -> outer -> type != omapi_type_io_object)
 
175
                return ISC_R_INVALIDARG;
 
176
        obj = (omapi_io_object_t *)h -> outer;
 
177
        ph = (omapi_io_object_t *)0;
 
178
        omapi_io_reference (&ph, obj, MDL);
 
179
 
 
180
        /* remove from the list of I/O states */
 
181
        last = &omapi_io_states;
 
182
        for (p = omapi_io_states.next; p; p = p -> next) {
 
183
                if (p == obj) {
 
184
                        omapi_io_dereference (&last -> next, MDL);
 
185
                        omapi_io_reference (&last -> next, p -> next, MDL);
 
186
                        break;
 
187
                }
 
188
                last = p;
 
189
        }
 
190
        if (obj -> next)
 
191
                omapi_io_dereference (&obj -> next, MDL);
 
192
 
 
193
        if (obj -> outer) {
 
194
                if (obj -> outer -> inner == (omapi_object_t *)obj)
 
195
                        omapi_object_dereference (&obj -> outer -> inner,
 
196
                                                  MDL);
 
197
                omapi_object_dereference (&obj -> outer, MDL);
 
198
        }
 
199
        omapi_object_dereference (&obj -> inner, MDL);
 
200
        omapi_object_dereference (&h -> outer, MDL);
 
201
        omapi_io_dereference (&ph, MDL);
 
202
        return ISC_R_SUCCESS;
 
203
}
 
204
 
 
205
isc_result_t omapi_dispatch (struct timeval *t)
 
206
{
 
207
        return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
 
208
                                          t);
 
209
}
 
210
 
 
211
isc_result_t omapi_wait_for_completion (omapi_object_t *object,
 
212
                                        struct timeval *t)
 
213
{
 
214
        isc_result_t status;
 
215
        omapi_waiter_object_t *waiter;
 
216
        omapi_object_t *inner;
 
217
 
 
218
        if (object) {
 
219
                waiter = (omapi_waiter_object_t *)0;
 
220
                status = omapi_waiter_allocate (&waiter, MDL);
 
221
                if (status != ISC_R_SUCCESS)
 
222
                        return status;
 
223
 
 
224
                /* Paste the waiter object onto the inner object we're
 
225
                   waiting on. */
 
226
                for (inner = object; inner -> inner; inner = inner -> inner)
 
227
                        ;
 
228
 
 
229
                status = omapi_object_reference (&waiter -> outer, inner, MDL);
 
230
                if (status != ISC_R_SUCCESS) {
 
231
                        omapi_waiter_dereference (&waiter, MDL);
 
232
                        return status;
 
233
                }
 
234
                
 
235
                status = omapi_object_reference (&inner -> inner,
 
236
                                                 (omapi_object_t *)waiter,
 
237
                                                 MDL);
 
238
                if (status != ISC_R_SUCCESS) {
 
239
                        omapi_waiter_dereference (&waiter, MDL);
 
240
                        return status;
 
241
                }
 
242
        } else
 
243
                waiter = (omapi_waiter_object_t *)0;
 
244
 
 
245
        do {
 
246
                status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
 
247
                if (status != ISC_R_SUCCESS)
 
248
                        return status;
 
249
        } while (!waiter || !waiter -> ready);
 
250
 
 
251
        if (waiter -> outer) {
 
252
                if (waiter -> outer -> inner) {
 
253
                        omapi_object_dereference (&waiter -> outer -> inner,
 
254
                                                  MDL);
 
255
                        if (waiter -> inner)
 
256
                                omapi_object_reference
 
257
                                        (&waiter -> outer -> inner,
 
258
                                         waiter -> inner, MDL);
 
259
                }
 
260
                omapi_object_dereference (&waiter -> outer, MDL);
 
261
        }
 
262
        if (waiter -> inner)
 
263
                omapi_object_dereference (&waiter -> inner, MDL);
 
264
        
 
265
        status = waiter -> waitstatus;
 
266
        omapi_waiter_dereference (&waiter, MDL);
 
267
        return status;
 
268
}
 
269
 
 
270
isc_result_t omapi_one_dispatch (omapi_object_t *wo,
 
271
                                 struct timeval *t)
 
272
{
 
273
        fd_set r, w, x, rr, ww, xx;
 
274
        int max = 0;
 
275
        int count;
 
276
        int desc;
 
277
        struct timeval now, to;
 
278
        omapi_io_object_t *io, *prev, *next;
 
279
        omapi_waiter_object_t *waiter;
 
280
        omapi_object_t *tmp = (omapi_object_t *)0;
 
281
 
 
282
        if (!wo || wo -> type != omapi_type_waiter)
 
283
                waiter = (omapi_waiter_object_t *)0;
 
284
        else
 
285
                waiter = (omapi_waiter_object_t *)wo;
 
286
 
 
287
        FD_ZERO (&x);
 
288
 
 
289
        /* First, see if the timeout has expired, and if so return. */
 
290
        if (t) {
 
291
                gettimeofday (&now, (struct timezone *)0);
 
292
                cur_tv.tv_sec = now.tv_sec;
 
293
                cur_tv.tv_usec = now.tv_usec;
 
294
                if (now.tv_sec > t -> tv_sec ||
 
295
                    (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
 
296
                        return ISC_R_TIMEDOUT;
 
297
                        
 
298
                /* We didn't time out, so figure out how long until
 
299
                   we do. */
 
300
                to.tv_sec = t -> tv_sec - now.tv_sec;
 
301
                to.tv_usec = t -> tv_usec - now.tv_usec;
 
302
                if (to.tv_usec < 0) {
 
303
                        to.tv_usec += 1000000;
 
304
                        to.tv_sec--;
 
305
                }
 
306
 
 
307
                /* It is possible for the timeout to get set larger than
 
308
                   the largest time select() is willing to accept.
 
309
                   Restricting the timeout to a maximum of one day should
 
310
                   work around this.  -DPN.  (Ref: Bug #416) */
 
311
                if (to.tv_sec > (60 * 60 * 24))
 
312
                        to.tv_sec = 60 * 60 * 24;
 
313
        }
 
314
        
 
315
        /* If the object we're waiting on has reached completion,
 
316
           return now. */
 
317
        if (waiter && waiter -> ready)
 
318
                return ISC_R_SUCCESS;
 
319
        
 
320
      again:
 
321
        /* If we have no I/O state, we can't proceed. */
 
322
        if (!(io = omapi_io_states.next))
 
323
                return ISC_R_NOMORE;
 
324
 
 
325
        /* Set up the read and write masks. */
 
326
        FD_ZERO (&r);
 
327
        FD_ZERO (&w);
 
328
 
 
329
        for (; io; io = io -> next) {
 
330
                /* Check for a read socket.   If we shouldn't be
 
331
                   trying to read for this I/O object, either there
 
332
                   won't be a readfd function, or it'll return -1. */
 
333
                if (io -> readfd && io -> inner &&
 
334
                    (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
 
335
                        FD_SET (desc, &r);
 
336
                        if (desc > max)
 
337
                                max = desc;
 
338
                }
 
339
                
 
340
                /* Same deal for write fdets. */
 
341
                if (io -> writefd && io -> inner &&
 
342
                    (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
 
343
                        FD_SET (desc, &w);
 
344
                        if (desc > max)
 
345
                                max = desc;
 
346
                }
 
347
        }
 
348
 
 
349
        /* poll if all reader are dry */ 
 
350
        now.tv_sec = 0;
 
351
        now.tv_usec = 0;
 
352
        rr=r; 
 
353
        ww=w; 
 
354
        xx=x;
 
355
 
 
356
        /* poll once */
 
357
        count = select(max + 1, &r, &w, &x, &now);
 
358
        if (!count) {  
 
359
                /* We are dry now */ 
 
360
                trigger_event(&rw_queue_empty);
 
361
                /* Wait for a packet or a timeout... XXX */
 
362
                count = select(max + 1, &rr, &ww, &xx, t ? &to : NULL);
 
363
        }
 
364
 
 
365
        /* Get the current time... */
 
366
        gettimeofday (&cur_tv, (struct timezone *)0);
 
367
 
 
368
        /* We probably have a bad file descriptor.   Figure out which one.
 
369
           When we find it, call the reaper function on it, which will
 
370
           maybe make it go away, and then try again. */
 
371
        if (count < 0) {
 
372
                struct timeval t0;
 
373
                omapi_io_object_t *prev = (omapi_io_object_t *)0;
 
374
                io = (omapi_io_object_t *)0;
 
375
                if (omapi_io_states.next)
 
376
                        omapi_io_reference (&io, omapi_io_states.next, MDL);
 
377
 
 
378
                while (io) {
 
379
                        omapi_object_t *obj;
 
380
                        FD_ZERO (&r);
 
381
                        FD_ZERO (&w);
 
382
                        t0.tv_sec = t0.tv_usec = 0;
 
383
 
 
384
                        if (io -> readfd && io -> inner &&
 
385
                            (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
 
386
                            FD_SET (desc, &r);
 
387
                            count = select (desc + 1, &r, &w, &x, &t0);
 
388
                           bogon:
 
389
                            if (count < 0) {
 
390
                                log_error ("Bad descriptor %d.", desc);
 
391
                                for (obj = (omapi_object_t *)io;
 
392
                                     obj -> outer;
 
393
                                     obj = obj -> outer)
 
394
                                        ;
 
395
                                for (; obj; obj = obj -> inner) {
 
396
                                    omapi_value_t *ov;
 
397
                                    int len;
 
398
                                    const char *s;
 
399
                                    ov = (omapi_value_t *)0;
 
400
                                    omapi_get_value_str (obj,
 
401
                                                         (omapi_object_t *)0,
 
402
                                                         "name", &ov);
 
403
                                    if (ov && ov -> value &&
 
404
                                        (ov -> value -> type ==
 
405
                                         omapi_datatype_string)) {
 
406
                                        s = (char *)
 
407
                                                ov -> value -> u.buffer.value;
 
408
                                        len = ov -> value -> u.buffer.len;
 
409
                                    } else {
 
410
                                        s = "";
 
411
                                        len = 0;
 
412
                                    }
 
413
                                    log_error ("Object %lx %s%s%.*s",
 
414
                                               (unsigned long)obj,
 
415
                                               obj -> type -> name,
 
416
                                               len ? " " : "",
 
417
                                               len, s);
 
418
                                    if (len)
 
419
                                        omapi_value_dereference (&ov, MDL);
 
420
                                }
 
421
                                (*(io -> reaper)) (io -> inner);
 
422
                                if (prev) {
 
423
                                    omapi_io_dereference (&prev -> next, MDL);
 
424
                                    if (io -> next)
 
425
                                        omapi_io_reference (&prev -> next,
 
426
                                                            io -> next, MDL);
 
427
                                } else {
 
428
                                    omapi_io_dereference
 
429
                                            (&omapi_io_states.next, MDL);
 
430
                                    if (io -> next)
 
431
                                        omapi_io_reference
 
432
                                                (&omapi_io_states.next,
 
433
                                                 io -> next, MDL);
 
434
                                }
 
435
                                omapi_io_dereference (&io, MDL);
 
436
                                goto again;
 
437
                            }
 
438
                        }
 
439
                        
 
440
                        FD_ZERO (&r);
 
441
                        FD_ZERO (&w);
 
442
                        t0.tv_sec = t0.tv_usec = 0;
 
443
 
 
444
                        /* Same deal for write fdets. */
 
445
                        if (io -> writefd && io -> inner &&
 
446
                            (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
 
447
                                FD_SET (desc, &w);
 
448
                                count = select (desc + 1, &r, &w, &x, &t0);
 
449
                                if (count < 0)
 
450
                                        goto bogon;
 
451
                        }
 
452
                        if (prev)
 
453
                                omapi_io_dereference (&prev, MDL);
 
454
                        omapi_io_reference (&prev, io, MDL);
 
455
                        omapi_io_dereference (&io, MDL);
 
456
                        if (prev -> next)
 
457
                            omapi_io_reference (&io, prev -> next, MDL);
 
458
                }
 
459
                if (prev)
 
460
                        omapi_io_dereference (&prev, MDL);
 
461
                
 
462
        }
 
463
 
 
464
        for (io = omapi_io_states.next; io; io = io -> next) {
 
465
                if (!io -> inner)
 
466
                        continue;
 
467
                omapi_object_reference (&tmp, io -> inner, MDL);
 
468
                /* Check for a read descriptor, and if there is one,
 
469
                   see if we got input on that socket. */
 
470
                if (io -> readfd &&
 
471
                    (desc = (*(io -> readfd)) (tmp)) >= 0) {
 
472
                        if (FD_ISSET (desc, &r))
 
473
                                ((*(io -> reader)) (tmp));
 
474
                }
 
475
                
 
476
                /* Same deal for write descriptors. */
 
477
                if (io -> writefd &&
 
478
                    (desc = (*(io -> writefd)) (tmp)) >= 0)
 
479
                {
 
480
                        if (FD_ISSET (desc, &w))
 
481
                                ((*(io -> writer)) (tmp));
 
482
                }
 
483
                omapi_object_dereference (&tmp, MDL);
 
484
        }
 
485
 
 
486
        /* Now check for I/O handles that are no longer valid,
 
487
           and remove them from the list. */
 
488
        prev = NULL;
 
489
        io = NULL;
 
490
        if (omapi_io_states.next != NULL) {
 
491
                omapi_io_reference(&io, omapi_io_states.next, MDL);
 
492
        }
 
493
        while (io != NULL) {
 
494
                if ((io->inner == NULL) || 
 
495
                    ((io->reaper != NULL) && 
 
496
                     ((io->reaper)(io->inner) != ISC_R_SUCCESS))) 
 
497
                {
 
498
 
 
499
                        omapi_io_object_t *tmp = NULL;
 
500
                        /* Save a reference to the next
 
501
                           pointer, if there is one. */
 
502
                        if (io->next != NULL) {
 
503
                                omapi_io_reference(&tmp, io->next, MDL);
 
504
                                omapi_io_dereference(&io->next, MDL);
 
505
                        }
 
506
                        if (prev != NULL) {
 
507
                                omapi_io_dereference(&prev->next, MDL);
 
508
                                if (tmp != NULL)
 
509
                                        omapi_io_reference(&prev->next,
 
510
                                                           tmp, MDL);
 
511
                        } else {
 
512
                                omapi_io_dereference(&omapi_io_states.next, 
 
513
                                                     MDL);
 
514
                                if (tmp != NULL)
 
515
                                        omapi_io_reference
 
516
                                            (&omapi_io_states.next,
 
517
                                             tmp, MDL);
 
518
                                else
 
519
                                        omapi_signal_in(
 
520
                                                        (omapi_object_t *)
 
521
                                                        &omapi_io_states,
 
522
                                                        "ready");
 
523
                        }
 
524
                        if (tmp != NULL)
 
525
                                omapi_io_dereference(&tmp, MDL);
 
526
 
 
527
                } else {
 
528
 
 
529
                        if (prev != NULL) {
 
530
                                omapi_io_dereference(&prev, MDL);
 
531
                        }
 
532
                        omapi_io_reference(&prev, io, MDL);
 
533
 
 
534
                }
 
535
 
 
536
                /*
 
537
                 * Equivalent to:
 
538
                 *   io = io->next
 
539
                 * But using our reference counting voodoo.
 
540
                 */
 
541
                next = NULL;
 
542
                if (io->next != NULL) {
 
543
                        omapi_io_reference(&next, io->next, MDL);
 
544
                }
 
545
                omapi_io_dereference(&io, MDL);
 
546
                if (next != NULL) {
 
547
                        omapi_io_reference(&io, next, MDL);
 
548
                        omapi_io_dereference(&next, MDL);
 
549
                }
 
550
        }
 
551
        if (prev != NULL) {
 
552
                omapi_io_dereference(&prev, MDL);
 
553
        }
 
554
 
 
555
        return ISC_R_SUCCESS;
 
556
}
 
557
 
 
558
isc_result_t omapi_io_set_value (omapi_object_t *h,
 
559
                                 omapi_object_t *id,
 
560
                                 omapi_data_string_t *name,
 
561
                                 omapi_typed_data_t *value)
 
562
{
 
563
        if (h -> type != omapi_type_io_object)
 
564
                return ISC_R_INVALIDARG;
 
565
        
 
566
        if (h -> inner && h -> inner -> type -> set_value)
 
567
                return (*(h -> inner -> type -> set_value))
 
568
                        (h -> inner, id, name, value);
 
569
        return ISC_R_NOTFOUND;
 
570
}
 
571
 
 
572
isc_result_t omapi_io_get_value (omapi_object_t *h,
 
573
                                 omapi_object_t *id,
 
574
                                 omapi_data_string_t *name,
 
575
                                 omapi_value_t **value)
 
576
{
 
577
        if (h -> type != omapi_type_io_object)
 
578
                return ISC_R_INVALIDARG;
 
579
        
 
580
        if (h -> inner && h -> inner -> type -> get_value)
 
581
                return (*(h -> inner -> type -> get_value))
 
582
                        (h -> inner, id, name, value);
 
583
        return ISC_R_NOTFOUND;
 
584
}
 
585
 
 
586
/* omapi_io_destroy (object, MDL);
 
587
 *
 
588
 *      Find the requested IO [object] and remove it from the list of io
 
589
 * states, causing the cleanup functions to destroy it.  Note that we must
 
590
 * hold a reference on the object while moving its ->next reference and
 
591
 * removing the reference in the chain to the target object...otherwise it
 
592
 * may be cleaned up from under us.
 
593
 */
 
594
isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
 
595
{
 
596
        omapi_io_object_t *obj = NULL, *p, *last = NULL, **holder;
 
597
 
 
598
        if (h -> type != omapi_type_io_object)
 
599
                return ISC_R_INVALIDARG;
 
600
        
 
601
        /* remove from the list of I/O states */
 
602
        for (p = omapi_io_states.next; p; p = p -> next) {
 
603
                if (p == (omapi_io_object_t *)h) {
 
604
                        omapi_io_reference (&obj, p, MDL);
 
605
 
 
606
                        if (last)
 
607
                                holder = &last -> next;
 
608
                        else
 
609
                                holder = &omapi_io_states.next;
 
610
 
 
611
                        omapi_io_dereference (holder, MDL);
 
612
 
 
613
                        if (obj -> next) {
 
614
                                omapi_io_reference (holder, obj -> next, MDL);
 
615
                                omapi_io_dereference (&obj -> next, MDL);
 
616
                        }
 
617
 
 
618
                        return omapi_io_dereference (&obj, MDL);
 
619
                }
 
620
                last = p;
 
621
        }
 
622
 
 
623
        return ISC_R_NOTFOUND;
 
624
}
 
625
 
 
626
isc_result_t omapi_io_signal_handler (omapi_object_t *h,
 
627
                                      const char *name, va_list ap)
 
628
{
 
629
        if (h -> type != omapi_type_io_object)
 
630
                return ISC_R_INVALIDARG;
 
631
        
 
632
        if (h -> inner && h -> inner -> type -> signal_handler)
 
633
                return (*(h -> inner -> type -> signal_handler)) (h -> inner,
 
634
                                                                  name, ap);
 
635
        return ISC_R_NOTFOUND;
 
636
}
 
637
 
 
638
isc_result_t omapi_io_stuff_values (omapi_object_t *c,
 
639
                                    omapi_object_t *id,
 
640
                                    omapi_object_t *i)
 
641
{
 
642
        if (i -> type != omapi_type_io_object)
 
643
                return ISC_R_INVALIDARG;
 
644
 
 
645
        if (i -> inner && i -> inner -> type -> stuff_values)
 
646
                return (*(i -> inner -> type -> stuff_values)) (c, id,
 
647
                                                                i -> inner);
 
648
        return ISC_R_SUCCESS;
 
649
}
 
650
 
 
651
isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
 
652
                                          const char *name, va_list ap)
 
653
{
 
654
        omapi_waiter_object_t *waiter;
 
655
 
 
656
        if (h -> type != omapi_type_waiter)
 
657
                return ISC_R_INVALIDARG;
 
658
        
 
659
        if (!strcmp (name, "ready")) {
 
660
                waiter = (omapi_waiter_object_t *)h;
 
661
                waiter -> ready = 1;
 
662
                waiter -> waitstatus = ISC_R_SUCCESS;
 
663
                return ISC_R_SUCCESS;
 
664
        }
 
665
 
 
666
        if (!strcmp (name, "status")) {
 
667
                waiter = (omapi_waiter_object_t *)h;
 
668
                waiter -> ready = 1;
 
669
                waiter -> waitstatus = va_arg (ap, isc_result_t);
 
670
                return ISC_R_SUCCESS;
 
671
        }
 
672
 
 
673
        if (!strcmp (name, "disconnect")) {
 
674
                waiter = (omapi_waiter_object_t *)h;
 
675
                waiter -> ready = 1;
 
676
                waiter -> waitstatus = ISC_R_CONNRESET;
 
677
                return ISC_R_SUCCESS;
 
678
        }
 
679
 
 
680
        if (h -> inner && h -> inner -> type -> signal_handler)
 
681
                return (*(h -> inner -> type -> signal_handler)) (h -> inner,
 
682
                                                                  name, ap);
 
683
        return ISC_R_NOTFOUND;
 
684
}
 
685
 
 
686
isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *,
 
687
                                                           void *),
 
688
                                     void *p)
 
689
{
 
690
        omapi_io_object_t *io;
 
691
        isc_result_t status;
 
692
 
 
693
        for (io = omapi_io_states.next; io; io = io -> next) {
 
694
                if (io -> inner) {
 
695
                        status = (*func) (io -> inner, p);
 
696
                        if (status != ISC_R_SUCCESS)
 
697
                                return status;
 
698
                }
 
699
        }
 
700
        return ISC_R_SUCCESS;
 
701
}