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
+30 -9
View File
@@ -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, &current))
{
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;
}
+2 -1
View File
@@ -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);
+5 -79
View File
@@ -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
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");
+2
View File
@@ -517,6 +517,8 @@ const char *const sa_policy_bit_names[] = {
"DONTREAUTH",
"BEET",
"MOBIKE",
"ECDSA",
"PROXY",
NULL
};
+2 -1
View File
@@ -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.)
+1
View File
@@ -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 */ },
+29
View File
@@ -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 */
}
+1 -1
View File
@@ -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;
+1
View File
@@ -68,6 +68,7 @@ typedef enum {
KW_TYPE,
KW_PFS,
KW_COMPRESS,
KW_INSTALLPOLICY,
KW_AUTH,
KW_AUTHBY,
KW_EAP,
+1
View File
@@ -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
+11 -4
View File
@@ -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);
+3
View File
@@ -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 {