File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / common / 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:    Network input dispatcher... */
    4: 
    5: /*
    6:  * Copyright (c) 2004-2009,2011 by Internet Systems Consortium, Inc. ("ISC")
    7:  * Copyright (c) 1995-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: struct timeout *timeouts;
   38: static struct timeout *free_timeouts;
   39: 
   40: void set_time(TIME t)
   41: {
   42: 	/* Do any outstanding timeouts. */
   43: 	if (cur_tv . tv_sec != t) {
   44: 		cur_tv . tv_sec = t;
   45: 		cur_tv . tv_usec = 0;
   46: 		process_outstanding_timeouts ((struct timeval *)0);
   47: 	}
   48: }
   49: 
   50: struct timeval *process_outstanding_timeouts (struct timeval *tvp)
   51: {
   52: 	/* Call any expired timeouts, and then if there's
   53: 	   still a timeout registered, time out the select
   54: 	   call then. */
   55:       another:
   56: 	if (timeouts) {
   57: 		struct timeout *t;
   58: 		if ((timeouts -> when . tv_sec < cur_tv . tv_sec) ||
   59: 		    ((timeouts -> when . tv_sec == cur_tv . tv_sec) &&
   60: 		     (timeouts -> when . tv_usec <= cur_tv . tv_usec))) {
   61: 			t = timeouts;
   62: 			timeouts = timeouts -> next;
   63: 			(*(t -> func)) (t -> what);
   64: 			if (t -> unref)
   65: 				(*t -> unref) (&t -> what, MDL);
   66: 			t -> next = free_timeouts;
   67: 			free_timeouts = t;
   68: 			goto another;
   69: 		}
   70: 		if (tvp) {
   71: 			tvp -> tv_sec = timeouts -> when . tv_sec;
   72: 			tvp -> tv_usec = timeouts -> when . tv_usec;
   73: 		}
   74: 		return tvp;
   75: 	} else
   76: 		return (struct timeval *)0;
   77: }
   78: 
   79: /* Wait for packets to come in using select().   When one does, call
   80:    receive_packet to receive the packet and possibly strip hardware
   81:    addressing information from it, and then call through the
   82:    bootp_packet_handler hook to try to do something with it. */
   83: 
   84: void dispatch ()
   85: {
   86: 	struct timeval tv, *tvp;
   87: 	isc_result_t status;
   88: 
   89: 	/* Wait for a packet or a timeout... XXX */
   90: 	do {
   91: 		tvp = process_outstanding_timeouts (&tv);
   92: 		status = omapi_one_dispatch (0, tvp);
   93: 	} while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS);
   94: 	log_fatal ("omapi_one_dispatch failed: %s -- exiting.",
   95: 		   isc_result_totext (status));
   96: }
   97: 
   98: void add_timeout (when, where, what, ref, unref)
   99: 	struct timeval *when;
  100: 	void (*where) (void *);
  101: 	void *what;
  102: 	tvref_t ref;
  103: 	tvunref_t unref;
  104: {
  105: 	struct timeout *t, *q;
  106: 
  107: 	/* See if this timeout supersedes an existing timeout. */
  108: 	t = (struct timeout *)0;
  109: 	for (q = timeouts; q; q = q -> next) {
  110: 		if ((where == NULL || q -> func == where) &&
  111: 		    q -> what == what) {
  112: 			if (t)
  113: 				t -> next = q -> next;
  114: 			else
  115: 				timeouts = q -> next;
  116: 			break;
  117: 		}
  118: 		t = q;
  119: 	}
  120: 
  121: 	/* If we didn't supersede a timeout, allocate a timeout
  122: 	   structure now. */
  123: 	if (!q) {
  124: 		if (free_timeouts) {
  125: 			q = free_timeouts;
  126: 			free_timeouts = q -> next;
  127: 		} else {
  128: 			q = ((struct timeout *)
  129: 			     dmalloc (sizeof (struct timeout), MDL));
  130: 			if (!q)
  131: 				log_fatal ("add_timeout: no memory!");
  132: 		}
  133: 		memset (q, 0, sizeof *q);
  134: 		q -> func = where;
  135: 		q -> ref = ref;
  136: 		q -> unref = unref;
  137: 		if (q -> ref)
  138: 			(*q -> ref)(&q -> what, what, MDL);
  139: 		else
  140: 			q -> what = what;
  141: 	}
  142: 
  143: 	q -> when . tv_sec = when -> tv_sec;
  144: 	q -> when . tv_usec = when -> tv_usec;
  145: 
  146: 	/* Now sort this timeout into the timeout list. */
  147: 
  148: 	/* Beginning of list? */
  149: 	if (!timeouts || (timeouts -> when . tv_sec > q -> when . tv_sec) ||
  150: 	    ((timeouts -> when . tv_sec == q -> when . tv_sec) &&
  151: 	     (timeouts -> when . tv_usec > q -> when . tv_usec))) {
  152: 		q -> next = timeouts;
  153: 		timeouts = q;
  154: 		return;
  155: 	}
  156: 
  157: 	/* Middle of list? */
  158: 	for (t = timeouts; t -> next; t = t -> next) {
  159: 		if ((t -> next -> when . tv_sec > q -> when . tv_sec) ||
  160: 		    ((t -> next -> when . tv_sec == q -> when . tv_sec) &&
  161: 		     (t -> next -> when . tv_usec > q -> when . tv_usec))) {
  162: 			q -> next = t -> next;
  163: 			t -> next = q;
  164: 			return;
  165: 		}
  166: 	}
  167: 
  168: 	/* End of list. */
  169: 	t -> next = q;
  170: 	q -> next = (struct timeout *)0;
  171: }
  172: 
  173: void cancel_timeout (where, what)
  174: 	void (*where) (void *);
  175: 	void *what;
  176: {
  177: 	struct timeout *t, *q;
  178: 
  179: 	/* Look for this timeout on the list, and unlink it if we find it. */
  180: 	t = (struct timeout *)0;
  181: 	for (q = timeouts; q; q = q -> next) {
  182: 		if (q -> func == where && q -> what == what) {
  183: 			if (t)
  184: 				t -> next = q -> next;
  185: 			else
  186: 				timeouts = q -> next;
  187: 			break;
  188: 		}
  189: 		t = q;
  190: 	}
  191: 
  192: 	/* If we found the timeout, put it on the free list. */
  193: 	if (q) {
  194: 		if (q -> unref)
  195: 			(*q -> unref) (&q -> what, MDL);
  196: 		q -> next = free_timeouts;
  197: 		free_timeouts = q;
  198: 	}
  199: }
  200: 
  201: #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
  202: void cancel_all_timeouts ()
  203: {
  204: 	struct timeout *t, *n;
  205: 	for (t = timeouts; t; t = n) {
  206: 		n = t -> next;
  207: 		if (t -> unref && t -> what)
  208: 			(*t -> unref) (&t -> what, MDL);
  209: 		t -> next = free_timeouts;
  210: 		free_timeouts = t;
  211: 	}
  212: }
  213: 
  214: void relinquish_timeouts ()
  215: {
  216: 	struct timeout *t, *n;
  217: 	for (t = free_timeouts; t; t = n) {
  218: 		n = t -> next;
  219: 		dfree (t, MDL);
  220: 	}
  221: }
  222: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>