summaryrefslogtreecommitdiffstats
path: root/ipsec-tools/src/racoon/schedule.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipsec-tools/src/racoon/schedule.c')
-rw-r--r--ipsec-tools/src/racoon/schedule.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/ipsec-tools/src/racoon/schedule.c b/ipsec-tools/src/racoon/schedule.c
new file mode 100644
index 00000000..018f920b
--- /dev/null
+++ b/ipsec-tools/src/racoon/schedule.c
@@ -0,0 +1,311 @@
+/* $NetBSD: schedule.c,v 1.7 2009/01/23 09:10:13 tteras Exp $ */
+
+/* $KAME: schedule.c,v 1.19 2001/11/05 10:53:19 sakane Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (C) 2008 Timo Teras.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include "misc.h"
+#include "plog.h"
+#include "schedule.h"
+#include "var.h"
+#include "gcmalloc.h"
+
+#ifndef TAILQ_FOREACH
+#define TAILQ_FOREACH(elm, head, field) \
+ for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
+#endif
+
+static TAILQ_HEAD(_schedtree, sched) sctree;
+
+void
+sched_get_monotonic_time(tv)
+ struct timeval *tv;
+{
+#ifdef HAVE_CLOCK_MONOTONIC
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+#else
+ gettimeofday(tv, NULL);
+#endif
+}
+
+time_t
+sched_monotonic_to_time_t(tv, now)
+ struct timeval *tv, *now;
+{
+#ifdef HAVE_CLOCK_MONOTONIC
+ struct timeval mynow, res;
+
+ if (now == NULL) {
+ sched_get_monotonic_time(&mynow);
+ now = &mynow;
+ }
+ timersub(now, tv, &res);
+
+ return time(NULL) + res.tv_sec;
+#else
+ return tv->tv_sec;
+#endif
+}
+
+/*
+ * schedule handler
+ * OUT:
+ * time to block until next event.
+ * if no entry, NULL returned.
+ */
+struct timeval *
+schedular()
+{
+ static struct timeval timeout;
+ struct timeval now;
+ struct sched *p;
+
+ sched_get_monotonic_time(&now);
+ while (!TAILQ_EMPTY(&sctree) &&
+ timercmp(&TAILQ_FIRST(&sctree)->xtime, &now, <=)) {
+ void (*func)(struct sched *);
+
+ p = TAILQ_FIRST(&sctree);
+ func = p->func;
+ sched_cancel(p);
+ func(p);
+ }
+
+ p = TAILQ_FIRST(&sctree);
+ if (p == NULL)
+ return NULL;
+
+ timersub(&p->xtime, &now, &timeout);
+
+ return &timeout;
+}
+
+/*
+ * add new schedule to schedule table.
+ */
+void
+sched_schedule(sc, tick, func)
+ struct sched *sc;
+ time_t tick;
+ void (*func) __P((struct sched *));
+{
+ static long id = 1;
+ struct sched *p;
+ struct timeval now;
+
+ sched_cancel(sc);
+
+ sc->func = func;
+ sc->id = id++;
+ sc->tick.tv_sec = tick;
+ sc->tick.tv_usec = 0;
+ sched_get_monotonic_time(&now);
+ timeradd(&now, &sc->tick, &sc->xtime);
+
+ /* add to schedule table */
+ TAILQ_FOREACH(p, &sctree, chain) {
+ if (timercmp(&sc->xtime, &p->xtime, <))
+ break;
+ }
+ if (p == NULL)
+ TAILQ_INSERT_TAIL(&sctree, sc, chain);
+ else
+ TAILQ_INSERT_BEFORE(p, sc, chain);
+}
+
+/*
+ * cancel scheduled callback
+ */
+void
+sched_cancel(sc)
+ struct sched *sc;
+{
+ if (sc->func != NULL) {
+ TAILQ_REMOVE(&sctree, sc, chain);
+ sc->func = NULL;
+ }
+}
+
+/*
+ * for debug
+ */
+int
+sched_dump(buf, len)
+ caddr_t *buf;
+ int *len;
+{
+ caddr_t new;
+ struct sched *p;
+ struct scheddump *dst;
+ struct timeval now, created;
+ int cnt = 0;
+
+ /* initialize */
+ *len = 0;
+ *buf = NULL;
+
+ TAILQ_FOREACH(p, &sctree, chain)
+ cnt++;
+
+ /* no entry */
+ if (cnt == 0)
+ return -1;
+
+ *len = cnt * sizeof(*dst);
+
+ new = racoon_malloc(*len);
+ if (new == NULL)
+ return -1;
+ dst = (struct scheddump *)new;
+
+ sched_get_monotonic_time(&now);
+ p = TAILQ_FIRST(&sctree);
+ while (p) {
+ timersub(&p->xtime, &p->tick, &created);
+ dst->xtime = p->xtime.tv_sec;
+ dst->id = p->id;
+ dst->created = sched_monotonic_to_time_t(&created, &now);
+ dst->tick = p->tick.tv_sec;
+
+ p = TAILQ_NEXT(p, chain);
+ if (p == NULL)
+ break;
+ dst++;
+ }
+
+ *buf = new;
+
+ return 0;
+}
+
+/* initialize schedule table */
+void
+sched_init()
+{
+ TAILQ_INIT(&sctree);
+}
+
+#ifdef STEST
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <err.h>
+
+void
+test(tick)
+ int *tick;
+{
+ printf("execute %d\n", *tick);
+ racoon_free(tick);
+}
+
+void
+getstdin()
+{
+ int *tick;
+ char buf[16];
+
+ read(0, buf, sizeof(buf));
+ if (buf[0] == 'd') {
+ struct scheddump *scbuf, *p;
+ int len;
+ sched_dump((caddr_t *)&scbuf, &len);
+ if (scbuf == NULL)
+ return;
+ for (p = scbuf; len; p++) {
+ printf("xtime=%ld\n", p->xtime);
+ len -= sizeof(*p);
+ }
+ racoon_free(scbuf);
+ return;
+ }
+
+ tick = (int *)racoon_malloc(sizeof(*tick));
+ *tick = atoi(buf);
+ printf("new queue tick = %d\n", *tick);
+ sched_new(*tick, test, tick);
+}
+
+int
+main()
+{
+ static fd_set mask0;
+ int nfds = 0;
+ fd_set rfds;
+ struct timeval *timeout;
+ int error;
+
+ FD_ZERO(&mask0);
+ FD_SET(0, &mask0);
+ nfds = 1;
+
+ /* initialize */
+ sched_init();
+
+ while (1) {
+ rfds = mask0;
+
+ timeout = schedular();
+
+ error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
+ if (error < 0) {
+ switch (errno) {
+ case EINTR: continue;
+ default:
+ err(1, "select");
+ }
+ /*NOTREACHED*/
+ }
+
+ if (FD_ISSET(0, &rfds))
+ getstdin();
+ }
+}
+#endif