]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/schedule.c
fe82c30ddea260b4076125c8a1698e02f7489dd2
[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 #if !defined(__LP64__)
55 // year 2038 problem and fix for 32-bit only
56 #define FIXY2038PROBLEM
57 #endif
58
59 #ifndef TAILQ_FOREACH
60 #define TAILQ_FOREACH(elm, head, field) \
61 for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
62 #endif
63
64 extern int terminated;
65 static struct timeval timeout;
66
67 #ifdef FIXY2038PROBLEM
68 #define Y2038TIME_T 0x7fffffff
69 static time_t launched; /* time when the program launched. */
70 static time_t deltaY2038;
71 #endif
72
73 static TAILQ_HEAD(_schedtree, sched) sctree;
74
75 static void sched_add __P((struct sched *));
76 static time_t current_time __P((void));
77
78 /*
79 * schedule handler
80 * OUT:
81 * time to block until next event.
82 * if no entry, NULL returned.
83 */
84 struct timeval *
85 schedular()
86 {
87 time_t now, delta;
88 struct sched *p, *next = NULL;
89
90 now = current_time();
91
92 for (p = TAILQ_FIRST(&sctree); p; p = next) {
93 /* if the entry has been dead, remove it */
94 if (p->dead)
95 goto next_schedule;
96
97 /* if the time hasn't come, proceed to the next entry */
98 if (now < p->xtime) {
99 next = TAILQ_NEXT(p, chain);
100 continue;
101 }
102
103 /* mark it with dead. and call the function. */
104 p->dead = 1;
105 if (p->func != NULL && !terminated)
106 (p->func)(p->param);
107
108 next_schedule:
109 next = TAILQ_NEXT(p, chain);
110 TAILQ_REMOVE(&sctree, p, chain);
111 racoon_free(p);
112 }
113
114 p = TAILQ_FIRST(&sctree);
115 if (p == NULL)
116 return NULL;
117
118 now = current_time();
119
120 delta = p->xtime - now;
121 timeout.tv_sec = delta < 0 ? 0 : delta;
122 timeout.tv_usec = 0;
123
124 return &timeout;
125 }
126
127 /*
128 * add new schedule to schedule table.
129 */
130 struct sched *
131 sched_new(tick, func, param)
132 time_t tick;
133 void (*func) __P((void *));
134 void *param;
135 {
136 static long id = 1;
137 struct sched *new;
138
139 new = (struct sched *)racoon_malloc(sizeof(*new));
140 if (new == NULL)
141 return NULL;
142
143 memset(new, 0, sizeof(*new));
144 new->func = func;
145 new->param = param;
146
147 new->id = id++;
148 time(&new->created);
149 new->tick = tick;
150
151 new->xtime = current_time() + tick;
152 new->dead = 0;
153
154 /* add to schedule table */
155 sched_add(new);
156
157 return(new);
158 }
159
160 /* add new schedule to schedule table */
161 static void
162 sched_add(sc)
163 struct sched *sc;
164 {
165 struct sched *p;
166
167 TAILQ_FOREACH(p, &sctree, chain) {
168 if (sc->xtime < p->xtime) {
169 TAILQ_INSERT_BEFORE(p, sc, chain);
170 return;
171 }
172 }
173 if (p == NULL)
174 TAILQ_INSERT_TAIL(&sctree, sc, chain);
175
176 return;
177 }
178
179 /* get current time.
180 * if defined FIXY2038PROBLEM, base time is the time when called sched_init().
181 * Otherwise, conform to time(3).
182 */
183 static time_t
184 current_time()
185 {
186 time_t n;
187 #ifdef FIXY2038PROBLEM
188 time_t t;
189
190 time(&n);
191 t = n - launched;
192 if (t < 0)
193 t += deltaY2038;
194
195 return t;
196 #else
197 return time(&n);
198 #endif
199 }
200
201 void
202 sched_kill(sc)
203 struct sched *sc;
204 {
205 sc->dead = 1;
206
207 return;
208 }
209
210 /* XXX this function is probably unnecessary. */
211 void
212 sched_scrub_param(param)
213 void *param;
214 {
215 struct sched *sc;
216
217 TAILQ_FOREACH(sc, &sctree, chain) {
218 if (sc->param == param) {
219 if (!sc->dead) {
220 plog(LLV_DEBUG, LOCATION, NULL,
221 "an undead schedule has been deleted.\n");
222 }
223 sched_kill(sc);
224 }
225 }
226 }
227
228 /*
229 * for debug
230 */
231 int
232 sched_dump(buf, len)
233 caddr_t *buf;
234 int *len;
235 {
236 caddr_t new;
237 struct sched *p;
238 struct scheddump *dst;
239 int cnt = 0;
240
241 /* initialize */
242 *len = 0;
243 *buf = NULL;
244
245 TAILQ_FOREACH(p, &sctree, chain)
246 cnt++;
247
248 /* no entry */
249 if (cnt == 0)
250 return -1;
251
252 *len = cnt * sizeof(*dst);
253
254 new = racoon_malloc(*len);
255 if (new == NULL)
256 return -1;
257 dst = (struct scheddump *)new;
258
259 p = TAILQ_FIRST(&sctree);
260 while (p) {
261 dst->xtime = p->xtime;
262 dst->id = p->id;
263 dst->created = p->created;
264 dst->tick = p->tick;
265
266 p = TAILQ_NEXT(p, chain);
267 if (p == NULL)
268 break;
269 dst++;
270 }
271
272 *buf = new;
273
274 return 0;
275 }
276
277 /* initialize schedule table */
278 void
279 sched_init()
280 {
281 #ifdef FIXY2038PROBLEM
282 time(&launched);
283
284 deltaY2038 = Y2038TIME_T - launched;
285 #endif
286
287 TAILQ_INIT(&sctree);
288
289 return;
290 }
291
292 #ifdef STEST
293 #include <sys/types.h>
294 #include <sys/time.h>
295 #include <unistd.h>
296 #include <err.h>
297
298 void
299 test(tick)
300 int *tick;
301 {
302 printf("execute %d\n", *tick);
303 racoon_free(tick);
304 }
305
306 void
307 getstdin()
308 {
309 int *tick;
310 char buf[16];
311
312 read(0, buf, sizeof(buf));
313 if (buf[0] == 'd') {
314 struct scheddump *scbuf, *p;
315 int len;
316 sched_dump((caddr_t *)&scbuf, &len);
317 if (scbuf == NULL)
318 return;
319 for (p = scbuf; len; p++) {
320 printf("xtime=%ld\n", p->xtime);
321 len -= sizeof(*p);
322 }
323 racoon_free(scbuf);
324 return;
325 }
326
327 tick = (int *)racoon_malloc(sizeof(*tick));
328 *tick = atoi(buf);
329 printf("new queue tick = %d\n", *tick);
330 sched_new(*tick, test, tick);
331 }
332
333 int
334 main()
335 {
336 static fd_set mask0;
337 int nfds = 0;
338 fd_set rfds;
339 struct timeval *timeout;
340 int error;
341
342 FD_ZERO(&mask0);
343 FD_SET(0, &mask0);
344 nfds = 1;
345
346 /* initialize */
347 sched_init();
348
349 while (1) {
350 rfds = mask0;
351
352 timeout = schedular();
353
354 error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
355 if (error < 0) {
356 switch (errno) {
357 case EINTR: continue;
358 default:
359 err(1, "select");
360 }
361 /*NOTREACHED*/
362 }
363
364 if (FD_ISSET(0, &rfds))
365 getstdin();
366 }
367 }
368 #endif