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