]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/schedule.c
ipsec-93.6.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / schedule.c
1 /* $NetBSD: schedule.c,v 1.4 2006/09/09 16:22:10 manu Exp $ */
2
3 /* $KAME: schedule.c,v 1.19 2001/11/05 10:53:19 sakane Exp $ */
4
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
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 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include "config.h"
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/time.h>
39 #include <sys/queue.h>
40 #include <sys/socket.h>
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <time.h>
47
48 #include "misc.h"
49 #include "plog.h"
50 #include "schedule.h"
51 #include "var.h"
52 #include "gcmalloc.h"
53
54 #define FIXY2038PROBLEM
55
56 #ifndef TAILQ_FOREACH
57 #define TAILQ_FOREACH(elm, head, field) \
58 for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
59 #endif
60
61 extern int terminated;
62 static struct timeval timeout;
63
64 #ifdef FIXY2038PROBLEM
65 #define Y2038TIME_T 0x7fffffff
66 static time_t launched; /* time when the program launched. */
67 static time_t deltaY2038;
68 #endif
69
70 static TAILQ_HEAD(_schedtree, sched) sctree;
71
72 static void sched_add __P((struct sched *));
73 static time_t current_time __P((void));
74
75 /*
76 * schedule handler
77 * OUT:
78 * time to block until next event.
79 * if no entry, NULL returned.
80 */
81 struct timeval *
82 schedular()
83 {
84 time_t now, delta;
85 struct sched *p, *next = NULL;
86
87 now = current_time();
88
89 for (p = TAILQ_FIRST(&sctree); p; p = next) {
90 /* if the entry has been dead, remove it */
91 if (p->dead)
92 goto next_schedule;
93
94 /* if the time hasn't come, proceed to the next entry */
95 if (now < p->xtime) {
96 next = TAILQ_NEXT(p, chain);
97 continue;
98 }
99
100 /* mark it with dead. and call the function. */
101 p->dead = 1;
102 if (p->func != NULL && !terminated)
103 (p->func)(p->param);
104
105 next_schedule:
106 next = TAILQ_NEXT(p, chain);
107 TAILQ_REMOVE(&sctree, p, chain);
108 racoon_free(p);
109 }
110
111 p = TAILQ_FIRST(&sctree);
112 if (p == NULL)
113 return NULL;
114
115 now = current_time();
116
117 delta = p->xtime - now;
118 timeout.tv_sec = delta < 0 ? 0 : delta;
119 timeout.tv_usec = 0;
120
121 return &timeout;
122 }
123
124 /*
125 * add new schedule to schedule table.
126 */
127 struct sched *
128 sched_new(tick, func, param)
129 time_t tick;
130 void (*func) __P((void *));
131 void *param;
132 {
133 static long id = 1;
134 struct sched *new;
135
136 new = (struct sched *)racoon_malloc(sizeof(*new));
137 if (new == NULL)
138 return NULL;
139
140 memset(new, 0, sizeof(*new));
141 new->func = func;
142 new->param = param;
143
144 new->id = id++;
145 time(&new->created);
146 new->tick = tick;
147
148 new->xtime = current_time() + tick;
149 new->dead = 0;
150
151 /* add to schedule table */
152 sched_add(new);
153
154 return(new);
155 }
156
157 /* add new schedule to schedule table */
158 static void
159 sched_add(sc)
160 struct sched *sc;
161 {
162 struct sched *p;
163
164 TAILQ_FOREACH(p, &sctree, chain) {
165 if (sc->xtime < p->xtime) {
166 TAILQ_INSERT_BEFORE(p, sc, chain);
167 return;
168 }
169 }
170 if (p == NULL)
171 TAILQ_INSERT_TAIL(&sctree, sc, chain);
172
173 return;
174 }
175
176 /* get current time.
177 * if defined FIXY2038PROBLEM, base time is the time when called sched_init().
178 * Otherwise, conform to time(3).
179 */
180 static time_t
181 current_time()
182 {
183 time_t n;
184 #ifdef FIXY2038PROBLEM
185 time_t t;
186
187 time(&n);
188 t = n - launched;
189 if (t < 0)
190 t += deltaY2038;
191
192 return t;
193 #else
194 return time(&n);
195 #endif
196 }
197
198 void
199 sched_kill(sc)
200 struct sched *sc;
201 {
202 sc->dead = 1;
203
204 return;
205 }
206
207 /* XXX this function is probably unnecessary. */
208 void
209 sched_scrub_param(param)
210 void *param;
211 {
212 struct sched *sc;
213
214 TAILQ_FOREACH(sc, &sctree, chain) {
215 if (sc->param == param) {
216 if (!sc->dead) {
217 plog(LLV_DEBUG, LOCATION, NULL,
218 "an undead schedule has been deleted.\n");
219 }
220 sched_kill(sc);
221 }
222 }
223 }
224
225 /*
226 * for debug
227 */
228 int
229 sched_dump(buf, len)
230 caddr_t *buf;
231 int *len;
232 {
233 caddr_t new;
234 struct sched *p;
235 struct scheddump *dst;
236 int cnt = 0;
237
238 /* initialize */
239 *len = 0;
240 *buf = NULL;
241
242 TAILQ_FOREACH(p, &sctree, chain)
243 cnt++;
244
245 /* no entry */
246 if (cnt == 0)
247 return -1;
248
249 *len = cnt * sizeof(*dst);
250
251 new = racoon_malloc(*len);
252 if (new == NULL)
253 return -1;
254 dst = (struct scheddump *)new;
255
256 p = TAILQ_FIRST(&sctree);
257 while (p) {
258 dst->xtime = p->xtime;
259 dst->id = p->id;
260 dst->created = p->created;
261 dst->tick = p->tick;
262
263 p = TAILQ_NEXT(p, chain);
264 if (p == NULL)
265 break;
266 dst++;
267 }
268
269 *buf = new;
270
271 return 0;
272 }
273
274 /* initialize schedule table */
275 void
276 sched_init()
277 {
278 #ifdef FIXY2038PROBLEM
279 time(&launched);
280
281 deltaY2038 = Y2038TIME_T - launched;
282 #endif
283
284 TAILQ_INIT(&sctree);
285
286 return;
287 }
288
289 #ifdef STEST
290 #include <sys/types.h>
291 #include <sys/time.h>
292 #include <unistd.h>
293 #include <err.h>
294
295 void
296 test(tick)
297 int *tick;
298 {
299 printf("execute %d\n", *tick);
300 racoon_free(tick);
301 }
302
303 void
304 getstdin()
305 {
306 int *tick;
307 char buf[16];
308
309 read(0, buf, sizeof(buf));
310 if (buf[0] == 'd') {
311 struct scheddump *scbuf, *p;
312 int len;
313 sched_dump((caddr_t *)&scbuf, &len);
314 if (scbuf == NULL)
315 return;
316 for (p = scbuf; len; p++) {
317 printf("xtime=%ld\n", p->xtime);
318 len -= sizeof(*p);
319 }
320 racoon_free(scbuf);
321 return;
322 }
323
324 tick = (int *)racoon_malloc(sizeof(*tick));
325 *tick = atoi(buf);
326 printf("new queue tick = %d\n", *tick);
327 sched_new(*tick, test, tick);
328 }
329
330 int
331 main()
332 {
333 static fd_set mask0;
334 int nfds = 0;
335 fd_set rfds;
336 struct timeval *timeout;
337 int error;
338
339 FD_ZERO(&mask0);
340 FD_SET(0, &mask0);
341 nfds = 1;
342
343 /* initialize */
344 sched_init();
345
346 while (1) {
347 rfds = mask0;
348
349 timeout = schedular();
350
351 error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
352 if (error < 0) {
353 switch (errno) {
354 case EINTR: continue;
355 default:
356 err(1, "select");
357 }
358 /*NOTREACHED*/
359 }
360
361 if (FD_ISSET(0, &rfds))
362 getstdin();
363 }
364 }
365 #endif