using dpd actions to enforce connection state

dpd actions a per child-, not peer ike-sa
This commit is contained in:
Martin Willi
2008-04-11 08:14:48 +00:00
parent 4a6474c2c3
commit 96926b006d
12 changed files with 264 additions and 239 deletions
+25 -6
View File
@@ -28,6 +28,12 @@ ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
"BEET",
);
ENUM(action_names, ACTION_NONE, ACTION_RESTART,
"ACTION_NONE",
"ACTION_ROUTE",
"ACTION_RESTART",
);
typedef struct private_child_cfg_t private_child_cfg_t;
/**
@@ -80,6 +86,11 @@ struct private_child_cfg_t {
*/
mode_t mode;
/**
* action to take on DPD/passive close
*/
action_t action;
/**
* Time before an SA gets invalid
*/
@@ -338,13 +349,21 @@ static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
}
/**
* Implementation of child_cfg_t.get_name
* Implementation of child_cfg_t.get_mode
*/
static mode_t get_mode(private_child_cfg_t *this)
{
return this->mode;
}
/**
* Implementation of child_cfg_t.get_action
*/
static action_t get_action(private_child_cfg_t *this)
{
return this->action;
}
/**
* Implementation of child_cfg_t.get_dh_group.
*/
@@ -398,11 +417,11 @@ static void destroy(private_child_cfg_t *this)
*/
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess, mode_t mode)
char *updown, bool hostaccess, mode_t mode,
action_t action)
{
private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
/* public functions */
this->public.get_name = (char* (*) (child_cfg_t*))get_name;
this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
@@ -412,12 +431,12 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode;
this->public.get_action = (action_t (*) (child_cfg_t *))get_action;
this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
this->public.get_dh_group = (diffie_hellman_group_t(*)(child_cfg_t*)) get_dh_group;
this->public.get_ref = (void (*) (child_cfg_t*))get_ref;
this->public.destroy = (void (*) (child_cfg_t*))destroy;
/* apply init values */
this->name = strdup(name);
this->lifetime = lifetime;
this->rekeytime = rekeytime;
@@ -425,8 +444,7 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
this->updown = updown ? strdup(updown) : NULL;
this->hostaccess = hostaccess;
this->mode = mode;
/* initialize private members*/
this->action = action;
this->refcount = 1;
this->proposals = linked_list_create();
this->my_ts = linked_list_create();
@@ -434,3 +452,4 @@ child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
return &this->public;
}
+29 -2
View File
@@ -25,6 +25,7 @@
#define CHILD_CFG_H_
typedef enum mode_t mode_t;
typedef enum action_t action_t;
typedef struct child_cfg_t child_cfg_t;
#include <library.h>
@@ -50,6 +51,23 @@ enum mode_t {
*/
extern enum_name_t *mode_names;
/**
* Action to take when DPD detected/connection gets closed by peer.
*/
enum action_t {
/** No action */
ACTION_NONE,
/** Route config to reestablish on demand */
ACTION_ROUTE,
/** Restart config immediately */
ACTION_RESTART,
};
/**
* enum names for action_t.
*/
extern enum_name_t *action_names;
/**
* A child_cfg_t defines the config template for a CHILD_SA.
*
@@ -170,10 +188,17 @@ struct child_cfg_t {
* The mode is either tunnel, transport or BEET. The peer must agree
* on the method, fallback is tunnel mode.
*
* @return lifetime in seconds
* @return ipsec mode
*/
mode_t (*get_mode) (child_cfg_t *this);
/**
* Action to take on DPD/passive close
*
* @return DPD/passive close action
*/
action_t (*get_action) (child_cfg_t *this);
/**
* Get the DH group to use for CHILD_SA setup.
*
@@ -218,10 +243,12 @@ struct child_cfg_t {
* @param updown updown script to execute on up/down event
* @param hostaccess TRUE to allow access to the local host
* @param mode mode to propose for CHILD_SA, transport, tunnel or BEET
* @param action DPD/passive close action
* @return child_cfg_t object
*/
child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
u_int32_t rekeytime, u_int32_t jitter,
char *updown, bool hostaccess, mode_t mode);
char *updown, bool hostaccess, mode_t mode,
action_t action);
#endif /* CHILD_CFG_H_ @} */
+9 -33
View File
@@ -31,13 +31,6 @@ ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
"CERT_NEVER_SEND"
);
ENUM(dpd_action_names, DPD_NONE, DPD_RESTART,
"DPD_NONE",
"DPD_CLEAR",
"DPD_ROUTE",
"DPD_RESTART"
);
typedef struct private_peer_cfg_t private_peer_cfg_t;
/**
@@ -141,14 +134,9 @@ struct private_peer_cfg_t {
u_int32_t over_time;
/**
* What to do with an SA when other peer seams to be dead?
* DPD check intervall
*/
bool dpd_delay;
/**
* What to do with CHILDren when other peer seams to be dead?
*/
bool dpd_action;
u_int32_t dpd;
/**
* virtual IP to use locally
@@ -380,19 +368,11 @@ static bool use_mobike(private_peer_cfg_t *this)
}
/**
* Implements peer_cfg_t.get_dpd_delay
* Implements peer_cfg_t.get_dpd
*/
static u_int32_t get_dpd_delay(private_peer_cfg_t *this)
static u_int32_t get_dpd(private_peer_cfg_t *this)
{
return this->dpd_delay;
}
/**
* Implements peer_cfg_t.get_dpd_action
*/
static dpd_action_t get_dpd_action(private_peer_cfg_t *this)
{
return this->dpd_action;
return this->dpd;
}
/**
@@ -473,8 +453,7 @@ static bool equals(private_peer_cfg_t *this, private_peer_cfg_t *other)
this->reauth_time == other->reauth_time &&
this->jitter_time == other->jitter_time &&
this->over_time == other->over_time &&
this->dpd_delay == other->dpd_delay &&
this->dpd_action == other->dpd_action &&
this->dpd == other->dpd &&
(this->virtual_ip == other->virtual_ip ||
(this->virtual_ip && other->virtual_ip &&
this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
@@ -531,8 +510,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
u_int32_t eap_vendor,
u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike,
u_int32_t dpd_delay, dpd_action_t dpd_action,
u_int32_t over_time, bool mobike, u_int32_t dpd,
host_t *virtual_ip, char *pool,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id)
@@ -557,8 +535,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->public.get_reauth_time = (u_int32_t(*)(peer_cfg_t*))get_reauth_time;
this->public.get_over_time = (u_int32_t(*)(peer_cfg_t*))get_over_time;
this->public.use_mobike = (bool (*) (peer_cfg_t *))use_mobike;
this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay;
this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action;
this->public.get_dpd = (u_int32_t (*) (peer_cfg_t *))get_dpd;
this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *))get_virtual_ip;
this->public.get_pool = (char*(*)(peer_cfg_t*))get_pool;
this->public.get_auth = (auth_info_t*(*)(peer_cfg_t*))get_auth;
@@ -597,8 +574,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
this->jitter_time = jitter_time;
this->over_time = over_time;
this->use_mobike = mobike;
this->dpd_delay = dpd_delay;
this->dpd_action = dpd_action;
this->dpd = dpd;
this->virtual_ip = virtual_ip;
this->pool = pool ? strdup(pool) : NULL;
this->auth = auth_info_create();
+3 -34
View File
@@ -25,7 +25,6 @@
#ifndef PEER_CFG_H_
#define PEER_CFG_H_
typedef enum dpd_action_t dpd_action_t;
typedef enum cert_policy_t cert_policy_t;
typedef struct peer_cfg_t peer_cfg_t;
@@ -63,27 +62,6 @@ enum cert_policy_t {
*/
extern enum_name_t *cert_policy_names;
/**
* Actions to take when a peer does not respond (dead peer detected).
*
* These values are the same as in pluto/starter, so do not modify them!
*/
enum dpd_action_t {
/** DPD disabled */
DPD_NONE,
/** remove CHILD_SAs without replacement */
DPD_CLEAR,
/** route the CHILD_SAs to resetup when needed */
DPD_ROUTE,
/** restart CHILD_SAs in a new IKE_SA, immediately */
DPD_RESTART,
};
/**
* enum names for dpd_action_t.
*/
extern enum_name_t *dpd_action_names;
/**
* Configuration of a peer, specified by IDs.
*
@@ -259,14 +237,7 @@ struct peer_cfg_t {
*
* @return dpd_delay in seconds
*/
u_int32_t (*get_dpd_delay) (peer_cfg_t *this);
/**
* What should be done with a CHILD_SA, when other peer does not respond.
*
* @return dpd action
*/
dpd_action_t (*get_dpd_action) (peer_cfg_t *this);
u_int32_t (*get_dpd) (peer_cfg_t *this);
/**
* Get a virtual IP for the local peer.
@@ -371,8 +342,7 @@ struct peer_cfg_t {
* @param over_time maximum overtime before closing a rekeying/reauth SA
* @param reauth sould be done reauthentication instead of rekeying?
* @param mobike use MOBIKE (RFC4555) if peer supports it
* @param dpd_delay after how many seconds of inactivity to check DPD
* @param dpd_action what to do with CHILD_SAs when detected a dead peer
* @param dpd DPD check interval, 0 to disable
* @param virtual_ip virtual IP for local host, or NULL
* @param pool pool name to get configuration attributes from, or NULL
* @param mediation TRUE if this is a mediation connection
@@ -387,8 +357,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
u_int32_t eap_vendor,
u_int32_t keyingtries, u_int32_t rekey_time,
u_int32_t reauth_time, u_int32_t jitter_time,
u_int32_t over_time, bool mobike,
u_int32_t dpd_delay, dpd_action_t dpd_action,
u_int32_t over_time, bool mobike, u_int32_t dpd,
host_t *virtual_ip, char *pool,
bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id);
+2 -2
View File
@@ -133,7 +133,7 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
&updown, &hostaccess, &mode))
{
child_cfg = child_cfg_create(name, lifetime, rekeytime, jitter,
updown, hostaccess, mode);
updown, hostaccess, mode, ACTION_NONE);
/* TODO: read proposal from db */
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
add_traffic_selectors(this, child_cfg, id);
@@ -311,7 +311,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
name, 2, ike, local_id, remote_id, cert_policy,
auth_method, eap_type, eap_vendor, keyingtries,
rekeytime, reauthtime, jitter, overtime, mobike,
dpd_delay, dpd_action, NULL, NULL,
dpd_delay, NULL, NULL,
mediation, mediated_cfg, peer_id);
add_child_cfgs(this, peer_cfg, id);
return peer_cfg;
+15 -2
View File
@@ -491,7 +491,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
msg->add_conn.me.sendcert, msg->add_conn.auth_method,
msg->add_conn.eap_type, msg->add_conn.eap_vendor,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.dpd.delay, msg->add_conn.dpd.action,
msg->add_conn.mobike, msg->add_conn.dpd.delay,
vip, msg->add_conn.other.sourceip ? msg->add_conn.name : NULL,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
}
@@ -626,13 +626,26 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
{
child_cfg_t *child_cfg;
traffic_selector_t *ts;
action_t action;
switch (msg->add_conn.dpd.action)
{ /* map startes magic values to our action type */
case 2: /* =hold */
action = ACTION_ROUTE;
break;
case 3: /* =restart */
action = ACTION_RESTART;
break;
default:
action = ACTION_NONE;
break;
}
child_cfg = child_cfg_create(
msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime,
msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode);
msg->add_conn.mode, action);
ts = build_ts(this, &msg->add_conn.me);
if (!ts)
@@ -68,7 +68,7 @@ static void execute(private_rekey_ike_sa_job_t *this)
{
if (this->reauth)
{
status = ike_sa->reestablish(ike_sa);
status = ike_sa->reauth(ike_sa);
}
else
{
+135 -147
View File
@@ -599,7 +599,7 @@ static status_t send_dpd(private_ike_sa_t *this)
send_dpd_job_t *job;
time_t diff, delay;
delay = this->peer_cfg->get_dpd_delay(this->peer_cfg);
delay = this->peer_cfg->get_dpd(this->peer_cfg);
if (delay == 0)
{
@@ -1434,147 +1434,6 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
}
}
/**
* Implementation of ike_sa_t.retransmit.
*/
static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
{ /* FIXME: IKE-ME */
this->time.outbound = time(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
child_cfg_t *child_cfg;
child_sa_t* child_sa;
linked_list_t *to_route, *to_restart;
iterator_t *iterator;
/* send a proper signal to brief interested bus listeners */
switch (this->state)
{
case IKE_CONNECTING:
{
/* retry IKE_SA_INIT if we have multiple keyingtries */
u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
this->keyingtry++;
if (tries == 0 || tries > this->keyingtry)
{
SIG(IKE_UP_FAILED, "peer not responding, trying again "
"(%d/%d) in background ", this->keyingtry + 1, tries);
reset(this);
return this->task_manager->initiate(this->task_manager);
}
SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding");
break;
}
case IKE_REKEYING:
SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding");
break;
case IKE_DELETING:
SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding");
break;
default:
break;
}
/* summarize how we have to handle each child */
to_route = linked_list_create();
to_restart = linked_list_create();
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
child_cfg = child_sa->get_config(child_sa);
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
{
/* reroute routed CHILD_SAs */
to_route->insert_last(to_route, child_cfg);
}
else
{
/* use DPD action for established CHILD_SAs */
switch (this->peer_cfg->get_dpd_action(this->peer_cfg))
{
case DPD_ROUTE:
to_route->insert_last(to_route, child_cfg);
break;
case DPD_RESTART:
to_restart->insert_last(to_restart, child_cfg);
break;
default:
break;
}
}
}
iterator->destroy(iterator);
/* create a new IKE_SA if we have to route or to restart */
if (to_route->get_count(to_route) || to_restart->get_count(to_restart))
{
private_ike_sa_t *new;
task_t *task;
new = (private_ike_sa_t*)charon->ike_sa_manager->checkout_new(
charon->ike_sa_manager, TRUE);
set_peer_cfg(new, this->peer_cfg);
/* use actual used host, not the wildcarded one in config */
new->other_host->destroy(new->other_host);
new->other_host = this->other_host->clone(this->other_host);
/* reset port to 500, but only if peer is not NATed */
if (!has_condition(this, COND_NAT_THERE))
{
new->other_host->set_port(new->other_host, IKEV2_UDP_PORT);
}
/* take over virtual ip, as we need it for a proper route */
if (this->my_virtual_ip)
{
set_virtual_ip(new, TRUE, this->my_virtual_ip);
}
/* install routes */
while (to_route->remove_last(to_route, (void**)&child_cfg) == SUCCESS)
{
route(new, child_cfg);
}
/* restart children */
if (to_restart->get_count(to_restart))
{
task = (task_t*)ike_init_create(&new->public, TRUE, NULL);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_natd_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_cert_pre_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_config_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_auth_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
task = (task_t*)ike_cert_post_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
while (to_restart->remove_last(to_restart, (void**)&child_cfg) == SUCCESS)
{
task = (task_t*)child_create_create(&new->public, child_cfg);
new->task_manager->queue_task(new->task_manager, task);
}
task = (task_t*)ike_auth_lifetime_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
if (this->peer_cfg->use_mobike(this->peer_cfg))
{
task = (task_t*)ike_mobike_create(&new->public, TRUE);
new->task_manager->queue_task(new->task_manager, task);
}
new->task_manager->initiate(new->task_manager);
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, &new->public);
}
to_route->destroy(to_route);
to_restart->destroy(to_restart);
return DESTROY_ME;
}
return SUCCESS;
}
/**
* Implementation of ike_sa_t.get_prf.
*/
@@ -1978,9 +1837,9 @@ static status_t rekey(private_ike_sa_t *this)
}
/**
* Implementation of ike_sa_t.reestablish
* Implementation of ike_sa_t.reauth
*/
static status_t reestablish(private_ike_sa_t *this)
static status_t reauth(private_ike_sa_t *this)
{
task_t *task;
@@ -2014,6 +1873,134 @@ static status_t reestablish(private_ike_sa_t *this)
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.reestablish
*/
static status_t reestablish(private_ike_sa_t *this)
{
ike_sa_t *new;
host_t *host;
iterator_t *iterator;
child_sa_t *child_sa;
child_cfg_t *child_cfg;
action_t action;
bool required = FALSE;
status_t status = FAILED;
if (!this->ike_initiator &&
(this->other_virtual_ip != NULL ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
|| this->is_mediation_server
#endif /* ME */
))
{
return FAILED;
}
new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, TRUE);
new->set_peer_cfg(new, this->peer_cfg);
host = this->other_host;
new->set_other_host(new, host->clone(host));
host = this->my_host;
new->set_my_host(new, host->clone(host));
/* if we already have a virtual IP, we reuse it */
host = this->my_virtual_ip;
if (host)
{
new->set_virtual_ip(new, TRUE, host);
}
#ifdef ME
/* we initiate the new IKE_SA of the mediation connection without CHILD_SA */
if (this->peer_cfg->is_mediation(this->peer_cfg))
{
required = TRUE;
}
#endif /* ME */
iterator = create_child_sa_iterator(this);
while (iterator->iterate(iterator, (void**)&child_sa))
{
child_cfg = child_sa->get_config(child_sa);
action = child_cfg->get_action(child_cfg);
if (action == ACTION_RESTART || action == ACTION_ROUTE)
{
required = TRUE;
if (action == ACTION_RESTART)
{
DBG1(DBG_IKE, "restarting CHILD_SA %s",
child_cfg->get_name(child_cfg));
child_cfg->get_ref(child_cfg);
status = new->initiate(new, child_cfg);
if (status == DESTROY_ME)
{
required = FALSE;
break;
}
}
else
{
new->route(new, child_cfg);
}
}
}
iterator->destroy(iterator);
if (required)
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
}
else
{
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
DBG1(DBG_IKE, "unable to reestablish IKE_SA, no CHILD_SA to recreate");
}
return status;
}
/**
* Implementation of ike_sa_t.retransmit.
*/
static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
{
this->time.outbound = time(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
{
/* send a proper signal to brief interested bus listeners */
switch (this->state)
{
case IKE_CONNECTING:
{
/* retry IKE_SA_INIT if we have multiple keyingtries */
u_int32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
this->keyingtry++;
if (tries == 0 || tries > this->keyingtry)
{
SIG(IKE_UP_FAILED, "peer not responding, trying again "
"(%d/%d) in background ", this->keyingtry + 1, tries);
reset(this);
return this->task_manager->initiate(this->task_manager);
}
SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding");
break;
}
case IKE_REKEYING:
SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding");
break;
case IKE_DELETING:
SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding");
break;
default:
break;
}
reestablish(this);
return DESTROY_ME;
}
return SUCCESS;
}
/**
* Implementation of ike_sa_t.set_auth_lifetime.
*/
@@ -2087,9 +2074,9 @@ static status_t roam(private_ike_sa_t *this, bool address)
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
return this->task_manager->initiate(this->task_manager);
}
DBG1(DBG_IKE, "reestablishing IKE_SA due address change");
/* ... reestablish if not */
return reestablish(this);
DBG1(DBG_IKE, "reauthenticating IKE_SA due address change");
/* ... reauth if not */
return reauth(this);
}
/**
@@ -2436,6 +2423,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
this->public.reauth = (status_t (*)(ike_sa_t*))reauth;
this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
this->public.set_auth_lifetime = (void(*)(ike_sa_t*, u_int32_t lifetime))set_auth_lifetime;
this->public.roam = (status_t(*)(ike_sa_t*,bool))roam;
+11 -2
View File
@@ -115,7 +115,7 @@ enum ike_condition_t {
/**
* received a certificate request from the peer
*/
COND_CERTREQ_SEEN = (1<<4),
COND_CERTREQ_SEEN = (1<<5),
};
/**
@@ -803,13 +803,22 @@ struct ike_sa_t {
status_t (*rekey) (ike_sa_t *this);
/**
* Restablish the IKE_SA.
* Reauthenticate the IKE_SA.
*
* Create a completely new IKE_SA with authentication, recreates all children
* within the IKE_SA, closes this IKE_SA.
*
* @return DESTROY_ME to destroy the IKE_SA
*/
status_t (*reauth) (ike_sa_t *this);
/**
* Restablish the IKE_SA.
*
* Reestablish an IKE_SA after it has been closed.
*
* @return DESTROY_ME to destroy the IKE_SA
*/
status_t (*reestablish) (ike_sa_t *this);
/**
+29 -6
View File
@@ -152,23 +152,48 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
}
/**
* destroy the children listed in this->child_sas
* destroy the children listed in this->child_sas, reestablish by policy
*/
static void destroy_children(private_child_delete_t *this)
static status_t destroy_and_reestablish(private_child_delete_t *this)
{
iterator_t *iterator;
child_sa_t *child_sa;
child_cfg_t *child_cfg;
protocol_id_t protocol;
u_int32_t spi;
status_t status = SUCCESS;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
while (iterator->iterate(iterator, (void**)&child_sa))
{
spi = child_sa->get_spi(child_sa, TRUE);
protocol = child_sa->get_protocol(child_sa);
child_cfg = child_sa->get_config(child_sa);
child_cfg->get_ref(child_cfg);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
if (!this->initiator)
{ /* enforce child_cfg policy if deleted passively */
switch (child_cfg->get_action(child_cfg))
{
case ACTION_RESTART:
child_cfg->get_ref(child_cfg);
status = this->ike_sa->initiate(this->ike_sa, child_cfg);
break;
case ACTION_ROUTE:
status = this->ike_sa->route(this->ike_sa, child_cfg);
break;
default:
break;
}
}
child_cfg->destroy(child_cfg);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
return status;
}
/**
@@ -209,9 +234,8 @@ static status_t process_i(private_child_delete_t *this, message_t *message)
this->child_sas = linked_list_create();
process_payloads(this, message);
destroy_children(this);
SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed");
return SUCCESS;
return destroy_and_reestablish(this);
}
/**
@@ -234,9 +258,8 @@ static status_t build_r(private_child_delete_t *this, message_t *message)
{
build_payloads(this, message);
}
destroy_children(this);
SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed");
return SUCCESS;
return destroy_and_reestablish(this);
}
/**
+1
View File
@@ -87,6 +87,7 @@ static status_t process_r(private_ike_delete_t *this, message_t *message)
break;
case IKE_ESTABLISHED:
DBG1(DBG_IKE, "deleting IKE_SA on request");
this->ike_sa->reestablish(this->ike_sa);
break;
case IKE_REKEYING:
break;
+4 -4
View File
@@ -68,7 +68,7 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
/* reestablish only if we have children */
/* reauthenticate only if we have children */
iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
if (iterator->get_count(iterator) == 0
#ifdef ME
@@ -77,7 +77,7 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
#endif /* ME */
)
{
DBG1(DBG_IKE, "unable to reestablish IKE_SA, no CHILD_SA to recreate");
DBG1(DBG_IKE, "unable to reauthenticate IKE_SA, no CHILD_SA to recreate");
iterator->destroy(iterator);
return FAILED;
}
@@ -104,7 +104,7 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
{
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, new);
DBG1(DBG_IKE, "reestablishing IKE_SA failed");
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
}
@@ -131,7 +131,7 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
iterator->destroy(iterator);
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, new);
DBG1(DBG_IKE, "reestablishing IKE_SA failed");
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
return FAILED;
}
break;