From 4b38c22c00ea24a9b47c9f81da0e2ea8c1731e69 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 15 May 2012 14:44:30 +0200 Subject: [PATCH] Schedule a DPD timeout job that enforces the IKE message timeout policy --- src/libcharon/Makefile.am | 1 + src/libcharon/processing/jobs/dpd_timeout_job.c | 111 ++++++++++++++++++++++++ src/libcharon/processing/jobs/dpd_timeout_job.h | 52 +++++++++++ src/libcharon/sa/ikev1/task_manager_v1.c | 13 +++ 4 files changed, 177 insertions(+) create mode 100644 src/libcharon/processing/jobs/dpd_timeout_job.c create mode 100644 src/libcharon/processing/jobs/dpd_timeout_job.h diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index e31d532..b68081a 100755 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -119,6 +119,7 @@ sa/ikev1/tasks/xauth.c sa/ikev1/tasks/xauth.h \ sa/ikev1/tasks/quick_mode.c sa/ikev1/tasks/quick_mode.h \ sa/ikev1/tasks/quick_delete.c sa/ikev1/tasks/quick_delete.h \ sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \ +processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \ processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h endif diff --git a/src/libcharon/processing/jobs/dpd_timeout_job.c b/src/libcharon/processing/jobs/dpd_timeout_job.c new file mode 100644 index 0000000..8dc458f --- /dev/null +++ b/src/libcharon/processing/jobs/dpd_timeout_job.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 . + * + * 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 + +#include "dpd_timeout_job.h" + +#include +#include + + +typedef struct private_dpd_timeout_job_t private_dpd_timeout_job_t; + +/** + * Private data + */ +struct private_dpd_timeout_job_t { + + /** + * public dpd_timeout_job_t interface + */ + dpd_timeout_job_t public; + + /** + * IKE_SA identifier + */ + ike_sa_id_t *ike_sa_id; + + /** + * Timestamp of first DPD check + */ + u_int32_t check; +}; + +METHOD(job_t, destroy, void, + private_dpd_timeout_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +METHOD(job_t, execute, void, + private_dpd_timeout_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa) + { + /* check if no incoming packet during timeout, reestalish SA */ + if (ike_sa->get_statistic(ike_sa, STAT_INBOUND) < this->check) + { + DBG1(DBG_JOB, "DPD check timed out, enforcing DPD action"); + if (ike_sa->reestablish(ike_sa) == SUCCESS) + { + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + destroy(this); +} + +METHOD(job_t, get_priority, job_priority_t, + private_dpd_timeout_job_t *this) +{ + return JOB_PRIO_HIGH; +} + +/* + * Described in header + */ +dpd_timeout_job_t *dpd_timeout_job_create(ike_sa_id_t *ike_sa_id) +{ + private_dpd_timeout_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .get_priority = _get_priority, + .destroy = _destroy, + }, + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + .check = time_monotonic(NULL), + ); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/dpd_timeout_job.h b/src/libcharon/processing/jobs/dpd_timeout_job.h new file mode 100644 index 0000000..573eb19 --- /dev/null +++ b/src/libcharon/processing/jobs/dpd_timeout_job.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 . + * + * 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. + */ + +/** + * @defgroup dpd_timeout_job dpd_timeout_job + * @{ @ingroup cjobs + */ + +#ifndef DPD_TIMEOUT_JOB_H_ +#define DPD_TIMEOUT_JOB_H_ + +typedef struct dpd_timeout_job_t dpd_timeout_job_t; + +#include +#include +#include + +/** + * Job enforcing DPD timeout. + * + * This job detects if a DPD response has been received during the DPD timeout + * interval, and if not, enforced the DPD action. + */ +struct dpd_timeout_job_t { + + /** + * implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a DPD timeout job. + * + * @param ike_sa_id ike_sa_id_t, gets cloned + * @return initiate_ike_sa_job_t object + */ +dpd_timeout_job_t *dpd_timeout_job_create(ike_sa_id_t *ike_sa_id); + +#endif /** DPD_TIMEOUT_JOB_H_ @}*/ diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 891f3d6..2e29267 100755 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -35,6 +35,7 @@ #include #include +#include /** * Number of old messages hashes we keep for retransmission. @@ -1358,8 +1359,20 @@ METHOD(task_manager_t, queue_child_delete, void, METHOD(task_manager_t, queue_dpd, void, private_task_manager_t *this) { + u_int32_t t = 0, retransmit; + queue_task(this, (task_t*)isakmp_dpd_create(this->ike_sa, TRUE, this->dpd_send++)); + + /* schedule DPD timeout job using the same timeout as a retransmitting + * IKE message would have. */ + for (retransmit = 0; retransmit <= this->retransmit_tries; retransmit++) + { + t += (u_int32_t)(this->retransmit_timeout * 1000.0 * + pow(this->retransmit_base, retransmit)); + } + lib->scheduler->schedule_job_ms(lib->scheduler, + (job_t*)dpd_timeout_job_create(this->ike_sa->get_id(this->ike_sa)), t); } METHOD(task_manager_t, adopt_tasks, void, -- 2.7.4