File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / omapip / dispatch.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    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>