]>
Commit | Line | Data |
---|---|---|
48d507a9 | 1 | /* dispatch.c |
decf33c2 | 2 | |
48d507a9 | 3 | Network input dispatcher... */ |
decf33c2 TL |
4 | |
5 | /* | |
eb6b5a20 | 6 | * Copyright (c) 1995-2001 Internet Software Consortium. |
49733f31 | 7 | * All rights reserved. |
decf33c2 | 8 | * |
49733f31 TL |
9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
decf33c2 | 12 | * |
49733f31 TL |
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. | |
decf33c2 | 21 | * |
49733f31 TL |
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''. | |
decf33c2 TL |
42 | */ |
43 | ||
44 | #ifndef lint | |
45 | static char copyright[] = | |
d758ad8c | 46 | "$Id: dispatch.c,v 1.64 2001/06/27 00:29:45 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n"; |
decf33c2 TL |
47 | #endif /* not lint */ |
48 | ||
49 | #include "dhcpd.h" | |
decf33c2 | 50 | |
6806c5ae TL |
51 | struct timeout *timeouts; |
52 | static struct timeout *free_timeouts; | |
decf33c2 | 53 | |
eb6b5a20 TL |
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 | ||
decf33c2 TL |
90 | /* Wait for packets to come in using select(). When one does, call |
91 | receive_packet to receive the packet and possibly strip hardware | |
b25cbbad TL |
92 | addressing information from it, and then call through the |
93 | bootp_packet_handler hook to try to do something with it. */ | |
decf33c2 | 94 | |
e4749e75 | 95 | void dispatch () |
decf33c2 | 96 | { |
6806c5ae | 97 | struct timeval tv, *tvp; |
16be3937 | 98 | isc_result_t status; |
decf33c2 | 99 | |
eb6b5a20 | 100 | /* Wait for a packet or a timeout... XXX */ |
decf33c2 | 101 | do { |
eb6b5a20 | 102 | tvp = process_outstanding_timeouts (&tv); |
16be3937 TL |
103 | status = omapi_one_dispatch (0, tvp); |
104 | } while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS); | |
eac1e66f | 105 | log_fatal ("omapi_one_dispatch failed: %s -- exiting.", |
00763cc1 | 106 | isc_result_totext (status)); |
decf33c2 TL |
107 | } |
108 | ||
20916cae | 109 | void add_timeout (when, where, what, ref, unref) |
6806c5ae | 110 | TIME when; |
e4749e75 TL |
111 | void (*where) PROTO ((void *)); |
112 | void *what; | |
20916cae TL |
113 | tvref_t ref; |
114 | tvunref_t unref; | |
6806c5ae TL |
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) { | |
bdcaf7b9 TL |
121 | if ((where == NULL || q -> func == where) && |
122 | q -> what == what) { | |
6806c5ae TL |
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; | |
6806c5ae | 138 | } else { |
4bd8800e TL |
139 | q = ((struct timeout *) |
140 | dmalloc (sizeof (struct timeout), MDL)); | |
6806c5ae | 141 | if (!q) |
16be3937 | 142 | log_fatal ("add_timeout: no memory!"); |
6806c5ae | 143 | } |
20916cae TL |
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; | |
6806c5ae TL |
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) | |
e4749e75 TL |
180 | void (*where) PROTO ((void *)); |
181 | void *what; | |
6806c5ae TL |
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) { | |
e4749e75 | 188 | if (q -> func == where && q -> what == what) { |
6806c5ae TL |
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) { | |
20916cae TL |
200 | if (q -> unref) |
201 | (*q -> unref) (&q -> what, MDL); | |
6806c5ae TL |
202 | q -> next = free_timeouts; |
203 | free_timeouts = q; | |
204 | } | |
205 | } | |
d758ad8c TL |
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 |