diff options
Diffstat (limited to 'src/libcharon/plugins/certexpire/certexpire_cron.c')
-rw-r--r-- | src/libcharon/plugins/certexpire/certexpire_cron.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/libcharon/plugins/certexpire/certexpire_cron.c b/src/libcharon/plugins/certexpire/certexpire_cron.c new file mode 100644 index 000000000..e8cd4bfd8 --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_cron.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "certexpire_cron.h" + +#include <time.h> + +#include <debug.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_certexpire_cron_t private_certexpire_cron_t; + +/** + * Private data of an certexpire_cron_t object. + */ +struct private_certexpire_cron_t { + + /** + * Public certexpire_cron_t interface. + */ + certexpire_cron_t public; + + /** + * time when to run export job + */ + struct { + bool m[60]; + bool h[24]; + bool d[32]; + bool my[13]; + bool dw[8]; + } cron; + + /** + * Callback function to execute + */ + certexpire_cron_job_t job; + + /** + * Data to pass to callback + */ + void *data; +}; + +/** + * Check if we should execute the export job + */ +static job_requeue_t check_cron(private_certexpire_cron_t *this) +{ + struct tm tm; + time_t t; + + t = time(NULL); + localtime_r(&t, &tm); + + /* recheck every minute at second 0 */ + lib->scheduler->schedule_job(lib->scheduler, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)check_cron, + this, NULL, NULL, JOB_PRIO_CRITICAL), 60 - tm.tm_sec); + + /* skip this minute if we had a large negative time shift */ + if (tm.tm_sec <= 30) + { + if (this->cron.m[tm.tm_min] && + this->cron.h[tm.tm_hour] && + this->cron.d[tm.tm_mday] && + this->cron.my[tm.tm_mon + 1] && + (this->cron.dw[tm.tm_wday] || + (this->cron.dw[7] && tm.tm_wday == 0))) + { + this->job(this->data); + } + } + return JOB_REQUEUE_NONE; +} + +/** + * Parse a cron range component into boolean fields + */ +static void parse_ranges(bool *fields, char *label, int mi, int ma, char *range) +{ + enumerator_t *enumerator; + int from, to, i; + + if (streq(range, "*")) + { + for (i = mi; i <= ma; i++) + { + fields[i] = TRUE; + } + } + else + { + enumerator = enumerator_create_token(range, ",", ""); + while (enumerator->enumerate(enumerator, &range)) + { + switch (sscanf(range, "%d-%d", &from, &to)) + { + case 1: /* single value */ + if (from >= mi && from <= ma) + { + fields[from] = TRUE; + } + else + { + DBG1(DBG_CFG, "ignoring cron %s %d, out of range", + label, from); + } + break; + case 2: /* range */ + if (from < mi) + { + DBG1(DBG_CFG, "cron %s out of range, shortening start " + "from %d to %d", label, from, mi); + from = mi; + } + if (to > ma) + { + DBG1(DBG_CFG, "cron %s out of range, shortening end " + "from %d to %d", label, to, ma); + to = ma; + } + for (i = from; i <= to; i++) + { + fields[i] = TRUE; + } + break; + default: + break; + } + } + enumerator->destroy(enumerator); + } + DBG3(DBG_CFG, "cron job with enabled %ss:", label); + for (i = mi; i <= ma; i++) + { + if (fields[i]) + { + DBG3(DBG_CFG, " %d", i); + } + } +} + +/** + * Start cron processing, if configured + */ +static void start_cron(private_certexpire_cron_t *this, char *cron) +{ + enumerator_t *enumerator; + int i = 0; + + enumerator = enumerator_create_token(cron, " ", " "); + for (i = 0; i < 5; i++) + { + if (!enumerator->enumerate(enumerator, &cron)) + { + DBG1(DBG_CFG, "cron misses a field, using '*'"); + cron = "*"; + } + switch (i) + { + case 0: + parse_ranges(this->cron.m, "minute", 0, 59, cron); + break; + case 1: + parse_ranges(this->cron.h, "hour", 0, 23, cron); + break; + case 2: + parse_ranges(this->cron.d, "day", 1, 31, cron); + break; + case 3: + parse_ranges(this->cron.my, "month", 1, 12, cron); + break; + case 4: + parse_ranges(this->cron.dw, "weekday", 0, 7, cron); + break; + default: + break; + } + } + if (enumerator->enumerate(enumerator, &cron)) + { + DBG1(DBG_CFG, "ignoring extra fields in cron"); + } + enumerator->destroy(enumerator); + + check_cron(this); +} + +METHOD(certexpire_cron_t, destroy, void, + private_certexpire_cron_t *this) +{ + free(this); +} + +/** + * See header + */ +certexpire_cron_t *certexpire_cron_create(char *cron, certexpire_cron_job_t job, + void *data) +{ + private_certexpire_cron_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .job = job, + .data = data, + ); + + start_cron(this, cron); + + return &this->public; +} |