Initial import from FreeBSD RELENG_4:
[games.git] / contrib / isc-dhcp / common / dispatch.c
1 /* dispatch.c
2
3    Network input dispatcher... */
4
5 /*
6  * Copyright (c) 1995-2002 Internet Software Consortium.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of The Internet Software Consortium nor the names
19  *    of its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * This software has been written for the Internet Software Consortium
37  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38  * To learn more about the Internet Software Consortium, see
39  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
40  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
41  * ``http://www.nominum.com''.
42  */
43
44 #ifndef lint
45 static char copyright[] =
46 "$Id: dispatch.c,v 1.63.2.3 2002/11/17 02:26:57 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium.  All rights reserved.\n";
47 #endif /* not lint */
48
49 #include "dhcpd.h"
50
51 struct timeout *timeouts;
52 static struct timeout *free_timeouts;
53
54 void set_time (u_int32_t t)
55 {
56         /* Do any outstanding timeouts. */
57         if (cur_time != t) {
58                 cur_time = t;
59                 process_outstanding_timeouts ((struct timeval *)0);
60         }
61 }
62
63 struct timeval *process_outstanding_timeouts (struct timeval *tvp)
64 {
65         /* Call any expired timeouts, and then if there's
66            still a timeout registered, time out the select
67            call then. */
68       another:
69         if (timeouts) {
70                 struct timeout *t;
71                 if (timeouts -> when <= cur_time) {
72                         t = timeouts;
73                         timeouts = timeouts -> next;
74                         (*(t -> func)) (t -> what);
75                         if (t -> unref)
76                                 (*t -> unref) (&t -> what, MDL);
77                         t -> next = free_timeouts;
78                         free_timeouts = t;
79                         goto another;
80                 }
81                 if (tvp) {
82                         tvp -> tv_sec = timeouts -> when;
83                         tvp -> tv_usec = 0;
84                 }
85                 return tvp;
86         } else
87                 return (struct timeval *)0;
88 }
89
90 /* Wait for packets to come in using select().   When one does, call
91    receive_packet to receive the packet and possibly strip hardware
92    addressing information from it, and then call through the
93    bootp_packet_handler hook to try to do something with it. */
94
95 void dispatch ()
96 {
97         struct timeval tv, *tvp;
98         isc_result_t status;
99
100         /* Wait for a packet or a timeout... XXX */
101         do {
102                 tvp = process_outstanding_timeouts (&tv);
103                 status = omapi_one_dispatch (0, tvp);
104         } while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS);
105         log_fatal ("omapi_one_dispatch failed: %s -- exiting.",
106                    isc_result_totext (status));
107 }
108
109 void add_timeout (when, where, what, ref, unref)
110         TIME when;
111         void (*where) PROTO ((void *));
112         void *what;
113         tvref_t ref;
114         tvunref_t unref;
115 {
116         struct timeout *t, *q;
117
118         /* See if this timeout supersedes an existing timeout. */
119         t = (struct timeout *)0;
120         for (q = timeouts; q; q = q -> next) {
121                 if ((where == NULL || q -> func == where) &&
122                     q -> what == what) {
123                         if (t)
124                                 t -> next = q -> next;
125                         else
126                                 timeouts = q -> next;
127                         break;
128                 }
129                 t = q;
130         }
131
132         /* If we didn't supersede a timeout, allocate a timeout
133            structure now. */
134         if (!q) {
135                 if (free_timeouts) {
136                         q = free_timeouts;
137                         free_timeouts = q -> next;
138                 } else {
139                         q = ((struct timeout *)
140                              dmalloc (sizeof (struct timeout), MDL));
141                         if (!q)
142                                 log_fatal ("add_timeout: no memory!");
143                 }
144                 memset (q, 0, sizeof *q);
145                 q -> func = where;
146                 q -> ref = ref;
147                 q -> unref = unref;
148                 if (q -> ref)
149                         (*q -> ref)(&q -> what, what, MDL);
150                 else
151                         q -> what = what;
152         }
153
154         q -> when = when;
155
156         /* Now sort this timeout into the timeout list. */
157
158         /* Beginning of list? */
159         if (!timeouts || timeouts -> when > q -> when) {
160                 q -> next = timeouts;
161                 timeouts = q;
162                 return;
163         }
164
165         /* Middle of list? */
166         for (t = timeouts; t -> next; t = t -> next) {
167                 if (t -> next -> when > q -> when) {
168                         q -> next = t -> next;
169                         t -> next = q;
170                         return;
171                 }
172         }
173
174         /* End of list. */
175         t -> next = q;
176         q -> next = (struct timeout *)0;
177 }
178
179 void cancel_timeout (where, what)
180         void (*where) PROTO ((void *));
181         void *what;
182 {
183         struct timeout *t, *q;
184
185         /* Look for this timeout on the list, and unlink it if we find it. */
186         t = (struct timeout *)0;
187         for (q = timeouts; q; q = q -> next) {
188                 if (q -> func == where && q -> what == what) {
189                         if (t)
190                                 t -> next = q -> next;
191                         else
192                                 timeouts = q -> next;
193                         break;
194                 }
195                 t = q;
196         }
197
198         /* If we found the timeout, put it on the free list. */
199         if (q) {
200                 if (q -> unref)
201                         (*q -> unref) (&q -> what, MDL);
202                 q -> next = free_timeouts;
203                 free_timeouts = q;
204         }
205 }
206
207 #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
208 void cancel_all_timeouts ()
209 {
210         struct timeout *t, *n;
211         for (t = timeouts; t; t = n) {
212                 n = t -> next;
213                 if (t -> unref && t -> what)
214                         (*t -> unref) (&t -> what, MDL);
215                 t -> next = free_timeouts;
216                 free_timeouts = t;
217         }
218 }
219
220 void relinquish_timeouts ()
221 {
222         struct timeout *t, *n;
223         for (t = free_timeouts; t; t = n) {
224                 n = t -> next;
225                 dfree (t, MDL);
226         }
227 }
228 #endif