preliminary support of Mobile IPv6
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "peer_cfg.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
#include <utils/mutex.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
@@ -228,16 +230,20 @@ static enumerator_t* create_child_cfg_enumerator(private_peer_cfg_t *this)
|
||||
/**
|
||||
* Check if child_cfg contains traffic selectors
|
||||
*/
|
||||
static bool contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
|
||||
static int contains_ts(child_cfg_t *child, bool mine, linked_list_t *ts,
|
||||
host_t *host)
|
||||
{
|
||||
linked_list_t *selected;
|
||||
bool contains = FALSE;
|
||||
int prio;
|
||||
|
||||
if (child->equal_traffic_selectors(child, mine, ts, host))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
selected = child->get_traffic_selectors(child, mine, ts, host);
|
||||
contains = selected->get_count(selected);
|
||||
prio = selected->get_count(selected) ? 1 : 0;
|
||||
selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy));
|
||||
return contains;
|
||||
return prio;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,18 +256,33 @@ static child_cfg_t* select_child_cfg(private_peer_cfg_t *this,
|
||||
{
|
||||
child_cfg_t *current, *found = NULL;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
int best = 0;
|
||||
|
||||
DBG2(DBG_CFG, "looking for a child config for %#R=== %#R", my_ts, other_ts);
|
||||
enumerator = create_child_cfg_enumerator(this);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (contains_ts(current, TRUE, my_ts, my_host) &&
|
||||
contains_ts(current, FALSE, other_ts, other_host))
|
||||
int prio = contains_ts(current, TRUE, my_ts, my_host) +
|
||||
contains_ts(current, FALSE, other_ts, other_host);
|
||||
|
||||
if (prio)
|
||||
{
|
||||
found = current->get_ref(current);
|
||||
break;
|
||||
DBG2(DBG_CFG, " candidate \"%s\" with prio %d",
|
||||
current->get_name(current), prio);
|
||||
if (prio > best)
|
||||
{
|
||||
best = prio;
|
||||
DESTROY_IF(found);
|
||||
found = current->get_ref(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (found)
|
||||
{
|
||||
DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
|
||||
found->get_name(found), best);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
@@ -775,7 +775,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
|
||||
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, dpd, dpd, msg->add_conn.ipcomp);
|
||||
|
||||
child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy,
|
||||
msg->add_conn.install_policy);
|
||||
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
|
||||
add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
|
||||
|
||||
|
||||
@@ -83,90 +83,16 @@ static void execute(private_migrate_job_t *this)
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
|
||||
this->reqid, TRUE);
|
||||
}
|
||||
if (ike_sa == NULL)
|
||||
if (ike_sa)
|
||||
{
|
||||
enumerator_t *enumerator, *children;
|
||||
peer_cfg_t *peer_cfg;
|
||||
child_cfg_t *found_cfg = NULL;
|
||||
|
||||
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
|
||||
while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
|
||||
{
|
||||
child_cfg_t *child_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))
|
||||
{
|
||||
if (child_cfg->equal_traffic_selectors(child_cfg, TRUE, this->src_ts) &&
|
||||
child_cfg->equal_traffic_selectors(child_cfg, FALSE, this->dst_ts))
|
||||
{
|
||||
found_cfg = child_cfg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
children->destroy(children);
|
||||
if (found_cfg)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (found_cfg == NULL)
|
||||
{
|
||||
DBG1(DBG_JOB, "no matching child config found for policy %R === %R",
|
||||
this->src_ts, this->dst_ts);
|
||||
destroy(this);
|
||||
return;
|
||||
}
|
||||
DBG1(DBG_JOB, "found matching child config '%s' for policy %R === %R",
|
||||
found_cfg->get_name(found_cfg),
|
||||
this->src_ts, this->dst_ts);
|
||||
|
||||
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
|
||||
peer_cfg);
|
||||
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
|
||||
{
|
||||
host_t *my_host, *other_host;
|
||||
ike_cfg_t *ike_cfg;
|
||||
|
||||
ike_sa->set_peer_cfg(ike_sa, peer_cfg);
|
||||
ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
|
||||
my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
|
||||
other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
|
||||
ike_sa->set_my_host(ike_sa, my_host);
|
||||
ike_sa->set_other_host(ike_sa, other_host);
|
||||
}
|
||||
if (this->local)
|
||||
{
|
||||
ike_sa->set_my_host(ike_sa, this->local->clone(this->local));
|
||||
}
|
||||
if (this->remote)
|
||||
{
|
||||
ike_sa->set_other_host(ike_sa, this->remote->clone(this->remote));
|
||||
}
|
||||
/* add a CHILD_SA for 'found_cfg' with a policy that has already been
|
||||
* installed in the kernel
|
||||
*/
|
||||
DBG2(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid);
|
||||
ike_sa->set_kmaddress(ike_sa, this->local, this->remote);
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid);
|
||||
if (this->local)
|
||||
{
|
||||
ike_sa->set_my_host(ike_sa, this->local);
|
||||
}
|
||||
if (this->remote)
|
||||
{
|
||||
ike_sa->set_other_host(ike_sa, this->remote->clone(this->remote));
|
||||
}
|
||||
DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid);
|
||||
}
|
||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||
destroy(this);
|
||||
}
|
||||
|
||||
|
||||
+161
-78
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -517,6 +517,8 @@ const char *const sa_policy_bit_names[] = {
|
||||
"DONTREAUTH",
|
||||
"BEET",
|
||||
"MOBIKE",
|
||||
"ECDSA",
|
||||
"PROXY",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -877,7 +877,8 @@ extern const char *prettypolicy(lset_t policy);
|
||||
#define POLICY_BEET LELEM(22) /* bound end2end tunnel, IKEv2 */
|
||||
#define POLICY_MOBIKE LELEM(23) /* enable MOBIKE for IKEv2 */
|
||||
#define POLICY_FORCE_ENCAP LELEM(24) /* force UDP encapsulation (IKEv2) */
|
||||
#define POLICY_ECDSASIG LELEM(25) /* ecdsa signature (IKEv2) */
|
||||
#define POLICY_ECDSASIG LELEM(25) /* ECDSA signature (IKEv2) */
|
||||
#define POLICY_PROXY LELEM(26) /* proxy transport mode (MIPv6) */
|
||||
|
||||
/* Any IPsec policy? If not, a connection description
|
||||
* is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
|
||||
|
||||
@@ -199,6 +199,7 @@ static const token_info_t token_info[] =
|
||||
{ ARG_MISC, 0, NULL /* KW_TYPE */ },
|
||||
{ ARG_MISC, 0, NULL /* KW_PFS */ },
|
||||
{ ARG_MISC, 0, NULL /* KW_COMPRESS */ },
|
||||
{ ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool },
|
||||
{ ARG_MISC, 0, NULL /* KW_AUTH */ },
|
||||
{ ARG_MISC, 0, NULL /* KW_AUTHBY */ },
|
||||
{ ARG_MISC, 0, NULL /* KW_EAP */ },
|
||||
|
||||
@@ -79,6 +79,7 @@ static void default_values(starter_config_t *cfg)
|
||||
cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
|
||||
cfg->conn_default.addr_family = AF_INET;
|
||||
cfg->conn_default.tunnel_addr_family = AF_INET;
|
||||
cfg->conn_default.install_policy = TRUE;
|
||||
cfg->conn_default.dpd_delay = 30; /* seconds */
|
||||
cfg->conn_default.dpd_timeout = 150; /* seconds */
|
||||
|
||||
@@ -497,15 +498,29 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
|
||||
case KW_TYPE:
|
||||
conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK);
|
||||
if (streq(kw->value, "tunnel"))
|
||||
{
|
||||
conn->policy |= POLICY_TUNNEL;
|
||||
}
|
||||
else if (streq(kw->value, "beet"))
|
||||
{
|
||||
conn->policy |= POLICY_BEET;
|
||||
}
|
||||
else if (streq(kw->value, "transport_proxy"))
|
||||
{
|
||||
conn->policy |= POLICY_PROXY;
|
||||
}
|
||||
else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
|
||||
{
|
||||
conn->policy |= POLICY_SHUNT_PASS;
|
||||
}
|
||||
else if (streq(kw->value, "drop"))
|
||||
{
|
||||
conn->policy |= POLICY_SHUNT_DROP;
|
||||
}
|
||||
else if (streq(kw->value, "reject"))
|
||||
{
|
||||
conn->policy |= POLICY_SHUNT_REJECT;
|
||||
}
|
||||
else if (strcmp(kw->value, "transport") != 0)
|
||||
{
|
||||
plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
|
||||
@@ -530,21 +545,33 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
|
||||
char *second = strchr(kw->value, '|');
|
||||
|
||||
if (second != NULL)
|
||||
{
|
||||
*second = '\0';
|
||||
}
|
||||
|
||||
/* also handles the cases secret|rsasig and rsasig|secret */
|
||||
for (;;)
|
||||
{
|
||||
if (streq(value, "rsa") || streq(value, "rsasig"))
|
||||
{
|
||||
conn->policy |= POLICY_RSASIG | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "secret") || streq(value, "psk"))
|
||||
{
|
||||
conn->policy |= POLICY_PSK | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "ecdsa") || streq(value, "ecdsasig"))
|
||||
{
|
||||
conn->policy |= POLICY_ECDSASIG | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "xauthrsasig"))
|
||||
{
|
||||
conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT;
|
||||
}
|
||||
else if (streq(value, "xauthpsk"))
|
||||
{
|
||||
conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
plog("# bad policy value: %s=%s", kw->entry->name, kw->value);
|
||||
@@ -552,7 +579,9 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
|
||||
break;
|
||||
}
|
||||
if (second == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
value = second;
|
||||
second = NULL; /* traverse the loop no more than twice */
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ struct starter_conn {
|
||||
unsigned long sa_rekey_fuzz;
|
||||
sa_family_t addr_family;
|
||||
sa_family_t tunnel_addr_family;
|
||||
|
||||
bool install_policy;
|
||||
starter_end_t left, right;
|
||||
|
||||
unsigned long id;
|
||||
|
||||
@@ -68,6 +68,7 @@ typedef enum {
|
||||
KW_TYPE,
|
||||
KW_PFS,
|
||||
KW_COMPRESS,
|
||||
KW_INSTALLPOLICY,
|
||||
KW_AUTH,
|
||||
KW_AUTHBY,
|
||||
KW_EAP,
|
||||
|
||||
@@ -61,6 +61,7 @@ keyexchange, KW_KEYEXCHANGE
|
||||
type, KW_TYPE
|
||||
pfs, KW_PFS
|
||||
compress, KW_COMPRESS
|
||||
installpolicy, KW_INSTALLPOLICY
|
||||
auth, KW_AUTH
|
||||
authby, KW_AUTHBY
|
||||
keylife, KW_KEYLIFE
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/xfrm.h>
|
||||
|
||||
#include <freeswan.h>
|
||||
|
||||
@@ -242,17 +243,22 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
|
||||
|
||||
if (conn->policy & POLICY_TUNNEL)
|
||||
{
|
||||
msg.add_conn.mode = 1; /* XFRM_MODE_TRANSPORT */
|
||||
msg.add_conn.mode = XFRM_MODE_TUNNEL;
|
||||
}
|
||||
else if (conn->policy & POLICY_BEET)
|
||||
{
|
||||
msg.add_conn.mode = 4; /* XFRM_MODE_BEET */
|
||||
msg.add_conn.mode = XFRM_MODE_BEET;
|
||||
}
|
||||
else if (conn->policy & POLICY_PROXY)
|
||||
{
|
||||
msg.add_conn.mode = XFRM_MODE_TRANSPORT;
|
||||
msg.add_conn.proxy = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.add_conn.mode = 0; /* XFRM_MODE_TUNNEL */
|
||||
msg.add_conn.mode = XFRM_MODE_TRANSPORT;
|
||||
}
|
||||
|
||||
|
||||
if (!(conn->policy & POLICY_DONT_REKEY))
|
||||
{
|
||||
msg.add_conn.rekey.reauth = (conn->policy & POLICY_DONT_REAUTH) == LEMPTY;
|
||||
@@ -265,6 +271,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
|
||||
msg.add_conn.mobike = conn->policy & POLICY_MOBIKE;
|
||||
msg.add_conn.force_encap = conn->policy & POLICY_FORCE_ENCAP;
|
||||
msg.add_conn.ipcomp = conn->policy & POLICY_COMPRESS;
|
||||
msg.add_conn.install_policy = conn->install_policy;
|
||||
msg.add_conn.crl_policy = cfg->setup.strictcrlpolicy;
|
||||
msg.add_conn.unique = cfg->setup.uniqueids;
|
||||
msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
|
||||
|
||||
@@ -212,6 +212,9 @@ struct stroke_msg_t {
|
||||
int mobike;
|
||||
int force_encap;
|
||||
int ipcomp;
|
||||
int install_policy;
|
||||
int proxy;
|
||||
|
||||
crl_policy_t crl_policy;
|
||||
int unique;
|
||||
struct {
|
||||
|
||||
Reference in New Issue
Block a user