diff options
Diffstat (limited to 'src/libcharon/processing/jobs')
23 files changed, 612 insertions, 74 deletions
diff --git a/src/libcharon/processing/jobs/acquire_job.c b/src/libcharon/processing/jobs/acquire_job.c index 2d836b002..207f534ba 100644 --- a/src/libcharon/processing/jobs/acquire_job.c +++ b/src/libcharon/processing/jobs/acquire_job.c @@ -53,12 +53,12 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_acquire_job_t *this) { charon->traps->acquire(charon->traps, this->reqid, this->src_ts, this->dst_ts); - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c new file mode 100644 index 000000000..df5b70c0f --- /dev/null +++ b/src/libcharon/processing/jobs/adopt_children_job.c @@ -0,0 +1,177 @@ +/* + * 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 <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 "adopt_children_job.h" + +#include <daemon.h> +#include <hydra.h> + +typedef struct private_adopt_children_job_t private_adopt_children_job_t; + +/** + * Private data of an adopt_children_job_t object. + */ +struct private_adopt_children_job_t { + + /** + * Public adopt_children_job_t interface. + */ + adopt_children_job_t public; + + /** + * IKE_SA id to adopt children from + */ + ike_sa_id_t *id; +}; + +METHOD(job_t, destroy, void, + private_adopt_children_job_t *this) +{ + this->id->destroy(this->id); + free(this); +} + +METHOD(job_t, execute, job_requeue_t, + private_adopt_children_job_t *this) +{ + identification_t *my_id, *other_id, *xauth; + host_t *me, *other; + peer_cfg_t *cfg; + linked_list_t *children; + enumerator_t *enumerator, *childenum; + ike_sa_id_t *id; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->id); + if (ike_sa) + { + /* get what we need from new SA */ + me = ike_sa->get_my_host(ike_sa); + me = me->clone(me); + other = ike_sa->get_other_host(ike_sa); + other = other->clone(other); + my_id = ike_sa->get_my_id(ike_sa); + my_id = my_id->clone(my_id); + other_id = ike_sa->get_other_id(ike_sa); + other_id = other_id->clone(other_id); + xauth = ike_sa->get_other_eap_id(ike_sa); + xauth = xauth->clone(xauth); + cfg = ike_sa->get_peer_cfg(ike_sa); + cfg->get_ref(cfg); + + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + + /* find old SA to adopt children from */ + children = linked_list_create(); + enumerator = charon->ike_sa_manager->create_id_enumerator( + charon->ike_sa_manager, my_id, xauth, + other->get_family(other)); + while (enumerator->enumerate(enumerator, &id)) + { + if (id->equals(id, this->id)) + { /* not from self */ + continue; + } + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + if (ike_sa) + { + if ((ike_sa->get_state(ike_sa) == IKE_ESTABLISHED || + ike_sa->get_state(ike_sa) == IKE_PASSIVE) && + me->equals(me, ike_sa->get_my_host(ike_sa)) && + other->equals(other, ike_sa->get_other_host(ike_sa)) && + other_id->equals(other_id, ike_sa->get_other_id(ike_sa)) && + cfg->equals(cfg, ike_sa->get_peer_cfg(ike_sa))) + { + childenum = ike_sa->create_child_sa_enumerator(ike_sa); + while (childenum->enumerate(childenum, &child_sa)) + { + ike_sa->remove_child_sa(ike_sa, childenum); + children->insert_last(children, child_sa); + } + childenum->destroy(childenum); + DBG1(DBG_IKE, "detected reauth of existing IKE_SA, " + "adopting %d children", children->get_count(children)); + ike_sa->set_state(ike_sa, IKE_DELETING); + charon->bus->ike_updown(charon->bus, ike_sa, FALSE); + 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); + } + if (children->get_count(children)) + { + break; + } + } + } + enumerator->destroy(enumerator); + + me->destroy(me); + other->destroy(other); + my_id->destroy(my_id); + other_id->destroy(other_id); + xauth->destroy(xauth); + cfg->destroy(cfg); + + if (children->get_count(children)) + { + /* adopt children by new SA */ + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->id); + if (ike_sa) + { + while (children->remove_last(children, + (void**)&child_sa) == SUCCESS) + { + ike_sa->add_child_sa(ike_sa, child_sa); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + children->destroy_offset(children, offsetof(child_sa_t, destroy)); + } + return JOB_REQUEUE_NONE; +} + +METHOD(job_t, get_priority, job_priority_t, + private_adopt_children_job_t *this) +{ + return JOB_PRIO_HIGH; +} + +/** + * See header + */ +adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id) +{ + private_adopt_children_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .get_priority = _get_priority, + .destroy = _destroy, + }, + }, + .id = id->clone(id), + ); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/adopt_children_job.h b/src/libcharon/processing/jobs/adopt_children_job.h new file mode 100644 index 000000000..073504abd --- /dev/null +++ b/src/libcharon/processing/jobs/adopt_children_job.h @@ -0,0 +1,49 @@ +/* + * 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 <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. + */ + +/** + * @defgroup adopt_children_job adopt_children_job + * @{ @ingroup cjobs + */ + +#ifndef ADOPT_CHILDREN_JOB_H_ +#define ADOPT_CHILDREN_JOB_H_ + +#include <library.h> +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +typedef struct adopt_children_job_t adopt_children_job_t; + +/** + * Job adopting children after IKEv1 reauthentication from old SA. + */ +struct adopt_children_job_t { + + /** + * Implements job_t. + */ + job_t job_interface; +}; + +/** + * Create a adopt_children_job instance. + * + * @param id ike_sa_id_t of old ISAKMP SA to adopt children from + * @return job + */ +adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id); + +#endif /** ADOPT_CHILDREN_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c index bd8bb9562..9afbac02b 100644 --- a/src/libcharon/processing/jobs/delete_child_sa_job.c +++ b/src/libcharon/processing/jobs/delete_child_sa_job.c @@ -44,6 +44,11 @@ struct private_delete_child_sa_job_t { * inbound SPI of the CHILD_SA */ u_int32_t spi; + + /** + * Delete for an expired CHILD_SA + */ + bool expired; }; METHOD(job_t, destroy, void, @@ -52,7 +57,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_delete_child_sa_job_t *this) { ike_sa_t *ike_sa; @@ -66,11 +71,11 @@ METHOD(job_t, execute, void, } else { - ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi); + ike_sa->delete_child_sa(ike_sa, this->protocol, this->spi, this->expired); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, @@ -83,8 +88,7 @@ METHOD(job_t, get_priority, job_priority_t, * Described in header */ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, - protocol_id_t protocol, - u_int32_t spi) + protocol_id_t protocol, u_int32_t spi, bool expired) { private_delete_child_sa_job_t *this; @@ -99,6 +103,7 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, .reqid = reqid, .protocol = protocol, .spi = spi, + .expired = expired, ); return &this->public; diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.h b/src/libcharon/processing/jobs/delete_child_sa_job.h index fc0e2b518..be6d578bc 100644 --- a/src/libcharon/processing/jobs/delete_child_sa_job.h +++ b/src/libcharon/processing/jobs/delete_child_sa_job.h @@ -50,10 +50,10 @@ struct delete_child_sa_job_t { * @param reqid reqid of the CHILD_SA, as used in kernel * @param protocol protocol of the CHILD_SA * @param spi security parameter index of the CHILD_SA + * @param expired TRUE if CHILD_SA already expired * @return delete_child_sa_job_t object */ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, - protocol_id_t protocol, - u_int32_t spi); + protocol_id_t protocol, u_int32_t spi, bool expired); #endif /** DELETE_CHILD_SA_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c index c29b72230..08b41af8c 100644 --- a/src/libcharon/processing/jobs/delete_ike_sa_job.c +++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c @@ -48,7 +48,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_delete_ike_sa_job_t *this) { ike_sa_t *ike_sa; @@ -60,7 +60,7 @@ METHOD(job_t, execute, void, if (ike_sa->get_state(ike_sa) == IKE_PASSIVE) { charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - return destroy(this); + return JOB_REQUEUE_NONE; } if (this->delete_if_established) { @@ -89,7 +89,7 @@ METHOD(job_t, execute, void, } } } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, 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 000000000..91a76bbaf --- /dev/null +++ b/src/libcharon/processing/jobs/dpd_timeout_job.c @@ -0,0 +1,118 @@ +/* + * 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 <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 <stdlib.h> + +#include "dpd_timeout_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +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 + */ + time_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, job_requeue_t, + private_dpd_timeout_job_t *this) +{ + time_t use_time, current; + enumerator_t *enumerator; + child_sa_t *child_sa; + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa) + { + use_time = ike_sa->get_statistic(ike_sa, STAT_INBOUND); + + enumerator = ike_sa->create_child_sa_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, &child_sa)) + { + child_sa->get_usestats(child_sa, TRUE, ¤t, NULL); + use_time = max(use_time, current); + } + enumerator->destroy(enumerator); + + /* check if no incoming packet during timeout, reestablish SA */ + if (use_time < this->check) + { + DBG1(DBG_JOB, "DPD check timed out, enforcing DPD action"); + ike_sa->reestablish(ike_sa); + 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); + } + } + return JOB_REQUEUE_NONE; +} + +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 000000000..573eb192d --- /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 <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. + */ + +/** + * @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 <library.h> +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +/** + * 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/processing/jobs/inactivity_job.c b/src/libcharon/processing/jobs/inactivity_job.c index 251b9ab03..3c56b0cd7 100644 --- a/src/libcharon/processing/jobs/inactivity_job.c +++ b/src/libcharon/processing/jobs/inactivity_job.c @@ -51,11 +51,11 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_inactivity_job_t *this) { ike_sa_t *ike_sa; - bool rescheduled = FALSE; + u_int32_t reschedule = 0; ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, this->reqid, TRUE); @@ -87,9 +87,7 @@ METHOD(job_t, execute, void, } else { - lib->scheduler->schedule_job(lib->scheduler, - &this->public.job_interface, this->timeout - diff); - rescheduled = TRUE; + reschedule = this->timeout - diff; } } children++; @@ -108,7 +106,7 @@ METHOD(job_t, execute, void, { DBG1(DBG_JOB, "deleting CHILD_SA after %d seconds " "of inactivity", this->timeout); - status = ike_sa->delete_child_sa(ike_sa, proto, delete); + status = ike_sa->delete_child_sa(ike_sa, proto, delete, FALSE); } } if (status == DESTROY_ME) @@ -121,10 +119,11 @@ METHOD(job_t, execute, void, charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } - if (!rescheduled) + if (reschedule) { - destroy(this); + return JOB_RESCHEDULE(reschedule); } + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c index e52f3c6df..17ab83053 100644 --- a/src/libcharon/processing/jobs/initiate_mediation_job.c +++ b/src/libcharon/processing/jobs/initiate_mediation_job.c @@ -54,7 +54,7 @@ METHOD(job_t, destroy, void, */ static bool initiate_callback(private_initiate_mediation_job_t *this, debug_t group, level_t level, ike_sa_t *ike_sa, - char *format, va_list args) + char *message) { if (ike_sa && !this->mediation_sa_id) { @@ -64,7 +64,7 @@ static bool initiate_callback(private_initiate_mediation_job_t *this, return TRUE; } -METHOD(job_t, initiate, void, +METHOD(job_t, initiate, job_requeue_t, private_initiate_mediation_job_t *this) { ike_sa_t *mediated_sa, *mediation_sa; @@ -93,8 +93,7 @@ METHOD(job_t, initiate, void, mediated_cfg->destroy(mediated_cfg); mediation_cfg->destroy(mediation_cfg); enumerator->destroy(enumerator); - destroy(this); - return; + return JOB_REQUEUE_NONE; } enumerator->destroy(enumerator); @@ -115,8 +114,7 @@ METHOD(job_t, initiate, void, charon->ike_sa_manager->checkin( charon->ike_sa_manager, mediated_sa); } - destroy(this); - return; + return JOB_REQUEUE_NONE; } /* we need an additional reference because initiate consumes one */ mediation_cfg->get_ref(mediation_cfg); @@ -134,8 +132,7 @@ METHOD(job_t, initiate, void, charon->ike_sa_manager->checkin_and_destroy( charon->ike_sa_manager, mediated_sa); } - destroy(this); - return; + return JOB_REQUEUE_NONE; } mediation_cfg->destroy(mediation_cfg); @@ -157,18 +154,17 @@ METHOD(job_t, initiate, void, charon->ike_sa_manager->checkin_and_destroy( charon->ike_sa_manager, mediated_sa); } - destroy(this); - return; + return JOB_REQUEUE_NONE; } charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediation_sa); } mediated_cfg->destroy(mediated_cfg); } - destroy(this); + return JOB_REQUEUE_NONE; } -METHOD(job_t, reinitiate, void, +METHOD(job_t, reinitiate, job_requeue_t, private_initiate_mediation_job_t *this) { ike_sa_t *mediated_sa, *mediation_sa; @@ -205,8 +201,7 @@ METHOD(job_t, reinitiate, void, charon->ike_sa_manager, mediated_sa); } - destroy(this); - return; + return JOB_REQUEUE_NONE; } charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediation_sa); @@ -214,7 +209,7 @@ METHOD(job_t, reinitiate, void, mediated_cfg->destroy(mediated_cfg); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/mediation_job.c b/src/libcharon/processing/jobs/mediation_job.c index 6f02f2a0a..759aad003 100644 --- a/src/libcharon/processing/jobs/mediation_job.c +++ b/src/libcharon/processing/jobs/mediation_job.c @@ -77,7 +77,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_mediation_job_t *this) { ike_sa_id_t *target_sa_id; @@ -98,8 +98,7 @@ METHOD(job_t, execute, void, DBG1(DBG_JOB, "callback for '%Y' to '%Y' failed", this->source, this->target); charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa); - destroy(this); - return; + return JOB_REQUEUE_NONE; } } else @@ -112,8 +111,7 @@ METHOD(job_t, execute, void, this->source, this->target); charon->ike_sa_manager->checkin(charon->ike_sa_manager, target_sa); /* FIXME: notify the initiator */ - destroy(this); - return; + return JOB_REQUEUE_NONE; } } @@ -130,7 +128,7 @@ METHOD(job_t, execute, void, DBG1(DBG_JOB, "mediation between '%Y' and '%Y' failed: " "peer is not online anymore", this->source, this->target); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c index eb10e2e46..2ebfc6714 100644 --- a/src/libcharon/processing/jobs/migrate_job.c +++ b/src/libcharon/processing/jobs/migrate_job.c @@ -67,7 +67,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_migrate_job_t *this) { ike_sa_t *ike_sa = NULL; @@ -79,9 +79,10 @@ METHOD(job_t, execute, void, } if (ike_sa) { - enumerator_t *children; + enumerator_t *children, *enumerator; child_sa_t *child_sa; host_t *host; + linked_list_t *vips; children = ike_sa->create_child_sa_enumerator(ike_sa); while (children->enumerate(children, (void**)&child_sa)) @@ -97,27 +98,35 @@ METHOD(job_t, execute, void, ike_sa->set_kmaddress(ike_sa, this->local, this->remote); host = this->local->clone(this->local); - host->set_port(host, IKEV2_UDP_PORT); + host->set_port(host, charon->socket->get_port(charon->socket, FALSE)); ike_sa->set_my_host(ike_sa, host); host = this->remote->clone(this->remote); host->set_port(host, IKEV2_UDP_PORT); ike_sa->set_other_host(ike_sa, host); - if (child_sa->update(child_sa, this->local, this->remote, - ike_sa->get_virtual_ip(ike_sa, TRUE), + vips = linked_list_create(); + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE); + while (enumerator->enumerate(enumerator, &host)) + { + vips->insert_last(vips, host); + } + enumerator->destroy(enumerator); + + if (child_sa->update(child_sa, this->local, this->remote, vips, ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED) { ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), child_sa->get_spi(child_sa, TRUE)); } charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + vips->destroy(vips); } else { DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c index a4924d001..71a2cb45d 100644 --- a/src/libcharon/processing/jobs/process_message_job.c +++ b/src/libcharon/processing/jobs/process_message_job.c @@ -42,7 +42,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_process_message_job_t *this) { ike_sa_t *ike_sa; @@ -59,8 +59,7 @@ METHOD(job_t, execute, void, this->message->get_source(this->message), this->message->get_destination(this->message)); charon->connect_manager->process_check(charon->connect_manager, this->message); - destroy(this); - return; + return JOB_REQUEUE_NONE; } #endif /* ME */ @@ -81,7 +80,7 @@ METHOD(job_t, execute, void, charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c index 5855f1bc9..1bf8dc0cb 100644 --- a/src/libcharon/processing/jobs/rekey_child_sa_job.c +++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c @@ -51,7 +51,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_rekey_child_sa_job_t *this) { ike_sa_t *ike_sa; @@ -68,7 +68,7 @@ METHOD(job_t, execute, void, ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c index 5366195fd..712c7c2c1 100644 --- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c +++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c @@ -46,7 +46,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_rekey_ike_sa_job_t *this) { ike_sa_t *ike_sa; @@ -78,7 +78,7 @@ METHOD(job_t, execute, void, charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/retransmit_job.c b/src/libcharon/processing/jobs/retransmit_job.c index 050f7005a..48c326804 100644 --- a/src/libcharon/processing/jobs/retransmit_job.c +++ b/src/libcharon/processing/jobs/retransmit_job.c @@ -47,7 +47,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_retransmit_job_t *this) { ike_sa_t *ike_sa; @@ -67,7 +67,7 @@ METHOD(job_t, execute, void, charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/retry_initiate_job.c b/src/libcharon/processing/jobs/retry_initiate_job.c new file mode 100644 index 000000000..1cdc3058a --- /dev/null +++ b/src/libcharon/processing/jobs/retry_initiate_job.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * 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 "retry_initiate_job.h" + +#include <daemon.h> + +typedef struct private_retry_initiate_job_t private_retry_initiate_job_t; + +/** + * Private data of an retry_initiate_job_t object. + */ +struct private_retry_initiate_job_t { + /** + * Public retry_initiate_job_t interface. + */ + retry_initiate_job_t public; + + /** + * ID of the IKE_SA to re-initiate + */ + ike_sa_id_t *ike_sa_id; +}; + +METHOD(job_t, destroy, void, + private_retry_initiate_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +METHOD(job_t, execute, job_requeue_t, + private_retry_initiate_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 == NULL) + { + DBG2(DBG_JOB, "IKE_SA to initiate not found"); + } + else + { + if (ike_sa->retry_initiate(ike_sa) == DESTROY_ME) + { + 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); + } + } + return JOB_REQUEUE_NONE; +} + +METHOD(job_t, get_priority, job_priority_t, + private_retry_initiate_job_t *this) +{ + return JOB_PRIO_HIGH; +} + +/* + * Described in header + */ +retry_initiate_job_t *retry_initiate_job_create(ike_sa_id_t *ike_sa_id) +{ + private_retry_initiate_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), + ); + + return &(this->public); +} diff --git a/src/libcharon/processing/jobs/retry_initiate_job.h b/src/libcharon/processing/jobs/retry_initiate_job.h new file mode 100644 index 000000000..29f79f23b --- /dev/null +++ b/src/libcharon/processing/jobs/retry_initiate_job.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * 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. + */ + +/** + * @defgroup retry_initiate_job retry_initiate_job + * @{ @ingroup cjobs + */ + +#ifndef RETRY_INITIATE_JOB_H_ +#define RETRY_INITIATE_JOB_H_ + +typedef struct retry_initiate_job_t retry_initiate_job_t; + +#include <library.h> +#include <sa/ike_sa_id.h> +#include <processing/jobs/job.h> + +/** + * This job retries initiating an IKE_SA in case of e.g. a failed DNS lookup. + */ +struct retry_initiate_job_t { + /** + * The job_t interface. + */ + job_t job_interface; +}; + +/** + * Creates a retry_initiate_job_t object. + * + * @param ike_sa_id ID of the IKE_SA to initiate + * @return retry_initiate_job_t object + */ +retry_initiate_job_t *retry_initiate_job_create(ike_sa_id_t *ike_sa_id); + +#endif /** RETRY_INITIATE_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/roam_job.c b/src/libcharon/processing/jobs/roam_job.c index 951ac5ad3..0af4c6c39 100644 --- a/src/libcharon/processing/jobs/roam_job.c +++ b/src/libcharon/processing/jobs/roam_job.c @@ -44,7 +44,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_roam_job_t *this) { ike_sa_t *ike_sa; @@ -82,8 +82,7 @@ METHOD(job_t, execute, void, id->destroy(id); } list->destroy(list); - - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/send_dpd_job.c b/src/libcharon/processing/jobs/send_dpd_job.c index ab00d013d..d2f38b803 100644 --- a/src/libcharon/processing/jobs/send_dpd_job.c +++ b/src/libcharon/processing/jobs/send_dpd_job.c @@ -45,7 +45,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_send_dpd_job_t *this) { ike_sa_t *ike_sa; @@ -63,7 +63,7 @@ METHOD(job_t, execute, void, charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/send_keepalive_job.c b/src/libcharon/processing/jobs/send_keepalive_job.c index 5e128d478..3e3477679 100644 --- a/src/libcharon/processing/jobs/send_keepalive_job.c +++ b/src/libcharon/processing/jobs/send_keepalive_job.c @@ -45,7 +45,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_send_keepalive_job_t *this) { ike_sa_t *ike_sa; @@ -57,7 +57,7 @@ METHOD(job_t, execute, void, ike_sa->send_keepalive(ike_sa); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c index b65181ef8..bc4aaf6d6 100644 --- a/src/libcharon/processing/jobs/start_action_job.c +++ b/src/libcharon/processing/jobs/start_action_job.c @@ -36,7 +36,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_start_action_job_t *this) { enumerator_t *enumerator, *children; @@ -46,14 +46,9 @@ METHOD(job_t, execute, void, char *name; enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, IKE_ANY); while (enumerator->enumerate(enumerator, &peer_cfg)) { - if (peer_cfg->get_ike_version(peer_cfg) != 2) - { - continue; - } - children = peer_cfg->create_child_cfg_enumerator(peer_cfg); while (children->enumerate(children, &child_cfg)) { @@ -88,7 +83,7 @@ METHOD(job_t, execute, void, children->destroy(children); } enumerator->destroy(enumerator); - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c index c4f6e4782..694318522 100644 --- a/src/libcharon/processing/jobs/update_sa_job.c +++ b/src/libcharon/processing/jobs/update_sa_job.c @@ -50,7 +50,7 @@ METHOD(job_t, destroy, void, free(this); } -METHOD(job_t, execute, void, +METHOD(job_t, execute, job_requeue_t, private_update_sa_job_t *this) { ike_sa_t *ike_sa; @@ -71,7 +71,7 @@ METHOD(job_t, execute, void, } charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } - destroy(this); + return JOB_REQUEUE_NONE; } METHOD(job_t, get_priority, job_priority_t, |