further MOBIKE stuff:

kernel properly reports network reconfiguration and informs all IKE_SAs
  MOBIKE in IKE_AUTH: MOBIKE_SUPPORTED notify and address exchange
  reestablishment of IKE_SAs on network reconfiguration kinda works
  not stable yet!
This commit is contained in:
Martin Willi
2007-06-21 15:25:28 +00:00
parent c25ef47702
commit 17d92e9732
22 changed files with 1131 additions and 372 deletions
+180 -46
View File
@@ -48,6 +48,7 @@
#include <sa/task_manager.h>
#include <sa/tasks/ike_init.h>
#include <sa/tasks/ike_natd.h>
#include <sa/tasks/ike_mobike.h>
#include <sa/tasks/ike_auth.h>
#include <sa/tasks/ike_config.h>
#include <sa/tasks/ike_cert.h>
@@ -148,6 +149,11 @@ struct private_ike_sa_t {
* set of extensions the peer supports
*/
ike_extension_t extensions;
/**
* set of condition flags currently enabled for this IKE_SA
*/
ike_condition_t conditions;
/**
* Linked List containing the child sa's of the current IKE_SA.
@@ -194,16 +200,6 @@ struct private_ike_sa_t {
*/
chunk_t skp_verify;
/**
* NAT status of local host.
*/
bool nat_here;
/**
* NAT status of remote host.
*/
bool nat_there;
/**
* Virtual IP on local host, if any
*/
@@ -218,6 +214,11 @@ struct private_ike_sa_t {
* List of DNS servers installed by us
*/
linked_list_t *dns_servers;
/**
* list of peers additional addresses, transmitted via MOBIKE
*/
linked_list_t *additional_addresses;
/**
* Timestamps for this IKE_SA
@@ -605,7 +606,7 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
this->my_host = me->clone(me);
}
if (!this->nat_here)
if (!(this->conditions & COND_NAT_THERE))
{
/* update without restrictions if we are not NATted */
if (other_diff)
@@ -806,6 +807,8 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_config_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_mobike_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
}
task = (task_t*)child_create_create(&this->public, child_cfg);
@@ -866,6 +869,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_config_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
task = (task_t*)ike_mobike_create(&this->public, TRUE);
this->task_manager->queue_task(this->task_manager, task);
}
child_cfg = child_sa->get_config(child_sa);
@@ -1092,6 +1097,8 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
task = (task_t*)child_create_create(&new->public, child_cfg);
new->task_manager->queue_task(new->task_manager, task);
}
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);
@@ -1205,8 +1212,7 @@ static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
{
DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
charon->kernel_interface->del_ip(charon->kernel_interface,
this->my_virtual_ip,
this->my_host);
this->my_virtual_ip);
this->my_virtual_ip->destroy(this->my_virtual_ip);
}
if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
@@ -1255,7 +1261,77 @@ static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
*/
static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension)
{
return this->extensions & extension;
return (this->extensions & extension) != FALSE;
}
/**
* Implementation of ike_sa_t.has_condition.
*/
static bool has_condition(private_ike_sa_t *this, ike_condition_t condition)
{
return (this->conditions & condition) != FALSE;
}
/**
* Implementation of ike_sa_t.enable_condition.
*/
static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
bool enable)
{
if (has_condition(this, condition) != enable)
{
if (enable)
{
switch (condition)
{
case COND_STALE:
DBG1(DBG_IKE, "no route to %H, setting IKE_SA to stale",
this->other_host);
break;
case COND_NAT_HERE:
DBG1(DBG_IKE, "local host is behind NAT, sending keep alives");
this->conditions |= COND_NAT_ANY;
send_keepalive(this);
break;
case COND_NAT_THERE:
DBG1(DBG_IKE, "remote host is behind NAT");
this->conditions |= COND_NAT_ANY;
break;
default:
break;
}
this->conditions |= condition;
}
else
{
switch (condition)
{
case COND_STALE:
DBG1(DBG_IKE, "new route to %H found", this->other_host);
break;
default:
break;
}
this->conditions &= ~condition;
}
}
}
/**
* Implementation of ike_sa_t.add_additional_address.
*/
static void add_additional_address(private_ike_sa_t *this, host_t *host)
{
this->additional_addresses->insert_last(this->additional_addresses, host);
}
/**
* Implementation of ike_sa_t.create_additional_address_iterator.
*/
static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
{
return this->additional_addresses->create_iterator(
this->additional_addresses, TRUE);
}
/**
@@ -1588,6 +1664,84 @@ static status_t reestablish(private_ike_sa_t *this)
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.roam.
*/
static status_t roam(private_ike_sa_t *this)
{
iterator_t *iterator;
host_t *me, *other;
ike_mobike_t *mobike;
/* only initiator handles address updated actively */
if (!this->ike_sa_id->is_initiator(this->ike_sa_id))
{
return SUCCESS;
}
me = charon->kernel_interface->get_source_addr(charon->kernel_interface,
this->other_host);
if (me)
{
set_condition(this, COND_STALE, FALSE);
/* attachment still the same? */
if (me->ip_equals(me, this->my_host))
{
DBG2(DBG_IKE, "%H still reached through %H, no update needed",
this->other_host, me);
me->destroy(me);
return SUCCESS;
}
me->set_port(me, this->my_host->get_port(this->my_host));
#ifndef MOBIKE
set_my_host(this, me);
return reestablish(this);
#endif
/* our attachement changed, update if we have mobike */
if (this->extensions & EXT_MOBIKE)
{
mobike = ike_mobike_create(&this->public, TRUE);
mobike->roam(mobike, me, NULL);
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
return this->task_manager->initiate(this->task_manager);
}
/* reestablish if not */
set_my_host(this, me);
return reestablish(this);
}
/* there is nothing we can do without mobike */
if (!(this->extensions & EXT_MOBIKE))
{
set_condition(this, COND_STALE, TRUE);
return FAILED;
}
#ifndef MOBIKE
set_condition(this, COND_STALE, TRUE);
return FAILED;
#endif
/* we are unable to reach the peer. Try an alternative address */
iterator = create_additional_address_iterator(this);
while (iterator->iterate(iterator, (void**)&other))
{
me = charon->kernel_interface->get_source_addr(charon->kernel_interface,
other);
if (me)
{
/* good, we have a new route. Use MOBIKE to update */
iterator->destroy(iterator);
mobike = ike_mobike_create(&this->public, TRUE);
mobike->roam(mobike, me, other);
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
return this->task_manager->initiate(this->task_manager);
}
}
iterator->destroy(iterator);
return SUCCESS;
}
/**
* Implementation of ike_sa_t.inherit.
@@ -1640,32 +1794,6 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
return this->task_manager->initiate(this->task_manager);
}
/**
* Implementation of ike_sa_t.is_natt_enabled.
*/
static bool is_natt_enabled(private_ike_sa_t *this)
{
return this->nat_here || this->nat_there;
}
/**
* Implementation of ike_sa_t.enable_natt.
*/
static void enable_natt(private_ike_sa_t *this, bool local)
{
if (local)
{
DBG1(DBG_IKE, "local host is behind NAT, scheduling keep alives");
this->nat_here = TRUE;
send_keepalive(this);
}
else
{
DBG1(DBG_IKE, "remote host is behind NAT");
this->nat_there = TRUE;
}
}
/**
* Implementation of ike_sa_t.remove_dns_server
*/
@@ -1818,13 +1946,16 @@ static void destroy(private_ike_sa_t *this)
if (this->my_virtual_ip)
{
charon->kernel_interface->del_ip(charon->kernel_interface,
this->my_virtual_ip, this->my_host);
this->my_virtual_ip);
this->my_virtual_ip->destroy(this->my_virtual_ip);
}
DESTROY_IF(this->other_virtual_ip);
remove_dns_servers(this);
this->dns_servers->destroy_offset(this->dns_servers, offsetof(host_t, destroy));
this->dns_servers->destroy_offset(this->dns_servers,
offsetof(host_t, destroy));
this->additional_addresses->destroy_offset(this->additional_addresses,
offsetof(host_t, destroy));
DESTROY_IF(this->my_host);
DESTROY_IF(this->other_host);
@@ -1874,6 +2005,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_other_ca = (void (*)(ike_sa_t*,ca_info_t*)) set_other_ca;
this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
this->public.delete = (status_t (*)(ike_sa_t*))delete_;
this->public.destroy = (void (*)(ike_sa_t*))destroy;
@@ -1890,10 +2025,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
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.enable_natt = (void (*)(ike_sa_t*, bool)) enable_natt;
this->public.is_natt_enabled = (bool (*)(ike_sa_t*)) is_natt_enabled;
this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
this->public.roam = (status_t(*)(ike_sa_t*))roam;
this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit;
this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message;
this->public.reset = (void (*)(ike_sa_t*))reset;
@@ -1911,6 +2045,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->other_ca = NULL;
this->extensions = 0;
this->conditions = 0;
this->crypter_in = NULL;
this->crypter_out = NULL;
this->signer_in = NULL;
@@ -1919,8 +2054,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->skp_verify = chunk_empty;
this->skp_build = chunk_empty;
this->child_prf = NULL;
this->nat_here = FALSE;
this->nat_there = FALSE;
this->state = IKE_CREATED;
this->time.inbound = this->time.outbound = time(NULL);
this->time.established = 0;
@@ -1933,6 +2066,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->my_virtual_ip = NULL;
this->other_virtual_ip = NULL;
this->dns_servers = linked_list_create();
this->additional_addresses = linked_list_create();
this->keyingtry = 0;
return &this->public;
+86 -29
View File
@@ -26,6 +26,7 @@
#define IKE_SA_H_
typedef enum ike_extension_t ike_extension_t;
typedef enum ike_condition_t ike_condition_t;
typedef enum ike_sa_state_t ike_sa_state_t;
typedef struct ike_sa_t ike_sa_t;
@@ -79,12 +80,38 @@ enum ike_extension_t {
/**
* peer supports NAT traversal as specified in RFC4306
*/
EXT_NATT,
EXT_NATT = (1<<0),
/**
* peer supports MOBIKE (RFC4555)
*/
EXT_MOBIKE,
EXT_MOBIKE = (1<<1),
};
/**
* @brief Conditions of an IKE_SA, change during its lifetime
*/
enum ike_condition_t {
/**
* Connection is natted somewhere
*/
COND_NAT_ANY = (1<<0),
/**
* we are behind NAT
*/
COND_NAT_HERE = (1<<1),
/**
* other is behind NAT
*/
COND_NAT_THERE = (1<<2),
/**
* peer is currently not reachable (due missing route, ...)
*/
COND_STALE = (1<<3),
};
/**
@@ -336,13 +363,25 @@ struct ike_sa_t {
void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config);
/**
* @brief Check if the peer supports an extension.
* @brief Add an additional address for the peer.
*
* In MOBIKE, a peer may transmit additional addresses where it is
* reachable. These are stored in the IKE_SA.
* The own list of addresses is not stored, they are queried from
* the kernel when required.
*
* @param this calling object
* @param extension extension to check for support
* @return TRUE if peer supports it, FALSE otherwise
* @param host host to add to list
*/
bool (*supports_extension)(ike_sa_t *this, ike_extension_t extension);
void (*add_additional_address)(ike_sa_t *this, host_t *host);
/**
* @brief Create an iterator over all additional addresses of the peer.
*
* @param this calling object
* @return iterator over addresses
*/
iterator_t* (*create_additional_address_iterator)(ike_sa_t *this);
/**
* @brief Enable an extension the peer supports.
@@ -355,6 +394,33 @@ struct ike_sa_t {
*/
void (*enable_extension)(ike_sa_t *this, ike_extension_t extension);
/**
* @brief Check if the peer supports an extension.
*
* @param this calling object
* @param extension extension to check for support
* @return TRUE if peer supports it, FALSE otherwise
*/
bool (*supports_extension)(ike_sa_t *this, ike_extension_t extension);
/**
* @brief Enable/disable a condition flag for this IKE_SA.
*
* @param this calling object
* @param condition condition to enable/disable
* @param enable TRUE to enable condition, FALSE to disable
*/
void (*set_condition) (ike_sa_t *this, ike_condition_t condition, bool enable);
/**
* @brief Check if a condition flag is set.
*
* @param this calling object
* @param condition condition to check
* @return TRUE if condition flag set, FALSE otherwise
*/
bool (*has_condition) (ike_sa_t *this, ike_condition_t condition);
/**
* @brief Initiate a new connection.
*
@@ -424,6 +490,20 @@ struct ike_sa_t {
*/
status_t (*delete) (ike_sa_t *this);
/**
* @brief Update IKE_SAs after network interfaces have changed.
*
* Whenever the network interface configuration changes, the kernel
* interface calls roam() on each IKE_SA. The IKE_SA then checks if
* the new network config requires changes, and handles appropriate.
* If MOBIKE is supported, addresses are updated; If not, the tunnel is
* restarted.
*
* @param
* @return
*/
status_t (*roam)(ike_sa_t *this);
/**
* @brief Processes a incoming IKEv2-Message.
*
@@ -493,29 +573,6 @@ struct ike_sa_t {
* @param this calling object
*/
void (*send_keepalive) (ike_sa_t *this);
/**
* @brief Check if NAT traversal is enabled for this IKE_SA.
*
* @param this calling object
* @return TRUE if NAT traversal enabled
*/
bool (*is_natt_enabled) (ike_sa_t *this);
/**
* @brief Enable NAT detection for this IKE_SA.
*
* If a Network address translation is detected with
* NAT_DETECTION notifys, a SA must switch to ports
* 4500. To enable this behavior, call enable_natt().
* It is relevant which peer is NATted, this is specified
* with the "local" parameter. Call it twice when both
* are NATted.
*
* @param this calling object
* @param local TRUE, if we are NATted, FALSE if other
*/
void (*enable_natt) (ike_sa_t *this, bool local);
/**
* @brief Derive all keys and create the transforms for IKE communication.
+23 -3
View File
@@ -27,6 +27,7 @@
#include <daemon.h>
#include <sa/tasks/ike_init.h>
#include <sa/tasks/ike_natd.h>
#include <sa/tasks/ike_mobike.h>
#include <sa/tasks/ike_auth.h>
#include <sa/tasks/ike_cert.h>
#include <sa/tasks/ike_rekey.h>
@@ -130,6 +131,11 @@ struct private_task_manager_t {
* List of tasks initiated by peer
*/
linked_list_t *passive_tasks;
/**
* the task manager has been reset
*/
bool reset;
};
/**
@@ -140,7 +146,7 @@ static void flush(private_task_manager_t *this)
task_t *task;
this->queued_tasks->destroy_offset(this->queued_tasks,
offsetof(task_t, destroy));
offsetof(task_t, destroy));
this->passive_tasks->destroy_offset(this->passive_tasks,
offsetof(task_t, destroy));
@@ -274,6 +280,7 @@ static status_t build_request(private_task_manager_t *this)
activate_task(this, IKE_AUTHENTICATE);
activate_task(this, IKE_CONFIG);
activate_task(this, CHILD_CREATE);
activate_task(this, IKE_MOBIKE);
}
break;
case IKE_ESTABLISHED:
@@ -307,7 +314,7 @@ static status_t build_request(private_task_manager_t *this)
exchange = INFORMATIONAL;
break;
}
if (activate_task(this, IKE_DEADPEER))
if (activate_task(this, IKE_DPD))
{
exchange = INFORMATIONAL;
break;
@@ -420,6 +427,8 @@ static status_t process_response(private_task_manager_t *this,
return DESTROY_ME;
}
/* catch if we get resetted while processing */
this->reset = FALSE;
iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
while (iterator->iterate(iterator, (void*)&task))
{
@@ -439,6 +448,12 @@ static status_t process_response(private_task_manager_t *this,
iterator->destroy(iterator);
return DESTROY_ME;
}
if (this->reset)
{ /* start all over again if we were reset */
this->reset = FALSE;
iterator->destroy(iterator);
return build_request(this);
}
}
iterator->destroy(iterator);
@@ -597,6 +612,8 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)child_create_create(this->ike_sa, NULL);
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
break;
}
case CREATE_CHILD_SA:
@@ -812,7 +829,7 @@ static void reset(private_task_manager_t *this)
this->responding.packet = NULL;
this->initiating.packet = NULL;
this->responding.mid = 0;
this->initiating.mid = -1;
this->initiating.mid = 0;
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
/* reset active tasks */
@@ -822,6 +839,8 @@ static void reset(private_task_manager_t *this)
task->migrate(task, this->ike_sa);
this->queued_tasks->insert_first(this->queued_tasks, task);
}
this->reset = TRUE;
}
/**
@@ -865,6 +884,7 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa)
this->queued_tasks = linked_list_create();
this->active_tasks = linked_list_create();
this->passive_tasks = linked_list_create();
this->reset = FALSE;
return &this->public;
}
+11 -12
View File
@@ -297,7 +297,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
this->mode = MODE_TUNNEL;
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
}
else if (this->ike_sa->is_natt_enabled(this->ike_sa))
else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
{
this->mode = MODE_TUNNEL;
DBG1(DBG_IKE, "not using tranport mode, connection NATed");
@@ -545,11 +545,10 @@ static status_t build_i(private_child_create_t *this, message_t *message)
this->dh_group == MODP_NONE);
this->mode = this->config->get_mode(this->config);
this->child_sa = child_sa_create(me, other,
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
this->config, this->reqid,
this->ike_sa->is_natt_enabled(this->ike_sa));
this->child_sa = child_sa_create(
me, other, this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
{
@@ -660,12 +659,12 @@ static status_t build_r(private_child_create_t *this, message_t *message)
return SUCCESS;
}
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa),
this->config, this->reqid,
this->ike_sa->is_natt_enabled(this->ike_sa));
this->child_sa = child_sa_create(
this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa),
this->ike_sa->get_my_id(this->ike_sa),
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
switch (select_and_install(this, no_dh))
{
+6 -1
View File
@@ -636,7 +636,12 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
case INVALID_SELECTORS:
/* these are errors, but are not critical as only the
* CHILD_SA won't get build, but IKE_SA establishes anyway */
break;
break;
case MOBIKE_SUPPORTED:
case ADDITIONAL_IP4_ADDRESS:
case ADDITIONAL_IP6_ADDRESS:
/* handled in ike_mobike task */
break;
default:
{
if (type < 16383)
+1 -1
View File
@@ -61,7 +61,7 @@ static status_t return_success(private_ike_dpd_t *this, message_t *message)
*/
static task_type_t get_type(private_ike_dpd_t *this)
{
return IKE_DEADPEER;
return IKE_DPD;
}
/**
+307
View File
@@ -0,0 +1,307 @@
/**
* @file ike_mobike.c
*
* @brief Implementation of the ike_mobike task.
*
*/
/*
* Copyright (C) 2007 Martin Willi
* 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 "ike_mobike.h"
#include <string.h>
#include <daemon.h>
#include <encoding/payloads/notify_payload.h>
typedef struct private_ike_mobike_t private_ike_mobike_t;
/**
* Private members of a ike_mobike_t task.
*/
struct private_ike_mobike_t {
/**
* Public methods and task_t interface.
*/
ike_mobike_t public;
/**
* Assigned IKE_SA.
*/
ike_sa_t *ike_sa;
/**
* Are we the initiator?
*/
bool initiator;
/**
* local host to roam to
*/
host_t *me;
/**
* remote host to roam to
*/
host_t *other;
};
/**
* flush the IKE_SAs list of additional addresses
*/
static void flush_additional_addresses(private_ike_mobike_t *this)
{
iterator_t *iterator;
host_t *host;
iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
while (iterator->iterate(iterator, (void**)&host))
{
iterator->remove(iterator);
host->destroy(host);
}
iterator->destroy(iterator);
}
/**
* read notifys from message and evaluate them
*/
static void process_payloads(private_ike_mobike_t *this, message_t *message)
{
iterator_t *iterator;
payload_t *payload;
bool first = TRUE;
iterator = message->get_payload_iterator(message);
while (iterator->iterate(iterator, (void**)&payload))
{
int family = AF_INET;
notify_payload_t *notify;
chunk_t data;
host_t *host;
if (payload->get_type(payload) != NOTIFY)
{
continue;
}
notify = (notify_payload_t*)payload;
switch (notify->get_notify_type(notify))
{
case MOBIKE_SUPPORTED:
{
DBG2(DBG_IKE, "peer supports MOBIKE");
this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
break;
}
case ADDITIONAL_IP6_ADDRESS:
{
family = AF_INET6;
/* fall through */
}
case ADDITIONAL_IP4_ADDRESS:
{
if (first)
{ /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
flush_additional_addresses(this);
}
data = notify->get_notification_data(notify);
host = host_create_from_chunk(family, data, 0);
DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
this->ike_sa->add_additional_address(this->ike_sa, host);
break;
}
case NO_ADDITIONAL_ADDRESSES:
{
flush_additional_addresses(this);
break;
}
default:
break;
}
}
iterator->destroy(iterator);
}
/**
* Add ADDITIONAL_*_ADDRESS notifys depending on our address list
*/
static void build_address_list(private_ike_mobike_t *this, message_t *message)
{
iterator_t *iterator;
host_t *host, *me;
notify_type_t type;
bool additional = FALSE;
me = this->ike_sa->get_my_host(this->ike_sa);
iterator = charon->kernel_interface->create_address_iterator(
charon->kernel_interface);
while (iterator->iterate(iterator, (void**)&host))
{
if (me->ip_equals(me, host))
{ /* "ADDITIONAL" means do not include IKE_SAs host */
continue;
}
switch (host->get_family(host))
{
case AF_INET:
type = ADDITIONAL_IP4_ADDRESS;
break;
case AF_INET6:
type = ADDITIONAL_IP6_ADDRESS;
break;
default:
continue;
}
message->add_notify(message, FALSE, type, host->get_address(host));
additional = TRUE;
}
if (!additional)
{
message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
}
iterator->destroy(iterator);
}
/**
* Implementation of task_t.process for initiator
*/
static status_t build_i(private_ike_mobike_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_payload(message, SECURITY_ASSOCIATION))
{
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
build_address_list(this, message);
}
return NEED_MORE;
}
/**
* Implementation of task_t.process for responder
*/
static status_t process_r(private_ike_mobike_t *this, message_t *message)
{
process_payloads(this, message);
return NEED_MORE;
}
/**
* Implementation of task_t.build for responder
*/
static status_t build_r(private_ike_mobike_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_payload(message, SECURITY_ASSOCIATION))
{
if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
{
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
build_address_list(this, message);
}
return SUCCESS;
}
return NEED_MORE;
}
/**
* Implementation of task_t.process for initiator
*/
static status_t process_i(private_ike_mobike_t *this, message_t *message)
{
if (message->get_exchange_type(message) == IKE_AUTH &&
message->get_payload(message, SECURITY_ASSOCIATION))
{
process_payloads(this, message);
return SUCCESS;
}
return NEED_MORE;
}
/**
* Implementation of ike_mobike_t.roam.
*/
static void roam(private_ike_mobike_t *this, host_t *me, host_t *other)
{
this->me = me;
this->other = other;
}
/**
* Implementation of task_t.get_type
*/
static task_type_t get_type(private_ike_mobike_t *this)
{
return IKE_MOBIKE;
}
/**
* Implementation of task_t.migrate
*/
static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->me);
DESTROY_IF(this->other);
this->ike_sa = ike_sa;
this->me = NULL;
this->other = NULL;
}
/**
* Implementation of task_t.destroy
*/
static void destroy(private_ike_mobike_t *this)
{
DESTROY_IF(this->me);
DESTROY_IF(this->other);
free(this);
}
/*
* Described in header.
*/
ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
{
private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
this->public.roam = (void(*)(ike_mobike_t*, host_t *, host_t *))roam;
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
this->public.task.destroy = (void(*)(task_t*))destroy;
if (initiator)
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
}
else
{
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
}
this->ike_sa = ike_sa;
this->initiator = initiator;
this->me = NULL;
this->other = NULL;
return &this->public;
}
+76
View File
@@ -0,0 +1,76 @@
/**
* @file ike_mobike.h
*
* @brief Interface ike_mobike_t.
*
*/
/*
* Copyright (C) 2007 Martin Willi
* 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.
*/
#ifndef IKE_MOBIKE_H_
#define IKE_MOBIKE_H_
typedef struct ike_mobike_t ike_mobike_t;
#include <library.h>
#include <sa/ike_sa.h>
#include <sa/tasks/task.h>
/**
* @brief Task of type ike_mobike, detects and handles MOBIKE extension.
*
* The MOBIKE extension is defined in RFC4555. It allows to update IKE
* and IPsec tunnel addresses.
* This tasks handles the MOBIKE_SUPPORTED notify exchange to detect MOBIKE
* support, allows the exchange of ADDITIONAL_*_ADDRESS to exchange additional
* endpoints and handles the UPDATE_SA_ADDRESS notify to finally update
* endpoints.
*
* @b Constructors:
* - ike_mobike_create()
*
* @ingroup tasks
*/
struct ike_mobike_t {
/**
* Implements the task_t interface
*/
task_t task;
/**
* @brief Use the task to roam to other addresses.
*
* Supplied hosts may be NULL to reuse existing IKE_SA hosts.
*
* @param this calling object
* @param me local host to roam to, or NULL
* @param other remote host to roam to, or NULL
*/
void (*roam)(ike_mobike_t *this, host_t *me, host_t *other);
};
/**
* @brief Create a new ike_mobike task.
*
* @param ike_sa IKE_SA this task works for
* @param initiator TRUE if taks is initiated by us
* @return ike_mobike task to handle by the task_manager
*/
ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator);
#endif /* IKE_MOBIKE_H_ */
+3 -3
View File
@@ -207,11 +207,11 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
if (!this->dst_matched)
{
this->ike_sa->enable_natt(this->ike_sa, TRUE);
this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE, TRUE);
}
if (!this->src_matched)
{
this->ike_sa->enable_natt(this->ike_sa, FALSE);
this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE, TRUE);
}
}
}
@@ -223,7 +223,7 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
{
process_payloads(this, message);
if (this->ike_sa->is_natt_enabled(this->ike_sa))
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
{
host_t *me, *other;
+2
View File
@@ -84,6 +84,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
host = this->ike_sa->get_other_host(this->ike_sa);
new->set_other_host(new, host->clone(host));
host = this->ike_sa->get_my_host(this->ike_sa);
new->set_my_host(new, host->clone(host));
/* if we already have a virtual IP, we reuse it */
host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
if (host)
+4 -2
View File
@@ -25,14 +25,16 @@
ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
"IKE_INIT",
"IKE_NATD",
"IKE_MOBIKE",
"IKE_AUTHENTICATE",
"IKE_CERT",
"IKE_CONFIG",
"IKE_DPD",
"IKE_REKEY",
"IKE_REAUTH",
"IKE_DELETE",
"IKE_DEADPEER",
"IKE_DPD",
"CHILD_CREATE",
"CHILD_DELETE",
"CHILD_REKEY",
);
+2 -2
View File
@@ -40,14 +40,14 @@ enum task_type_t {
IKE_INIT,
/** detect NAT situation */
IKE_NATD,
/** handle MOBIKE stuff */
IKE_MOBIKE,
/** authenticate the initiated IKE_SA */
IKE_AUTHENTICATE,
/** exchange certificates and requests */
IKE_CERT,
/** Configuration payloads, virtual IP and such */
IKE_CONFIG,
/** DPD detection */
IKE_DEADPEER,
/** rekey an IKE_SA */
IKE_REKEY,
/** reestablish a complete IKE_SA */