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