Annotation of embedaddon/dhcp/omapip/dispatch.c, revision 1.1.1.1
1.1 misho 1: /* dispatch.c
2:
3: I/O dispatcher. */
4:
5: /*
6: * Copyright (c) 2004,2007-2009 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: * https://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: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32: * ``http://www.nominum.com''.
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: /* ReRegister an I/O handle so that we can do asynchronous I/O on it.
171: * If the handle doesn't exist we call the register routine to build it.
172: * if it does exist we change the functions associated with it, and
173: * repoke the fd code to make it happy. Neither the objects nor the
174: * fd are allowed to have changed. */
175:
176: isc_result_t omapi_reregister_io_object (omapi_object_t *h,
177: int (*readfd) (omapi_object_t *),
178: int (*writefd) (omapi_object_t *),
179: isc_result_t (*reader)
180: (omapi_object_t *),
181: isc_result_t (*writer)
182: (omapi_object_t *),
183: isc_result_t (*reaper)
184: (omapi_object_t *))
185: {
186: omapi_io_object_t *obj;
187:
188: if ((!h -> outer) || (h -> outer -> type != omapi_type_io_object)) {
189: /* If we don't have an object or if the type isn't what
190: * we expect do the normal registration (which will overwrite
191: * an incorrect type, that's what we did historically, may
192: * want to change that)
193: */
194: return (omapi_register_io_object (h, readfd, writefd,
195: reader, writer, reaper));
196: }
197:
198: /* We have an io object of the correct type, try to update it */
199: /*sar*/
200: /* Should we validate that the fd matches the previous one?
201: * It's suppossed to, that's a requirement, don't bother yet */
202:
203: obj = (omapi_io_object_t *)h->outer;
204:
205: obj -> readfd = readfd;
206: obj -> writefd = writefd;
207: obj -> reader = reader;
208: obj -> writer = writer;
209: obj -> reaper = reaper;
210:
211: return (ISC_R_SUCCESS);
212: }
213:
214: isc_result_t omapi_unregister_io_object (omapi_object_t *h)
215: {
216: omapi_io_object_t *p, *obj, *last, *ph;
217:
218: if (!h -> outer || h -> outer -> type != omapi_type_io_object)
219: return ISC_R_INVALIDARG;
220: obj = (omapi_io_object_t *)h -> outer;
221: ph = (omapi_io_object_t *)0;
222: omapi_io_reference (&ph, obj, MDL);
223:
224: /* remove from the list of I/O states */
225: last = &omapi_io_states;
226: for (p = omapi_io_states.next; p; p = p -> next) {
227: if (p == obj) {
228: omapi_io_dereference (&last -> next, MDL);
229: omapi_io_reference (&last -> next, p -> next, MDL);
230: break;
231: }
232: last = p;
233: }
234: if (obj -> next)
235: omapi_io_dereference (&obj -> next, MDL);
236:
237: if (obj -> outer) {
238: if (obj -> outer -> inner == (omapi_object_t *)obj)
239: omapi_object_dereference (&obj -> outer -> inner,
240: MDL);
241: omapi_object_dereference (&obj -> outer, MDL);
242: }
243: omapi_object_dereference (&obj -> inner, MDL);
244: omapi_object_dereference (&h -> outer, MDL);
245: omapi_io_dereference (&ph, MDL);
246: return ISC_R_SUCCESS;
247: }
248:
249: isc_result_t omapi_dispatch (struct timeval *t)
250: {
251: return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
252: t);
253: }
254:
255: isc_result_t omapi_wait_for_completion (omapi_object_t *object,
256: struct timeval *t)
257: {
258: isc_result_t status;
259: omapi_waiter_object_t *waiter;
260: omapi_object_t *inner;
261:
262: if (object) {
263: waiter = (omapi_waiter_object_t *)0;
264: status = omapi_waiter_allocate (&waiter, MDL);
265: if (status != ISC_R_SUCCESS)
266: return status;
267:
268: /* Paste the waiter object onto the inner object we're
269: waiting on. */
270: for (inner = object; inner -> inner; inner = inner -> inner)
271: ;
272:
273: status = omapi_object_reference (&waiter -> outer, inner, MDL);
274: if (status != ISC_R_SUCCESS) {
275: omapi_waiter_dereference (&waiter, MDL);
276: return status;
277: }
278:
279: status = omapi_object_reference (&inner -> inner,
280: (omapi_object_t *)waiter,
281: MDL);
282: if (status != ISC_R_SUCCESS) {
283: omapi_waiter_dereference (&waiter, MDL);
284: return status;
285: }
286: } else
287: waiter = (omapi_waiter_object_t *)0;
288:
289: do {
290: status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
291: if (status != ISC_R_SUCCESS)
292: return status;
293: } while (!waiter || !waiter -> ready);
294:
295: if (waiter -> outer) {
296: if (waiter -> outer -> inner) {
297: omapi_object_dereference (&waiter -> outer -> inner,
298: MDL);
299: if (waiter -> inner)
300: omapi_object_reference
301: (&waiter -> outer -> inner,
302: waiter -> inner, MDL);
303: }
304: omapi_object_dereference (&waiter -> outer, MDL);
305: }
306: if (waiter -> inner)
307: omapi_object_dereference (&waiter -> inner, MDL);
308:
309: status = waiter -> waitstatus;
310: omapi_waiter_dereference (&waiter, MDL);
311: return status;
312: }
313:
314: isc_result_t omapi_one_dispatch (omapi_object_t *wo,
315: struct timeval *t)
316: {
317: fd_set r, w, x, rr, ww, xx;
318: int max = 0;
319: int count;
320: int desc;
321: struct timeval now, to;
322: omapi_io_object_t *io, *prev, *next;
323: omapi_waiter_object_t *waiter;
324: omapi_object_t *tmp = (omapi_object_t *)0;
325:
326: if (!wo || wo -> type != omapi_type_waiter)
327: waiter = (omapi_waiter_object_t *)0;
328: else
329: waiter = (omapi_waiter_object_t *)wo;
330:
331: FD_ZERO (&x);
332:
333: /* First, see if the timeout has expired, and if so return. */
334: if (t) {
335: gettimeofday (&now, (struct timezone *)0);
336: cur_tv.tv_sec = now.tv_sec;
337: cur_tv.tv_usec = now.tv_usec;
338: if (now.tv_sec > t -> tv_sec ||
339: (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
340: return ISC_R_TIMEDOUT;
341:
342: /* We didn't time out, so figure out how long until
343: we do. */
344: to.tv_sec = t -> tv_sec - now.tv_sec;
345: to.tv_usec = t -> tv_usec - now.tv_usec;
346: if (to.tv_usec < 0) {
347: to.tv_usec += 1000000;
348: to.tv_sec--;
349: }
350:
351: /* It is possible for the timeout to get set larger than
352: the largest time select() is willing to accept.
353: Restricting the timeout to a maximum of one day should
354: work around this. -DPN. (Ref: Bug #416) */
355: if (to.tv_sec > (60 * 60 * 24))
356: to.tv_sec = 60 * 60 * 24;
357: }
358:
359: /* If the object we're waiting on has reached completion,
360: return now. */
361: if (waiter && waiter -> ready)
362: return ISC_R_SUCCESS;
363:
364: again:
365: /* If we have no I/O state, we can't proceed. */
366: if (!(io = omapi_io_states.next))
367: return ISC_R_NOMORE;
368:
369: /* Set up the read and write masks. */
370: FD_ZERO (&r);
371: FD_ZERO (&w);
372:
373: for (; io; io = io -> next) {
374: /* Check for a read socket. If we shouldn't be
375: trying to read for this I/O object, either there
376: won't be a readfd function, or it'll return -1. */
377: if (io -> readfd && io -> inner &&
378: (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
379: FD_SET (desc, &r);
380: if (desc > max)
381: max = desc;
382: }
383:
384: /* Same deal for write fdets. */
385: if (io -> writefd && io -> inner &&
386: (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
387: FD_SET (desc, &w);
388: if (desc > max)
389: max = desc;
390: }
391: }
392:
393: /* poll if all reader are dry */
394: now.tv_sec = 0;
395: now.tv_usec = 0;
396: rr=r;
397: ww=w;
398: xx=x;
399:
400: /* poll once */
401: count = select(max + 1, &r, &w, &x, &now);
402: if (!count) {
403: /* We are dry now */
404: trigger_event(&rw_queue_empty);
405: /* Wait for a packet or a timeout... XXX */
406: r = rr;
407: w = ww;
408: x = xx;
409: count = select(max + 1, &r, &w, &x, t ? &to : NULL);
410: }
411:
412: /* Get the current time... */
413: gettimeofday (&cur_tv, (struct timezone *)0);
414:
415: /* We probably have a bad file descriptor. Figure out which one.
416: When we find it, call the reaper function on it, which will
417: maybe make it go away, and then try again. */
418: if (count < 0) {
419: struct timeval t0;
420: omapi_io_object_t *prev = (omapi_io_object_t *)0;
421: io = (omapi_io_object_t *)0;
422: if (omapi_io_states.next)
423: omapi_io_reference (&io, omapi_io_states.next, MDL);
424:
425: while (io) {
426: omapi_object_t *obj;
427: FD_ZERO (&r);
428: FD_ZERO (&w);
429: t0.tv_sec = t0.tv_usec = 0;
430:
431: if (io -> readfd && io -> inner &&
432: (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
433: FD_SET (desc, &r);
434: count = select (desc + 1, &r, &w, &x, &t0);
435: bogon:
436: if (count < 0) {
437: log_error ("Bad descriptor %d.", desc);
438: for (obj = (omapi_object_t *)io;
439: obj -> outer;
440: obj = obj -> outer)
441: ;
442: for (; obj; obj = obj -> inner) {
443: omapi_value_t *ov;
444: int len;
445: const char *s;
446: ov = (omapi_value_t *)0;
447: omapi_get_value_str (obj,
448: (omapi_object_t *)0,
449: "name", &ov);
450: if (ov && ov -> value &&
451: (ov -> value -> type ==
452: omapi_datatype_string)) {
453: s = (char *)
454: ov -> value -> u.buffer.value;
455: len = ov -> value -> u.buffer.len;
456: } else {
457: s = "";
458: len = 0;
459: }
460: log_error ("Object %lx %s%s%.*s",
461: (unsigned long)obj,
462: obj -> type -> name,
463: len ? " " : "",
464: len, s);
465: if (len)
466: omapi_value_dereference (&ov, MDL);
467: }
468: (*(io -> reaper)) (io -> inner);
469: if (prev) {
470: omapi_io_dereference (&prev -> next, MDL);
471: if (io -> next)
472: omapi_io_reference (&prev -> next,
473: io -> next, MDL);
474: } else {
475: omapi_io_dereference
476: (&omapi_io_states.next, MDL);
477: if (io -> next)
478: omapi_io_reference
479: (&omapi_io_states.next,
480: io -> next, MDL);
481: }
482: omapi_io_dereference (&io, MDL);
483: goto again;
484: }
485: }
486:
487: FD_ZERO (&r);
488: FD_ZERO (&w);
489: t0.tv_sec = t0.tv_usec = 0;
490:
491: /* Same deal for write fdets. */
492: if (io -> writefd && io -> inner &&
493: (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
494: FD_SET (desc, &w);
495: count = select (desc + 1, &r, &w, &x, &t0);
496: if (count < 0)
497: goto bogon;
498: }
499: if (prev)
500: omapi_io_dereference (&prev, MDL);
501: omapi_io_reference (&prev, io, MDL);
502: omapi_io_dereference (&io, MDL);
503: if (prev -> next)
504: omapi_io_reference (&io, prev -> next, MDL);
505: }
506: if (prev)
507: omapi_io_dereference (&prev, MDL);
508:
509: }
510:
511: for (io = omapi_io_states.next; io; io = io -> next) {
512: if (!io -> inner)
513: continue;
514: omapi_object_reference (&tmp, io -> inner, MDL);
515: /* Check for a read descriptor, and if there is one,
516: see if we got input on that socket. */
517: if (io -> readfd &&
518: (desc = (*(io -> readfd)) (tmp)) >= 0) {
519: if (FD_ISSET (desc, &r))
520: ((*(io -> reader)) (tmp));
521: }
522:
523: /* Same deal for write descriptors. */
524: if (io -> writefd &&
525: (desc = (*(io -> writefd)) (tmp)) >= 0)
526: {
527: if (FD_ISSET (desc, &w))
528: ((*(io -> writer)) (tmp));
529: }
530: omapi_object_dereference (&tmp, MDL);
531: }
532:
533: /* Now check for I/O handles that are no longer valid,
534: and remove them from the list. */
535: prev = NULL;
536: io = NULL;
537: if (omapi_io_states.next != NULL) {
538: omapi_io_reference(&io, omapi_io_states.next, MDL);
539: }
540: while (io != NULL) {
541: if ((io->inner == NULL) ||
542: ((io->reaper != NULL) &&
543: ((io->reaper)(io->inner) != ISC_R_SUCCESS)))
544: {
545:
546: omapi_io_object_t *tmp = NULL;
547: /* Save a reference to the next
548: pointer, if there is one. */
549: if (io->next != NULL) {
550: omapi_io_reference(&tmp, io->next, MDL);
551: omapi_io_dereference(&io->next, MDL);
552: }
553: if (prev != NULL) {
554: omapi_io_dereference(&prev->next, MDL);
555: if (tmp != NULL)
556: omapi_io_reference(&prev->next,
557: tmp, MDL);
558: } else {
559: omapi_io_dereference(&omapi_io_states.next,
560: MDL);
561: if (tmp != NULL)
562: omapi_io_reference
563: (&omapi_io_states.next,
564: tmp, MDL);
565: else
566: omapi_signal_in(
567: (omapi_object_t *)
568: &omapi_io_states,
569: "ready");
570: }
571: if (tmp != NULL)
572: omapi_io_dereference(&tmp, MDL);
573:
574: } else {
575:
576: if (prev != NULL) {
577: omapi_io_dereference(&prev, MDL);
578: }
579: omapi_io_reference(&prev, io, MDL);
580:
581: }
582:
583: /*
584: * Equivalent to:
585: * io = io->next
586: * But using our reference counting voodoo.
587: */
588: next = NULL;
589: if (io->next != NULL) {
590: omapi_io_reference(&next, io->next, MDL);
591: }
592: omapi_io_dereference(&io, MDL);
593: if (next != NULL) {
594: omapi_io_reference(&io, next, MDL);
595: omapi_io_dereference(&next, MDL);
596: }
597: }
598: if (prev != NULL) {
599: omapi_io_dereference(&prev, MDL);
600: }
601:
602: return ISC_R_SUCCESS;
603: }
604:
605: isc_result_t omapi_io_set_value (omapi_object_t *h,
606: omapi_object_t *id,
607: omapi_data_string_t *name,
608: omapi_typed_data_t *value)
609: {
610: if (h -> type != omapi_type_io_object)
611: return ISC_R_INVALIDARG;
612:
613: if (h -> inner && h -> inner -> type -> set_value)
614: return (*(h -> inner -> type -> set_value))
615: (h -> inner, id, name, value);
616: return ISC_R_NOTFOUND;
617: }
618:
619: isc_result_t omapi_io_get_value (omapi_object_t *h,
620: omapi_object_t *id,
621: omapi_data_string_t *name,
622: omapi_value_t **value)
623: {
624: if (h -> type != omapi_type_io_object)
625: return ISC_R_INVALIDARG;
626:
627: if (h -> inner && h -> inner -> type -> get_value)
628: return (*(h -> inner -> type -> get_value))
629: (h -> inner, id, name, value);
630: return ISC_R_NOTFOUND;
631: }
632:
633: /* omapi_io_destroy (object, MDL);
634: *
635: * Find the requested IO [object] and remove it from the list of io
636: * states, causing the cleanup functions to destroy it. Note that we must
637: * hold a reference on the object while moving its ->next reference and
638: * removing the reference in the chain to the target object...otherwise it
639: * may be cleaned up from under us.
640: */
641: isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
642: {
643: omapi_io_object_t *obj = NULL, *p, *last = NULL, **holder;
644:
645: if (h -> type != omapi_type_io_object)
646: return ISC_R_INVALIDARG;
647:
648: /* remove from the list of I/O states */
649: for (p = omapi_io_states.next; p; p = p -> next) {
650: if (p == (omapi_io_object_t *)h) {
651: omapi_io_reference (&obj, p, MDL);
652:
653: if (last)
654: holder = &last -> next;
655: else
656: holder = &omapi_io_states.next;
657:
658: omapi_io_dereference (holder, MDL);
659:
660: if (obj -> next) {
661: omapi_io_reference (holder, obj -> next, MDL);
662: omapi_io_dereference (&obj -> next, MDL);
663: }
664:
665: return omapi_io_dereference (&obj, MDL);
666: }
667: last = p;
668: }
669:
670: return ISC_R_NOTFOUND;
671: }
672:
673: isc_result_t omapi_io_signal_handler (omapi_object_t *h,
674: const char *name, va_list ap)
675: {
676: if (h -> type != omapi_type_io_object)
677: return ISC_R_INVALIDARG;
678:
679: if (h -> inner && h -> inner -> type -> signal_handler)
680: return (*(h -> inner -> type -> signal_handler)) (h -> inner,
681: name, ap);
682: return ISC_R_NOTFOUND;
683: }
684:
685: isc_result_t omapi_io_stuff_values (omapi_object_t *c,
686: omapi_object_t *id,
687: omapi_object_t *i)
688: {
689: if (i -> type != omapi_type_io_object)
690: return ISC_R_INVALIDARG;
691:
692: if (i -> inner && i -> inner -> type -> stuff_values)
693: return (*(i -> inner -> type -> stuff_values)) (c, id,
694: i -> inner);
695: return ISC_R_SUCCESS;
696: }
697:
698: isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
699: const char *name, va_list ap)
700: {
701: omapi_waiter_object_t *waiter;
702:
703: if (h -> type != omapi_type_waiter)
704: return ISC_R_INVALIDARG;
705:
706: if (!strcmp (name, "ready")) {
707: waiter = (omapi_waiter_object_t *)h;
708: waiter -> ready = 1;
709: waiter -> waitstatus = ISC_R_SUCCESS;
710: return ISC_R_SUCCESS;
711: }
712:
713: if (!strcmp (name, "status")) {
714: waiter = (omapi_waiter_object_t *)h;
715: waiter -> ready = 1;
716: waiter -> waitstatus = va_arg (ap, isc_result_t);
717: return ISC_R_SUCCESS;
718: }
719:
720: if (!strcmp (name, "disconnect")) {
721: waiter = (omapi_waiter_object_t *)h;
722: waiter -> ready = 1;
723: waiter -> waitstatus = ISC_R_CONNRESET;
724: return ISC_R_SUCCESS;
725: }
726:
727: if (h -> inner && h -> inner -> type -> signal_handler)
728: return (*(h -> inner -> type -> signal_handler)) (h -> inner,
729: name, ap);
730: return ISC_R_NOTFOUND;
731: }
732:
733: isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *,
734: void *),
735: void *p)
736: {
737: omapi_io_object_t *io;
738: isc_result_t status;
739:
740: for (io = omapi_io_states.next; io; io = io -> next) {
741: if (io -> inner) {
742: status = (*func) (io -> inner, p);
743: if (status != ISC_R_SUCCESS)
744: return status;
745: }
746: }
747: return ISC_R_SUCCESS;
748: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>