aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2008-11-11 06:37:37 +0000
committerAndreas Steffen <andreas.steffen@strongswan.org>2008-11-11 06:37:37 +0000
commitd487b4b727ca423aeca2b047c8d28d28dea57b02 (patch)
tree6a706c07a47c0d8f42f76e301d8690e39f322f5d /src
parent91db979cdda4943ab6512dc309ebe1b07273e717 (diff)
downloadstrongswan-d487b4b727ca423aeca2b047c8d28d28dea57b02.tar.bz2
strongswan-d487b4b727ca423aeca2b047c8d28d28dea57b02.tar.xz
preliminary support of Mobile IPv6
Diffstat (limited to 'src')
-rw-r--r--src/charon/config/peer_cfg.c39
-rw-r--r--src/charon/plugins/stroke/stroke_config.c3
-rw-r--r--src/charon/processing/jobs/migrate_job.c84
-rw-r--r--src/charon/sa/child_sa.c239
-rw-r--r--src/charon/sa/child_sa.h18
-rw-r--r--src/charon/sa/ike_sa.c79
-rw-r--r--src/charon/sa/ike_sa.h11
-rw-r--r--src/charon/sa/tasks/child_create.c6
-rw-r--r--src/pluto/constants.c2
-rw-r--r--src/pluto/constants.h3
-rw-r--r--src/starter/args.c1
-rw-r--r--src/starter/confread.c29
-rw-r--r--src/starter/confread.h2
-rw-r--r--src/starter/keywords.h1
-rw-r--r--src/starter/keywords.txt1
-rw-r--r--src/starter/starterstroke.c15
-rw-r--r--src/stroke/stroke_msg.h3
17 files changed, 336 insertions, 200 deletions
diff --git a/src/charon/config/peer_cfg.c b/src/charon/config/peer_cfg.c
index 34e466bfb..398244f6d 100644
--- a/src/charon/config/peer_cfg.c
+++ b/src/charon/config/peer_cfg.c
@@ -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;
}
diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c
index d339f2698..d4ab691bd 100644
--- a/src/charon/plugins/stroke/stroke_config.c
+++ b/src/charon/plugins/stroke/stroke_config.c
@@ -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);
diff --git a/src/charon/processing/jobs/migrate_job.c b/src/charon/processing/jobs/migrate_job.c
index 100158a67..f9b1df26b 100644
--- a/src/charon/processing/jobs/migrate_job.c
+++ b/src/charon/processing/jobs/migrate_job.c
@@ -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);
}
diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c
index f60ea3ff1..24d91a5da 100644
--- a/src/charon/sa/child_sa.c
+++ b/src/charon/sa/child_sa.c
@@ -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 (!other->equals(other, this->other_addr))
- {
- this->other_addr->destroy(this->other_addr);
- this->other_addr = other->clone(other);
+ 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);
+ }
}
-
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;
}
diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h
index 3e138143d..cbf1f3b5c 100644
--- a/src/charon/sa/child_sa.h
+++ b/src/charon/sa/child_sa.h
@@ -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);
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index 6af92e141..ab2a789d0 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -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;
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index 6a8de6984..23098f58e 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -865,6 +865,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.
*
* When rekeying is completed, all CHILD_SAs, the virtual IP and all
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c
index ab12b48b1..628d1397c 100644
--- a/src/charon/sa/tasks/child_create.c
+++ b/src/charon/sa/tasks/child_create.c
@@ -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");
diff --git a/src/pluto/constants.c b/src/pluto/constants.c
index da4d9fc7a..70215441b 100644
--- a/src/pluto/constants.c
+++ b/src/pluto/constants.c
@@ -517,6 +517,8 @@ const char *const sa_policy_bit_names[] = {
"DONTREAUTH",
"BEET",
"MOBIKE",
+ "ECDSA",
+ "PROXY",
NULL
};
diff --git a/src/pluto/constants.h b/src/pluto/constants.h
index 9505d3426..13251dc3b 100644
--- a/src/pluto/constants.h
+++ b/src/pluto/constants.h
@@ -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.)
diff --git a/src/starter/args.c b/src/starter/args.c
index b373be97c..b5f716069 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -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 */ },
diff --git a/src/starter/confread.c b/src/starter/confread.c
index 1b3f31a55..9528f6a98 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -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 */
}
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 8e1584526..ed344fe6f 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -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;
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 9470c75e5..17789d9bd 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -68,6 +68,7 @@ typedef enum {
KW_TYPE,
KW_PFS,
KW_COMPRESS,
+ KW_INSTALLPOLICY,
KW_AUTH,
KW_AUTHBY,
KW_EAP,
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index b54da8ca8..d834fe425 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -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
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 07be12e26..0fe87dfc5 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -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);
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 3ab1c4643..a5fe17df6 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -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 {