preliminary support of Mobile IPv6

This commit is contained in:
Andreas Steffen
2008-11-11 06:37:37 +00:00
parent 91db979cdd
commit d487b4b727
17 changed files with 336 additions and 200 deletions
+161 -78
View File
@@ -155,7 +155,7 @@ struct private_child_sa_t {
};
/**
* Implementation of child_sa_t.get_namy_
* Implementation of child_sa_t.get_name
*/
static char *get_name(private_child_sa_t *this)
{
@@ -334,10 +334,13 @@ static u_int32_t get_usetime(private_child_sa_t *this, bool inbound)
{
last_use = max(last_use, in);
}
if (charon->kernel_interface->query_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
if (this->mode == MODE_TUNNEL)
{
last_use = max(last_use, fwd);
if (charon->kernel_interface->query_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
{
last_use = max(last_use, fwd);
}
}
}
else
@@ -595,7 +598,7 @@ static status_t add_policies(private_child_sa_t *this,
{ /* update if not set yet */
this->protocol = proto;
}
/* apply traffic selectors */
enumerator = my_ts_list->create_enumerator(my_ts_list);
while (enumerator->enumerate(enumerator, &my_ts))
@@ -610,30 +613,36 @@ static status_t add_policies(private_child_sa_t *this,
}
enumerator->destroy(enumerator);
/* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
if (this->config->install_policy(this->config))
{
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
/* enumerate pairs of traffic selectors */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
if (mode == MODE_TUNNEL)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
this->protocol, this->reqid, high_prio, mode, this->ipcomp);
}
if (status != SUCCESS)
{
break;
if (status != SUCCESS)
{
break;
}
}
enumerator->destroy(enumerator);
}
enumerator->destroy(enumerator);
if (status == SUCCESS)
{
/* switch to routed state if no SAD entry set up */
@@ -694,71 +703,82 @@ static status_t update_hosts(private_child_sa_t *this,
charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi,
this->protocol, this->my_addr, this->other_addr, me, other, encap);
/* update policies */
if (!me->ip_equals(me, this->my_addr) ||
!other->ip_equals(other, this->other_addr))
if (this->config->install_policy(this->config))
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
/* always use high priorities, as hosts getting updated are INSTALLED */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
/* update policies */
if (!me->ip_equals(me, this->my_addr) ||
!other->ip_equals(other, this->other_addr))
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
/* always use high priorities, as hosts getting updated are INSTALLED */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
my_ts, other_ts, POLICY_OUT);
charon->kernel_interface->del_policy(charon->kernel_interface,
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_IN);
charon->kernel_interface->del_policy(charon->kernel_interface,
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_FWD);
/* check whether we have to update a "dynamic" traffic selector */
if (!me->ip_equals(me, this->my_addr) &&
my_ts->is_host(my_ts, this->my_addr))
{
my_ts->set_address(my_ts, me);
}
if (!other->ip_equals(other, this->other_addr) &&
other_ts->is_host(other_ts, this->other_addr))
{
other_ts->set_address(other_ts, other);
}
}
/* check whether we have to update a "dynamic" traffic selector */
if (!me->ip_equals(me, this->my_addr) &&
my_ts->is_host(my_ts, this->my_addr))
{
my_ts->set_address(my_ts, me);
}
if (!other->ip_equals(other, this->other_addr) &&
other_ts->is_host(other_ts, this->other_addr))
{
other_ts->set_address(other_ts, other);
}
/* we reinstall the virtual IP to handle interface roaming
* correctly */
if (vip)
{
charon->kernel_interface->del_ip(charon->kernel_interface, vip);
charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
}
/* we reinstall the virtual IP to handle interface roaming
* correctly */
if (vip)
{
charon->kernel_interface->del_ip(charon->kernel_interface, vip);
charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
}
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, my_ts, other_ts, POLICY_OUT, this->protocol,
this->reqid, TRUE, this->mode, this->ipcomp);
charon->kernel_interface->add_policy(charon->kernel_interface,
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_IN, this->protocol,
this->reqid, TRUE, this->mode, this->ipcomp);
charon->kernel_interface->add_policy(charon->kernel_interface,
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_FWD, this->protocol,
this->reqid, TRUE, this->mode, this->ipcomp);
}
}
enumerator->destroy(enumerator);
}
enumerator->destroy(enumerator);
}
/* apply hosts */
if (!me->equals(me, this->my_addr))
if (!this->config->use_proxy_mode(this->config) || this->mode != MODE_TRANSPORT)
{
this->my_addr->destroy(this->my_addr);
this->my_addr = me->clone(me);
if (!me->equals(me, this->my_addr))
{
this->my_addr->destroy(this->my_addr);
this->my_addr = me->clone(me);
}
if (!other->equals(other, this->other_addr))
{
this->other_addr->destroy(this->other_addr);
this->other_addr = other->clone(other);
}
}
if (!other->equals(other, this->other_addr))
{
this->other_addr->destroy(this->other_addr);
this->other_addr = other->clone(other);
}
set_state(this, old);
return SUCCESS;
@@ -830,19 +850,25 @@ static void destroy(private_child_sa_t *this)
this->other_addr, htonl(ntohs(this->other_cpi)), IPPROTO_COMP);
}
/* delete all policies in the kernel */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
if (this->config->install_policy(this->config))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
my_ts, other_ts, POLICY_OUT);
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_IN);
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_FWD);
/* delete all policies in the kernel */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
my_ts, other_ts, POLICY_OUT);
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_IN);
if (this->mode == MODE_TUNNEL)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_FWD);
}
}
enumerator->destroy(enumerator);
}
enumerator->destroy(enumerator);
this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
this->my_addr->destroy(this->my_addr);
@@ -909,6 +935,63 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->proposal = NULL;
this->config = config;
config->get_ref(config);
/* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
if (config->get_mode(config) == MODE_TRANSPORT &&
config->use_proxy_mode(config))
{
ts_type_t type;
int family;
chunk_t addr;
host_t *host;
enumerator_t *enumerator;
linked_list_t *my_ts_list, *other_ts_list;
traffic_selector_t *my_ts, *other_ts;
this->mode = MODE_TRANSPORT;
my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
enumerator = my_ts_list->create_enumerator(my_ts_list);
if (enumerator->enumerate(enumerator, &my_ts))
{
if (my_ts->is_host(my_ts, NULL) &&
!my_ts->is_host(my_ts, this->my_addr))
{
type = my_ts->get_type(my_ts);
family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
addr = my_ts->get_from_address(my_ts);
host = host_create_from_chunk(family, addr, 0);
free(addr.ptr);
DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H",
this->my_addr, host);
this->my_addr->destroy(this->my_addr);
this->my_addr = host;
}
}
enumerator->destroy(enumerator);
my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
enumerator = other_ts_list->create_enumerator(other_ts_list);
if (enumerator->enumerate(enumerator, &other_ts))
{
if (other_ts->is_host(other_ts, NULL) &&
!other_ts->is_host(other_ts, this->other_addr))
{
type = other_ts->get_type(other_ts);
family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
addr = other_ts->get_from_address(other_ts);
host = host_create_from_chunk(family, addr, 0);
free(addr.ptr);
DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H",
this->other_addr, host);
this->other_addr->destroy(this->other_addr);
this->other_addr = host;
}
}
enumerator->destroy(enumerator);
other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy));
}
return &this->public;
}
+10 -8
View File
@@ -323,14 +323,16 @@ struct child_sa_t {
/**
* Constructor to create a new child_sa_t.
*
* @param me own address
* @param other remote address
* @param my_id id of own peer
* @param other_id id of remote peer
* @param config config to use for this CHILD_SA
* @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
* @param encap TRUE to enable UDP encapsulation (NAT traversal)
* @return child_sa_t object
* @param me own address
* @param other remote address
* @param my_id id of own peer
* @param other_id id of remote peer
* @param config config to use for this CHILD_SA
* @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise
* @param encap TRUE to enable UDP encapsulation (NAT traversal)
* @param proxy TRUE if IPsec transport SA is to be set up in proxy mode
* @param install_policy TRUE if kernel policies are to be installed
* @return child_sa_t object
*/
child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
u_int32_t reqid, bool encap);
+62 -17
View File
@@ -250,6 +250,16 @@ struct private_ike_sa_t {
* are we the initiator of this IKE_SA (rekeying does not affect this flag)
*/
bool ike_initiator;
/**
* local host address to be used for IKE, set via MIGRATE kernel message
*/
host_t *local_host;
/**
* remote host address to be used for IKE, set via MIGRATE kernel message
*/
host_t *remote_host;
};
/**
@@ -943,6 +953,17 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
response->destroy(response);
}
/**
* Implementation of ike_sa_t.set_kmaddress.
*/
static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
{
DESTROY_IF(this->local_host);
DESTROY_IF(this->remote_host);
this->local_host = local->clone(local);
this->remote_host = remote->clone(remote);
}
#ifdef ME
/**
* Implementation of ike_sa_t.act_as_mediation_server.
@@ -1047,26 +1068,42 @@ static void resolve_hosts(private_ike_sa_t *this)
{
host_t *host;
host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
0, IKEV2_UDP_PORT);
if (this->remote_host)
{
host = this->remote_host->clone(this->remote_host);
host->set_port(host, IKEV2_UDP_PORT);
}
else
{
host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
0, IKEV2_UDP_PORT);
}
if (host)
{
set_other_host(this, host);
}
host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
this->my_host->get_family(this->my_host),
IKEV2_UDP_PORT);
if (host && host->is_anyaddr(host) &&
!this->other_host->is_anyaddr(this->other_host))
if (this->local_host)
{
host->destroy(host);
host = charon->kernel_interface->get_source_addr(
charon->kernel_interface, this->other_host, NULL);
if (host)
host = this->local_host->clone(this->local_host);
host->set_port(host, IKEV2_UDP_PORT);
}
else
{
host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg),
this->my_host->get_family(this->my_host),
IKEV2_UDP_PORT);
if (host && host->is_anyaddr(host) &&
!this->other_host->is_anyaddr(this->other_host))
{
host->set_port(host, IKEV2_UDP_PORT);
host->destroy(host);
host = charon->kernel_interface->get_source_addr(
charon->kernel_interface, this->other_host, NULL);
if (host)
{
host->set_port(host, IKEV2_UDP_PORT);
}
}
}
if (host)
@@ -1264,8 +1301,10 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, me);
other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, other);
status = child_sa->add_policies(child_sa, my_ts, other_ts,
child_cfg->get_mode(child_cfg), PROTO_NONE);
child_cfg->get_mode(child_cfg), PROTO_NONE);
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
if (status == SUCCESS)
@@ -1318,6 +1357,7 @@ static status_t unroute(private_ike_sa_t *this, u_int32_t reqid)
}
return SUCCESS;
}
/**
* Implementation of ike_sa_t.process_message.
*/
@@ -1389,7 +1429,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
me = message->get_destination(message);
other = message->get_source(message);
/* if this IKE_SA is virgin, we check for a config */
if (this->ike_cfg == NULL)
{
@@ -2235,6 +2275,8 @@ static void destroy(private_ike_sa_t *this)
DESTROY_IF(this->other_host);
DESTROY_IF(this->my_id);
DESTROY_IF(this->other_id);
DESTROY_IF(this->local_host);
DESTROY_IF(this->remote_host);
DESTROY_IF(this->eap_identity);
DESTROY_IF(this->ike_cfg);
@@ -2319,6 +2361,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
this->public.add_dns_server = (void (*)(ike_sa_t*,host_t*))add_dns_server;
this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
#ifdef ME
this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
@@ -2334,8 +2377,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
/* initialize private fields */
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
this->child_sas = linked_list_create();
this->my_host = host_create_from_string("%any", IKEV2_UDP_PORT);
this->other_host = host_create_from_string("%any", IKEV2_UDP_PORT);
this->my_host = host_create_any(AF_INET);
this->other_host = host_create_any(AF_INET);
this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
this->eap_identity = NULL;
@@ -2362,6 +2405,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
this->pending_updates = 0;
this->keyingtry = 0;
this->ike_initiator = FALSE;
this->local_host = NULL;
this->remote_host = NULL;
#ifdef ME
this->is_mediation_server = FALSE;
this->server_reflexive_host = NULL;
+11
View File
@@ -864,6 +864,17 @@ struct ike_sa_t {
*/
void (*add_dns_server) (ike_sa_t *this, host_t *dns);
/**
* Set local and remote host addresses to be used for IKE.
*
* These addresses are communicated via the KMADDRESS field of a MIGRATE
* message sent via the NETLINK or PF _KEY kernel socket interface.
*
* @param local local kmaddress
* @param remote remote kmaddress
*/
void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote);
/**
* Inherit all attributes of other to this after rekeying.
*
+4 -2
View File
@@ -300,8 +300,10 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
switch (this->mode)
{
case MODE_TRANSPORT:
if (!ts_list_is_host(this->tsi, other) ||
!ts_list_is_host(this->tsr, me))
if (!this->config->use_proxy_mode(this->config) &&
(!ts_list_is_host(this->tsi, other) ||
!ts_list_is_host(this->tsr, me))
)
{
this->mode = MODE_TUNNEL;
DBG1(DBG_IKE, "not using transport mode, not host-to-host");