aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS14
-rw-r--r--man/ipsec.conf.5.in22
-rw-r--r--src/_updown/_updown.in14
-rw-r--r--src/charon-nm/nm/nm_handler.c16
-rw-r--r--src/charon-nm/nm/nm_service.c7
-rw-r--r--src/conftest/config.c2
-rw-r--r--src/frontends/android/jni/libandroidbridge/backend/android_attr.c2
-rw-r--r--src/frontends/android/jni/libandroidbridge/backend/android_service.c32
-rw-r--r--src/libcharon/config/peer_cfg.c92
-rw-r--r--src/libcharon/config/peer_cfg.h37
-rw-r--r--src/libcharon/plugins/android/android_handler.c2
-rw-r--r--src/libcharon/plugins/android/android_service.c4
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c27
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c29
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c6
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c20
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c52
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c11
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c4
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c3
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c1
-rw-r--r--src/libcharon/plugins/sql/sql_config.c18
-rw-r--r--src/libcharon/plugins/stroke/Makefile.am1
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c214
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.h23
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c173
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.h4
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c49
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.c231
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.h64
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c20
-rw-r--r--src/libcharon/plugins/uci/uci_config.c1
-rw-r--r--src/libcharon/plugins/updown/Makefile.am1
-rw-r--r--src/libcharon/plugins/updown/updown_handler.c243
-rw-r--r--src/libcharon/plugins/updown/updown_handler.h57
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c112
-rw-r--r--src/libcharon/plugins/updown/updown_listener.h4
-rw-r--r--src/libcharon/plugins/updown/updown_plugin.c22
-rw-r--r--src/libcharon/processing/jobs/migrate_job.c15
-rw-r--r--src/libcharon/sa/child_sa.c21
-rw-r--r--src/libcharon/sa/child_sa.h4
-rw-r--r--src/libcharon/sa/ike_sa.c100
-rw-r--r--src/libcharon/sa/ike_sa.h10
-rw-r--r--src/libcharon/sa/ikev1/phase1.c30
-rw-r--r--src/libcharon/sa/ikev1/phase1.h16
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c28
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c6
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c6
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.c131
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c44
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c87
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_config.c141
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.c19
-rw-r--r--src/libhydra/attributes/attribute_handler.h6
-rw-r--r--src/libhydra/attributes/attribute_manager.c65
-rw-r--r--src/libhydra/attributes/attribute_manager.h14
-rw-r--r--src/libhydra/attributes/attribute_provider.h8
-rw-r--r--src/libhydra/attributes/mem_pool.c11
-rw-r--r--src/libhydra/attributes/mem_pool.h7
-rw-r--r--src/libhydra/plugins/attr/attr_provider.c6
-rw-r--r--src/libhydra/plugins/attr_sql/sql_attribute.c123
-rw-r--r--src/libhydra/plugins/resolve/resolve_handler.c77
-rw-r--r--src/starter/args.c2
-rw-r--r--src/starter/cmp.c1
-rw-r--r--src/starter/confread.c79
-rw-r--r--src/starter/confread.h3
-rw-r--r--src/starter/keywords.h6
-rw-r--r--src/starter/keywords.txt4
-rw-r--r--src/starter/starterstroke.c2
-rw-r--r--src/stroke/stroke_msg.h2
71 files changed, 1977 insertions, 733 deletions
diff --git a/NEWS b/NEWS
index fb963fce7..de8afdb90 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,20 @@ strongswan-5.0.1
The plugin initially requests the first registered method or the first method
configured with charon.plugins.eap-dynamic.preferred.
+- The new left/rightdns options specify connection specific DNS servers to
+ request/respond in IKEv2 configuration payloads or IKEv2 mode config. leftdns
+ can be any (comma separated) combination of %config4 and %config6 to request
+ multiple servers, both for IPv4 and IPv6. rightdns takes a list of DNS server
+ IP addresses to return.
+
+- The left/rightsourceip options now accept multiple addresses or pools.
+ leftsourceip can be any (comma separated) combination of %config4, %config6
+ or fixed IP addresses to request. rightsourceip accepts multiple explicitly
+ specified or referenced named pools.
+
+- Multiple connections can now share a single address pool when they use the
+ same definition in one of the rightsourceip pools.
+
- The autotools build has been migrated to use a config.h header. strongSwan
development headers will get installed during "make install" if
--with-dev-headers has been passed to ./configure.
diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index 837a2055a..7c336c451 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -586,6 +586,16 @@ Comma separated list of certificate policy OIDs the peer's certificate must
have.
OIDs are specified using the numerical dotted representation.
.TP
+.BR leftdns " = <servers>"
+Comma separated list of DNS server addresses to exchange as configuration
+attributes. On the initiator, a server is a fixed IPv4 / IPv6 address, or
+.B %config4
+/
+.B %config6
+to request attributes without an address. On the responder,
+only fixed IPv4 /IPv6 addresses are allowed and define DNS servers assigned
+to the client.
+.TP
.BR leftfirewall " = yes | " no
whether the left participant is doing forwarding-firewalling
(including masquerading) using iptables for traffic from \fIleftsubnet\fR,
@@ -691,19 +701,19 @@ and
the latter meaning that the peer must send a certificate request payload in
order to get a certificate in return.
.TP
-.BR leftsourceip " = %config | %cfg | %modeconfig | %modecfg | <ip address>"
-The internal source IP to use in a tunnel, also known as virtual IP. If the
-value is one of the synonyms
+.BR leftsourceip " = %config4 | %config6 | <ip address>"
+Comma separated list of internal source IPs to use in a tunnel, also known as
+virtual IP. If the value is one of the synonyms
.BR %config ,
.BR %cfg ,
.BR %modeconfig ,
or
.BR %modecfg ,
-an address is requested from the peer.
+an address (from the tunnel address family) is requested from the peer.
.TP
.BR rightsourceip " = %config | <network>/<netmask> | %poolname"
-The internal source IP to use in a tunnel for the remote peer. If the
-value is
+Comma separated list of internal source IPs to use in a tunnel for the remote
+peer. If the value is
.B %config
on the responder side, the initiator must propose an address which is then
echoed back. Also supported are address pools expressed as
diff --git a/src/_updown/_updown.in b/src/_updown/_updown.in
index 2c742c010..3a40e2110 100644
--- a/src/_updown/_updown.in
+++ b/src/_updown/_updown.in
@@ -73,8 +73,12 @@
# just the host, this will be 255.255.255.255.
#
# PLUTO_MY_SOURCEIP
-# if non-empty, then the source address for the route will be
-# set to this IP address.
+# PLUTO_MY_SOURCEIP4_$i
+# PLUTO_MY_SOURCEIP6_$i
+# contains IPv4/IPv6 virtual IP received from a responder,
+# $i enumerates from 1 to the number of IP per address family.
+# PLUTO_MY_SOURCEIP is a legacy variable and equals to the first
+# virtual IP, IPv4 or IPv6.
#
# PLUTO_MY_PROTOCOL
# is the IP protocol that will be transported.
@@ -128,6 +132,12 @@
# contains the remote UDP port in the case of ESP_IN_UDP
# encapsulation
#
+# PLUTO_DNS4_$i
+# PLUTO_DNS6_$i
+# contains IPv4/IPv6 DNS server attribute received from a
+# responder, $i enumerates from 1 to the number of servers per
+# address family.
+#
# define a minimum PATH environment in case it is not set
PATH="/sbin:/bin:/usr/sbin:/usr/bin:@sbindir@"
diff --git a/src/charon-nm/nm/nm_handler.c b/src/charon-nm/nm/nm_handler.c
index 408129ebe..28aa04b31 100644
--- a/src/charon-nm/nm/nm_handler.c
+++ b/src/charon-nm/nm/nm_handler.c
@@ -92,15 +92,17 @@ static bool enumerate_dns(enumerator_t *this,
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
- private_nm_handler_t *this, identification_t *server, host_t *vip)
+ private_nm_handler_t *this, identification_t *server, linked_list_t *vips)
{
- if (vip && vip->get_family(vip) == AF_INET)
- { /* no IPv6 attributes yet */
- enumerator_t *enumerator = malloc_thing(enumerator_t);
- /* enumerate DNS attribute first ... */
- enumerator->enumerate = (void*)enumerate_dns;
- enumerator->destroy = (void*)free;
+ if (vips->get_count(vips))
+ {
+ enumerator_t *enumerator;
+ INIT(enumerator,
+ /* enumerate DNS attribute first ... */
+ .enumerate = (void*)enumerate_dns,
+ .destroy = (void*)free,
+ );
return enumerator;
}
return enumerator_create_empty();
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index ccfa210a0..461837c0c 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -507,8 +507,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */
- virtual ? host_create_from_string("0.0.0.0", 0) : NULL,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ FALSE, NULL, NULL); /* mediation */
+ if (virtual)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
+ }
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
auth->add(auth, AUTH_RULE_IDENTITY, user);
diff --git a/src/conftest/config.c b/src/conftest/config.c
index a3f23f3a4..cbc6ac05f 100644
--- a/src/conftest/config.c
+++ b/src/conftest/config.c
@@ -253,7 +253,7 @@ static peer_cfg_t *load_peer_config(private_config_t *this,
ike_cfg = load_ike_config(this, settings, config);
peer_cfg = peer_cfg_create(config, IKEV2, ike_cfg, CERT_ALWAYS_SEND,
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, 0, 0,
- NULL, NULL, FALSE, NULL, NULL);
+ FALSE, NULL, NULL);
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_attr.c b/src/frontends/android/jni/libandroidbridge/backend/android_attr.c
index e8c506950..f9e96a76c 100644
--- a/src/frontends/android/jni/libandroidbridge/backend/android_attr.c
+++ b/src/frontends/android/jni/libandroidbridge/backend/android_attr.c
@@ -80,7 +80,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
- private_android_attr_t *this, identification_t *server, host_t *vip)
+ private_android_attr_t *this, identification_t *server, linked_list_t *vips)
{
enumerator_t *enumerator;
diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c
index dfc0d2342..d1769a99a 100644
--- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c
+++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c
@@ -235,21 +235,36 @@ static bool setup_tun_device(private_android_service_t *this,
ike_sa_t *ike_sa, child_sa_t *child_sa)
{
vpnservice_builder_t *builder;
+ enumerator_t *enumerator;
+ bool vip_found = FALSE;
host_t *vip;
int tunfd;
DBG1(DBG_DMN, "setting up TUN device for CHILD_SA %s{%u}",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa));
- vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
- if (!vip || vip->is_anyaddr(vip))
+
+ builder = charonservice->get_vpnservice_builder(charonservice);
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &vip))
+ {
+ if (!vip->is_anyaddr(vip))
+ {
+ if (!builder->add_address(builder, vip))
+ {
+ break;
+ }
+ vip_found = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!vip_found)
{
DBG1(DBG_DMN, "setting up TUN device failed, no virtual IP found");
return FALSE;
}
-
- builder = charonservice->get_vpnservice_builder(charonservice);
- if (!builder->add_address(builder, vip) ||
- !add_routes(builder, child_sa) ||
+ if (!add_routes(builder, child_sa) ||
!builder->set_mtu(builder, TUN_DEFAULT_MTU))
{
return FALSE;
@@ -427,9 +442,8 @@ static job_requeue_t initiate(private_android_service_t *this)
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
-
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index d16aedc79..59869eab2 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -141,14 +141,14 @@ struct private_peer_cfg_t {
u_int32_t dpd_timeout;
/**
- * virtual IP to use locally
+ * List of virtual IPs (host_t*) to request
*/
- host_t *virtual_ip;
+ linked_list_t *vips;
/**
- * pool to acquire configuration attributes from
+ * List of pool names to use for virtual IP lookup
*/
- char *pool;
+ linked_list_t *pools;
/**
* local authentication configs (rulesets)
@@ -409,16 +409,28 @@ METHOD(peer_cfg_t, get_dpd_timeout, u_int32_t,
return this->dpd_timeout;
}
-METHOD(peer_cfg_t, get_virtual_ip, host_t*,
+METHOD(peer_cfg_t, add_virtual_ip, void,
+ private_peer_cfg_t *this, host_t *vip)
+{
+ this->vips->insert_last(this->vips, vip);
+}
+
+METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*,
private_peer_cfg_t *this)
{
- return this->virtual_ip;
+ return this->vips->create_enumerator(this->vips);
}
-METHOD(peer_cfg_t, get_pool, char*,
+METHOD(peer_cfg_t, add_pool, void,
+ private_peer_cfg_t *this, char *name)
+{
+ this->pools->insert_last(this->pools, strdup(name));
+}
+
+METHOD(peer_cfg_t, create_pool_enumerator, enumerator_t*,
private_peer_cfg_t *this)
{
- return this->pool;
+ return this->pools->create_enumerator(this->pools);
}
METHOD(peer_cfg_t, add_auth_cfg, void,
@@ -521,6 +533,10 @@ static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
METHOD(peer_cfg_t, equals, bool,
private_peer_cfg_t *this, private_peer_cfg_t *other)
{
+ enumerator_t *e1, *e2;
+ host_t *vip1, *vip2;
+ char *pool1, *pool2;
+
if (this == other)
{
return TRUE;
@@ -530,6 +546,43 @@ METHOD(peer_cfg_t, equals, bool,
return FALSE;
}
+ if (this->vips->get_count(this->vips) != other->vips->get_count(other->vips))
+ {
+ return FALSE;
+ }
+ e1 = create_virtual_ip_enumerator(this);
+ e2 = create_virtual_ip_enumerator(other);
+ if (e1->enumerate(e1, &vip1) && e2->enumerate(e2, &vip2))
+ {
+ if (!vip1->ip_equals(vip1, vip2))
+ {
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return FALSE;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
+ if (this->pools->get_count(this->pools) !=
+ other->pools->get_count(other->pools))
+ {
+ return FALSE;
+ }
+ e1 = create_pool_enumerator(this);
+ e2 = create_pool_enumerator(other);
+ if (e1->enumerate(e1, &pool1) && e2->enumerate(e2, &pool2))
+ {
+ if (!streq(pool1, pool2))
+ {
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return FALSE;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+
return (
this->ike_version == other->ike_version &&
this->cert_policy == other->cert_policy &&
@@ -541,11 +594,6 @@ METHOD(peer_cfg_t, equals, bool,
this->jitter_time == other->jitter_time &&
this->over_time == other->over_time &&
this->dpd == other->dpd &&
- (this->virtual_ip == other->virtual_ip ||
- (this->virtual_ip && other->virtual_ip &&
- this->virtual_ip->equals(this->virtual_ip, other->virtual_ip))) &&
- (this->pool == other->pool ||
- (this->pool && other->pool && streq(this->pool, other->pool))) &&
auth_cfg_equal(this, other)
#ifdef ME
&& this->mediation == other->mediation &&
@@ -572,18 +620,18 @@ METHOD(peer_cfg_t, destroy, void,
this->ike_cfg->destroy(this->ike_cfg);
this->child_cfgs->destroy_offset(this->child_cfgs,
offsetof(child_cfg_t, destroy));
- DESTROY_IF(this->virtual_ip);
this->local_auth->destroy_offset(this->local_auth,
offsetof(auth_cfg_t, destroy));
this->remote_auth->destroy_offset(this->remote_auth,
offsetof(auth_cfg_t, destroy));
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->pools->destroy_function(this->pools, free);
#ifdef ME
DESTROY_IF(this->mediated_by);
DESTROY_IF(this->peer_id);
#endif /* ME */
this->mutex->destroy(this->mutex);
free(this->name);
- free(this->pool);
free(this);
}
}
@@ -597,8 +645,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
u_int32_t rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd,
- u_int32_t dpd_timeout, host_t *virtual_ip,
- char *pool, bool mediation, peer_cfg_t *mediated_by,
+ u_int32_t dpd_timeout,
+ bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id)
{
private_peer_cfg_t *this;
@@ -631,8 +679,10 @@ peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
.use_aggressive = _use_aggressive,
.get_dpd = _get_dpd,
.get_dpd_timeout = _get_dpd_timeout,
- .get_virtual_ip = _get_virtual_ip,
- .get_pool = _get_pool,
+ .add_virtual_ip = _add_virtual_ip,
+ .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
+ .add_pool = _add_pool,
+ .create_pool_enumerator = _create_pool_enumerator,
.add_auth_cfg = _add_auth_cfg,
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
.equals = (void*)_equals,
@@ -660,8 +710,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
.aggressive = aggressive,
.dpd = dpd,
.dpd_timeout = dpd_timeout,
- .virtual_ip = virtual_ip,
- .pool = strdupnull(pool),
+ .vips = linked_list_create(),
+ .pools = linked_list_create(),
.local_auth = linked_list_create(),
.remote_auth = linked_list_create(),
.refcount = 1,
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 572153505..f65b91258 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -278,23 +278,34 @@ struct peer_cfg_t {
u_int32_t (*get_dpd_timeout) (peer_cfg_t *this);
/**
- * Get a virtual IP for the local peer.
+ * Add a virtual IP to request as initiator.
*
- * If no virtual IP should be used, NULL is returned. %any means to request
- * a virtual IP using configuration payloads. A specific address is also
- * used for a request and may be changed by the server.
+ * @param vip virtual IP to request, may be %any or %any6
+ */
+ void (*add_virtual_ip)(peer_cfg_t *this, host_t *vip);
+
+ /**
+ * Create an enumerator over virtual IPs to request.
+ *
+ * The returned enumerator enumerates over IPs added with add_virtual_ip().
+ *
+ * @return enumerator over host_t*
+ */
+ enumerator_t* (*create_virtual_ip_enumerator)(peer_cfg_t *this);
+
+ /**
+ * Add a pool name this configuration uses to select virtual IPs.
*
- * @param suggestion NULL, %any or specific
- * @return virtual IP, %any or NULL
+ * @param name pool name to use for virtual IP lookup
*/
- host_t* (*get_virtual_ip) (peer_cfg_t *this);
+ void (*add_pool)(peer_cfg_t *this, char *name);
/**
- * Get the name of the pool to acquire configuration attributes from.
+ * Create an enumerator over pool names of this config.
*
- * @return pool name, NULL if none defined
+ * @return enumerator over char*
*/
- char* (*get_pool)(peer_cfg_t *this);
+ enumerator_t* (*create_pool_enumerator)(peer_cfg_t *this);
#ifdef ME
/**
@@ -374,8 +385,6 @@ struct peer_cfg_t {
* @param aggressive use/accept aggressive mode with IKEv1
* @param dpd DPD check interval, 0 to disable
* @param dpd_timeout DPD timeout interval (IKEv1 only), if 0 default applies
- * @param virtual_ip virtual IP for local host, or NULL
- * @param pool pool name to get configuration attributes from, or NULL
* @param mediation TRUE if this is a mediation connection
* @param mediated_by peer_cfg_t of the mediation connection to mediate through
* @param peer_id ID that identifies our peer at the mediation server
@@ -387,8 +396,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
u_int32_t rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd,
- u_int32_t dpd_timeout, host_t *virtual_ip,
- char *pool, bool mediation, peer_cfg_t *mediated_by,
+ u_int32_t dpd_timeout,
+ bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id);
#endif /** PEER_CFG_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c
index a53962f16..f1d3045ca 100644
--- a/src/libcharon/plugins/android/android_handler.c
+++ b/src/libcharon/plugins/android/android_handler.c
@@ -196,7 +196,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
- android_handler_t *this, identification_t *id, host_t *vip)
+ android_handler_t *this, identification_t *id, linked_list_t *vips)
{
enumerator_t *enumerator;
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index f2d8ddce9..81628b80a 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -275,8 +275,8 @@ static job_requeue_t initiate(private_android_service_t *this)
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
index a6a887780..e46cc4d90 100644
--- a/src/libcharon/plugins/dhcp/dhcp_provider.c
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -84,7 +84,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
private_dhcp_provider_t *this, char *pool,
identification_t *id, host_t *requested)
{
- if (streq(pool, "dhcp"))
+ if (streq(pool, "dhcp") && requested->get_family(requested) == AF_INET)
{
dhcp_transaction_t *transaction, *old;
host_t *vip;
@@ -110,7 +110,7 @@ METHOD(attribute_provider_t, release_address, bool,
private_dhcp_provider_t *this, char *pool,
host_t *address, identification_t *id)
{
- if (streq(pool, "dhcp"))
+ if (streq(pool, "dhcp") && address->get_family(address) == AF_INET)
{
dhcp_transaction_t *transaction;
@@ -129,18 +129,25 @@ METHOD(attribute_provider_t, release_address, bool,
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_dhcp_provider_t *this, char *pool, identification_t *id,
- host_t *vip)
+ private_dhcp_provider_t *this, linked_list_t *pools, identification_t *id,
+ linked_list_t *vips)
{
- dhcp_transaction_t *transaction;
+ dhcp_transaction_t *transaction = NULL;
+ enumerator_t *enumerator;
+ host_t *vip;
- if (!vip)
+ this->mutex->lock(this->mutex);
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &vip))
{
- return NULL;
+ transaction = this->transactions->get(this->transactions,
+ (void*)hash_id_host(id, vip));
+ if (transaction)
+ {
+ break;
+ }
}
- this->mutex->lock(this->mutex);
- transaction = this->transactions->get(this->transactions,
- (void*)hash_id_host(id, vip));
+ enumerator->destroy(enumerator);
if (!transaction)
{
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index 243c76304..7690cf9f8 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -149,6 +149,7 @@ static bool send_message(private_eap_radius_accounting_t *this,
*/
static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
{
+ enumerator_t *enumerator;
host_t *vip;
char buf[64];
chunk_t data;
@@ -157,17 +158,25 @@ static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
message->add(message, RAT_USER_NAME, chunk_create(buf, strlen(buf)));
snprintf(buf, sizeof(buf), "%#H", ike_sa->get_other_host(ike_sa));
message->add(message, RAT_CALLING_STATION_ID, chunk_create(buf, strlen(buf)));
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip && vip->get_family(vip) == AF_INET)
- {
- message->add(message, RAT_FRAMED_IP_ADDRESS, vip->get_address(vip));
- }
- if (vip && vip->get_family(vip) == AF_INET6)
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &vip))
{
- /* we currently assign /128 prefixes, only (reserved, length) */
- data = chunk_from_chars(0, 128);
- data = chunk_cata("cc", data, vip->get_address(vip));
- message->add(message, RAT_FRAMED_IPV6_PREFIX, data);
+ switch (vip->get_family(vip))
+ {
+ case AF_INET:
+ message->add(message, RAT_FRAMED_IP_ADDRESS,
+ vip->get_address(vip));
+ break;
+ case AF_INET6:
+ /* we currently assign /128 prefixes, only (reserved, length) */
+ data = chunk_from_chars(0, 128);
+ data = chunk_cata("cc", data, vip->get_address(vip));
+ message->add(message, RAT_FRAMED_IPV6_PREFIX, data);
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c
index 64bd2b8b7..f18c58b6a 100644
--- a/src/libcharon/plugins/ha/ha_attribute.c
+++ b/src/libcharon/plugins/ha/ha_attribute.c
@@ -181,6 +181,12 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
pool = get_pool(this, name);
if (pool)
{
+ if (pool->base->get_family(pool->base) !=
+ requested->get_family(requested))
+ {
+ this->mutex->unlock(this->mutex);
+ return NULL;
+ }
for (byte = 0; byte < pool->size / 8; byte++)
{
if (pool->mask[byte] != 0xFF)
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 8b6ec9180..f07b4ea21 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -344,10 +344,10 @@ static void process_ike_update(private_ha_dispatcher_t *this,
ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
break;
case HA_LOCAL_VIP:
- ike_sa->set_virtual_ip(ike_sa, TRUE, value.host);
+ ike_sa->add_virtual_ip(ike_sa, TRUE, value.host);
break;
case HA_REMOTE_VIP:
- ike_sa->set_virtual_ip(ike_sa, FALSE, value.host);
+ ike_sa->add_virtual_ip(ike_sa, FALSE, value.host);
received_vip = TRUE;
break;
case HA_PEER_ADDR:
@@ -413,18 +413,24 @@ static void process_ike_update(private_ha_dispatcher_t *this,
}
if (received_vip)
{
+ enumerator_t *pools, *vips;
host_t *vip;
char *pool;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (peer_cfg && vip)
+ if (peer_cfg)
{
- pool = peer_cfg->get_pool(peer_cfg);
- if (pool)
+ pools = peer_cfg->create_pool_enumerator(peer_cfg);
+ while (pools->enumerate(pools, &pool))
{
- this->attr->reserve(this->attr, pool, vip);
+ vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (vips->enumerate(vips, &vip))
+ {
+ this->attr->reserve(this->attr, pool, vip);
+ }
+ vips->destroy(vips);
}
+ pools->destroy(pools);
}
}
if (ike_sa->get_version(ike_sa) == IKEV1)
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index d523e8919..442a3a23d 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -241,6 +241,34 @@ METHOD(listener_t, ike_state_change, bool,
return TRUE;
}
+/**
+ * Send a virtual IP sync message for remote VIPs
+ */
+static void sync_vips(private_ha_ike_t *this, ike_sa_t *ike_sa)
+{
+ ha_message_t *m = NULL;
+ enumerator_t *enumerator;
+ host_t *vip;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &vip))
+ {
+ if (!m)
+ {
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ }
+ m->add_attribute(m, HA_REMOTE_VIP, vip);
+ }
+ enumerator->destroy(enumerator);
+
+ if (m)
+ {
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
+}
+
METHOD(listener_t, message_hook, bool,
private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming, bool plain)
@@ -276,18 +304,7 @@ METHOD(listener_t, message_hook, bool,
{ /* After IKE_SA has been established, sync peers virtual IP.
* We cannot sync it in the state_change hook, it is installed later.
* TODO: where to sync local VIP? */
- ha_message_t *m;
- host_t *vip;
-
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip)
- {
- m = ha_message_create(HA_IKE_UPDATE);
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_REMOTE_VIP, vip);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
- }
+ sync_vips(this, ike_sa);
}
}
if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
@@ -296,7 +313,6 @@ METHOD(listener_t, message_hook, bool,
keymat_v1_t *keymat;
u_int32_t mid;
chunk_t iv;
- host_t *vip;
mid = message->get_message_id(message);
if (mid == 0)
@@ -313,15 +329,7 @@ METHOD(listener_t, message_hook, bool,
}
if (!incoming && message->get_exchange_type(message) == TRANSACTION)
{
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip)
- {
- m = ha_message_create(HA_IKE_UPDATE);
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_REMOTE_VIP, vip);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
- }
+ sync_vips(this, ike_sa);
}
}
if (plain && ike_sa->get_version(ike_sa) == IKEV1 &&
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index ad458caad..541dd9313 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -209,7 +209,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
- 0, NULL, NULL, FALSE, NULL, NULL);
+ 0, FALSE, NULL, NULL);
auth_cfg = auth_cfg_create();
auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index f5da8b892..735f17985 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -268,8 +268,15 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
FALSE, FALSE, /* mobike, aggressive mode */
this->dpd_delay, /* dpd_delay */
this->dpd_timeout, /* dpd_timeout */
- this->vip ? this->vip->clone(this->vip) : NULL,
- this->pool, FALSE, NULL, NULL);
+ FALSE, NULL, NULL);
+ if (this->vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, this->vip->clone(this->vip));
+ }
+ if (this->pool)
+ {
+ peer_cfg->add_pool(peer_cfg, this->pool);
+ }
if (num)
{ /* initiator */
generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index f638a81b7..cb2fc9ebb 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -335,8 +335,8 @@ static gboolean initiate_connection(private_maemo_service_t *this,
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 829c8f05e..a1825effc 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -129,7 +129,6 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
@@ -167,7 +166,6 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
FALSE, med_cfg, /* mediation, med by */
identification_create_from_encoding(ID_KEY_ID, other));
@@ -243,7 +241,6 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index ebc142de2..ff33c53e1 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -94,7 +94,6 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressiv */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 890077157..c614c679e 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -333,6 +333,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
mediation, mediated_by, p_type;
chunk_t l_data, r_data, p_data;
char *name, *virtual, *pool;
+ enumerator_t *enumerator;
while (e->enumerate(e,
&id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data,
@@ -371,8 +372,23 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
peer_cfg = peer_cfg_create(
name, IKEV2, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime,
- mobike, FALSE, dpd_delay, 0, vip, pool,
+ mobike, FALSE, dpd_delay, 0,
mediation, mediated_cfg, peer_id);
+ if (vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, vip);
+ }
+ if (pool)
+ {
+ /* attr-sql used comma separated pools, but we now completely
+ * support multiple pools directly. Support old SQL configs: */
+ enumerator = enumerator_create_token(pool, ",", " ");
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ peer_cfg->add_pool(peer_cfg, pool);
+ }
+ enumerator->destroy(enumerator);
+ }
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
auth->add(auth, AUTH_RULE_IDENTITY, local_id);
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index e561224e9..cebcd984f 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -21,6 +21,7 @@ libstrongswan_stroke_la_SOURCES = \
stroke_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \
+ stroke_handler.h stroke_handler.c \
stroke_list.h stroke_list.c
libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index 1e4615e12..3e012230a 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -17,7 +17,6 @@
#include "stroke_attribute.h"
#include <daemon.h>
-#include <attributes/mem_pool.h>
#include <utils/linked_list.h>
#include <threading/rwlock.h>
@@ -39,12 +38,37 @@ struct private_stroke_attribute_t {
linked_list_t *pools;
/**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
* rwlock to lock access to pools
*/
rwlock_t *lock;
};
/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+ /** name of the connection */
+ char *name;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this->name);
+ free(this);
+}
+
+/**
* find a pool by name
*/
static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
@@ -66,11 +90,12 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_stroke_attribute_t *this, char *name, identification_t *id,
- host_t *requested)
+ private_stroke_attribute_t *this, char *name, identification_t *id,
+ host_t *requested)
{
mem_pool_t *pool;
host_t *addr = NULL;
+
this->lock->read_lock(this->lock);
pool = find_pool(this, name);
if (pool)
@@ -82,11 +107,12 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
METHOD(attribute_provider_t, release_address, bool,
- private_stroke_attribute_t *this, char *name, host_t *address,
- identification_t *id)
+ private_stroke_attribute_t *this, char *name, host_t *address,
+ identification_t *id)
{
mem_pool_t *pool;
bool found = FALSE;
+
this->lock->read_lock(this->lock);
pool = find_pool(this, name);
if (pool)
@@ -97,56 +123,162 @@ METHOD(attribute_provider_t, release_address, bool,
return found;
}
-METHOD(stroke_attribute_t, add_pool, void,
- private_stroke_attribute_t *this, stroke_msg_t *msg)
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+ configuration_attribute_type_t *type,
+ void *dummy, chunk_t *data)
{
- if (msg->add_conn.other.sourceip_mask)
+ host_t *host = *in;
+
+ switch (host->get_family(host))
{
- mem_pool_t *pool;
- host_t *base = NULL;
- u_int32_t bits = 0;
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ *data = host->get_address(host);
+ return TRUE;
+}
- /* if %config, add an empty pool, otherwise */
- if (msg->add_conn.other.sourceip)
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+ private_stroke_attribute_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
+{
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
{
- DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d",
- msg->add_conn.name, msg->add_conn.other.sourceip,
- msg->add_conn.other.sourceip_mask);
- base = host_create_from_string(msg->add_conn.other.sourceip, 0);
- if (!base)
+ if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
{
- DBG1(DBG_CFG, "virtual IP address invalid, discarded");
- return;
+ enumerator->destroy(enumerator);
+ return enumerator_create_filter(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)attr_filter, this->lock,
+ (void*)this->lock->unlock);
}
- bits = msg->add_conn.other.sourceip_mask;
}
- pool = mem_pool_create(msg->add_conn.name, base, bits);
- DESTROY_IF(base);
-
- this->lock->write_lock(this->lock);
- this->pools->insert_last(this->pools, pool);
+ enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
+ return enumerator_create_empty();
}
-METHOD(stroke_attribute_t, del_pool, void,
- private_stroke_attribute_t *this, stroke_msg_t *msg)
+METHOD(stroke_attribute_t, add_pool, void,
+ private_stroke_attribute_t *this, mem_pool_t *pool)
{
enumerator_t *enumerator;
- mem_pool_t *pool;
+ mem_pool_t *current;
+ host_t *base;
+ int size;
+
+ base = pool->get_base(pool);
+ size = pool->get_size(pool);
this->lock->write_lock(this->lock);
+
enumerator = this->pools->create_enumerator(this->pools);
- while (enumerator->enumerate(enumerator, &pool))
+ while (enumerator->enumerate(enumerator, &current))
{
- if (streq(msg->del_conn.name, pool->get_name(pool)))
+ if (base && current->get_base(current) &&
+ base->ip_equals(base, current->get_base(current)) &&
+ size == current->get_size(current))
{
- this->pools->remove_at(this->pools, enumerator);
pool->destroy(pool);
+ pool = NULL;
+ DBG1(DBG_CFG, "reusing virtual IP address pool %H/%d", base, size);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (pool)
+ {
+ if (base)
+ {
+ DBG1(DBG_CFG, "adding virtual IP address pool %H/%d", base, size);
+ }
+ this->pools->insert_last(this->pools, pool);
+ }
+
+ this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_attribute_t, add_dns, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.other.dns)
+ {
+ enumerator_t *enumerator;
+ attributes_t *attr = NULL;
+ host_t *host;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ host = host_create_from_string(token, 0);
+ if (host)
+ {
+ if (!attr)
+ {
+ INIT(attr,
+ .name = strdup(msg->add_conn.name),
+ .dns = linked_list_create(),
+ );
+ }
+ attr->dns->insert_last(attr->dns, host);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (attr)
+ {
+ this->lock->write_lock(this->lock);
+ this->attrs->insert_last(this->attrs, attr);
+ this->lock->unlock(this->lock);
+ }
+ }
+}
+
+METHOD(stroke_attribute_t, del_dns, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ this->lock->write_lock(this->lock);
+
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(msg->del_conn.name, attr->name))
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
break;
}
}
enumerator->destroy(enumerator);
+
this->lock->unlock(this->lock);
}
@@ -158,6 +290,11 @@ static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
void *d3, u_int *offline)
{
mem_pool_t *pool = *poolp;
+
+ if (pool->get_size(pool) == 0)
+ {
+ return FALSE;
+ }
*name = pool->get_name(pool);
*size = pool->get_size(pool);
*online = pool->get_online(pool);
@@ -166,7 +303,7 @@ static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
}
METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
- private_stroke_attribute_t *this)
+ private_stroke_attribute_t *this)
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->pools->create_enumerator(this->pools),
@@ -175,7 +312,7 @@ METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
}
METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
- private_stroke_attribute_t *this, char *name)
+ private_stroke_attribute_t *this, char *name)
{
mem_pool_t *pool;
this->lock->read_lock(this->lock);
@@ -190,10 +327,11 @@ METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
}
METHOD(stroke_attribute_t, destroy, void,
- private_stroke_attribute_t *this)
+ private_stroke_attribute_t *this)
{
this->lock->destroy(this->lock);
this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
free(this);
}
@@ -209,15 +347,17 @@ stroke_attribute_t *stroke_attribute_create()
.provider = {
.acquire_address = _acquire_address,
.release_address = _release_address,
- .create_attribute_enumerator = enumerator_create_empty,
+ .create_attribute_enumerator = _create_attribute_enumerator,
},
.add_pool = _add_pool,
- .del_pool = _del_pool,
+ .add_dns = _add_dns,
+ .del_dns = _del_dns,
.create_pool_enumerator = _create_pool_enumerator,
.create_lease_enumerator = _create_lease_enumerator,
.destroy = _destroy,
},
.pools = linked_list_create(),
+ .attrs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.h b/src/libcharon/plugins/stroke/stroke_attribute.h
index 249a9899b..f1b9d135b 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.h
+++ b/src/libcharon/plugins/stroke/stroke_attribute.h
@@ -23,6 +23,7 @@
#include <stroke_msg.h>
#include <attributes/attribute_provider.h>
+#include <attributes/mem_pool.h>
typedef struct stroke_attribute_t stroke_attribute_t;
@@ -37,18 +38,28 @@ struct stroke_attribute_t {
attribute_provider_t provider;
/**
- * Add a virtual IP address pool.
+ * Add a memory pool to this virtual IP backend.
*
- * @param msg stroke message
+ * The pool gets owned by the provider, or destroyed if such a pool
+ * is already registered.
+ *
+ * @param pool virtual IP pool to add
+ */
+ void (*add_pool)(stroke_attribute_t *this, mem_pool_t *pool);
+
+ /**
+ * Add connection specific DNS servers.
+ *
+ * @param msg stroke add message
*/
- void (*add_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+ void (*add_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
- * Remove a virtual IP address pool.
+ * Remove connection specific DNS servers.
*
- * @param msg stroke message
+ * @param msg stroke del message
*/
- void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+ void (*del_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
* Create an enumerator over installed pools.
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 9dcb9ba0c..e3c78f750 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -52,6 +52,11 @@ struct private_stroke_config_t {
* credentials
*/
stroke_cred_t *cred;
+
+ /**
+ * Virtual IP pool / DNS backend
+ */
+ stroke_attribute_t *attributes;
};
METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
@@ -618,7 +623,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
identification_t *peer_id = NULL;
peer_cfg_t *mediated_by = NULL;
- host_t *vip = NULL;
unique_policy_t unique;
u_int32_t rekey = 0, reauth = 0, over, jitter;
peer_cfg_t *peer_cfg;
@@ -677,49 +681,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
rekey = msg->add_conn.rekey.ike_lifetime - over;
}
- if (msg->add_conn.me.sourceip_mask)
- {
- if (msg->add_conn.me.sourceip)
- {
- vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
- }
- if (!vip)
- { /* if it is set to something like %poolname, request an address */
- if (msg->add_conn.me.subnets)
- { /* use the same family as in local subnet, if any */
- if (strchr(msg->add_conn.me.subnets, '.'))
- {
- vip = host_create_any(AF_INET);
- }
- else
- {
- vip = host_create_any(AF_INET6);
- }
- }
- else if (msg->add_conn.other.subnets)
- { /* use the same family as in remote subnet, if any */
- if (strchr(msg->add_conn.other.subnets, '.'))
- {
- vip = host_create_any(AF_INET);
- }
- else
- {
- vip = host_create_any(AF_INET6);
- }
- }
- else
- {
- if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
- {
- vip = host_create_any(AF_INET6);
- }
- else
- {
- vip = host_create_any(AF_INET);
- }
- }
- }
- }
switch (msg->add_conn.unique)
{
case 1: /* yes */
@@ -747,10 +708,126 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.aggressive,
msg->add_conn.dpd.delay, msg->add_conn.dpd.timeout,
- vip, msg->add_conn.other.sourceip_mask ?
- msg->add_conn.name : msg->add_conn.other.sourceip,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
+ if (msg->add_conn.other.sourceip)
+ {
+ enumerator_t *enumerator;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.other.sourceip,
+ ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
+ streq(token, "%config") || streq(token, "%cfg") ||
+ streq(token, "%config4") || streq(token, "%config6"))
+ {
+ /* empty pool, uses connection name */
+ this->attributes->add_pool(this->attributes,
+ mem_pool_create(msg->add_conn.name, NULL, 0));
+ peer_cfg->add_pool(peer_cfg, msg->add_conn.name);
+ }
+ else if (*token == '%')
+ {
+ /* external named pool */
+ peer_cfg->add_pool(peer_cfg, token + 1);
+ }
+ else
+ {
+ /* in-memory pool, named using CIDR notation */
+ host_t *base;
+ int bits;
+
+ base = host_create_from_subnet(token, &bits);
+ if (base)
+ {
+ this->attributes->add_pool(this->attributes,
+ mem_pool_create(token, base, bits));
+ peer_cfg->add_pool(peer_cfg, token);
+ base->destroy(base);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "IP pool %s invalid, ignored", token);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (msg->add_conn.me.sourceip)
+ {
+ enumerator_t *enumerator;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.me.sourceip, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ host_t *vip = NULL;
+
+ if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
+ streq(token, "%config") || streq(token, "%cfg"))
+ { /* try to deduce an address family */
+ if (msg->add_conn.me.subnets)
+ { /* use the same family as in local subnet, if any */
+ if (strchr(msg->add_conn.me.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else if (msg->add_conn.other.subnets)
+ { /* use the same family as in remote subnet, if any */
+ if (strchr(msg->add_conn.other.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else
+ {
+ if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET);
+ }
+ }
+ }
+ else if (streq(token, "%config4"))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else if (streq(token, "%config6"))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_from_string(token, 0);
+ if (vip)
+ {
+ DBG1(DBG_CFG, "ignored invalid subnet token: %s", token);
+ }
+ }
+
+ if (vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, vip);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
/* build leftauth= */
auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
if (auth_cfg)
@@ -1209,7 +1286,8 @@ METHOD(stroke_config_t, destroy, void,
/*
* see header file
*/
-stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
+ stroke_attribute_t *attributes)
{
private_stroke_config_t *this;
@@ -1229,6 +1307,7 @@ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
.ca = ca,
.cred = cred,
+ .attributes = attributes,
);
return &this->public;
diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h
index 450d517f3..894e03ce4 100644
--- a/src/libcharon/plugins/stroke/stroke_config.h
+++ b/src/libcharon/plugins/stroke/stroke_config.h
@@ -26,6 +26,7 @@
#include <stroke_msg.h>
#include "stroke_ca.h"
#include "stroke_cred.h"
+#include "stroke_attribute.h"
typedef struct stroke_config_t stroke_config_t;
@@ -71,6 +72,7 @@ struct stroke_config_t {
/**
* Create a stroke_config instance.
*/
-stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred);
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
+ stroke_attribute_t *attributes);
#endif /** STROKE_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 163a2a750..233d4088f 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -407,10 +407,10 @@ METHOD(stroke_control_t, rekey, void,
METHOD(stroke_control_t, terminate_srcip, void,
private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
- enumerator_t *enumerator;
+ enumerator_t *enumerator, *vips;
ike_sa_t *ike_sa;
host_t *start = NULL, *end = NULL, *vip;
- chunk_t chunk_start, chunk_end = chunk_empty, chunk_vip;
+ chunk_t chunk_start, chunk_end = chunk_empty, chunk;
if (msg->terminate_srcip.start)
{
@@ -438,33 +438,40 @@ METHOD(stroke_control_t, terminate_srcip, void,
charon->controller, TRUE);
while (enumerator->enumerate(enumerator, &ike_sa))
{
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (!vip)
- {
- continue;
- }
- if (!end)
+ bool match = FALSE;
+
+ vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (vips->enumerate(vips, &vip))
{
- if (!vip->ip_equals(vip, start))
+ if (!end)
{
- continue;
+ if (vip->ip_equals(vip, start))
+ {
+ match = TRUE;
+ break;
+ }
}
- }
- else
- {
- chunk_vip = vip->get_address(vip);
- if (chunk_vip.len != chunk_start.len ||
- chunk_vip.len != chunk_end.len ||
- memcmp(chunk_vip.ptr, chunk_start.ptr, chunk_vip.len) < 0 ||
- memcmp(chunk_vip.ptr, chunk_end.ptr, chunk_vip.len) > 0)
+ else
{
- continue;
+ chunk = vip->get_address(vip);
+ if (chunk.len == chunk_start.len &&
+ chunk.len == chunk_end.len &&
+ memcmp(chunk.ptr, chunk_start.ptr, chunk.len) >= 0 &&
+ memcmp(chunk.ptr, chunk_end.ptr, chunk.len) <= 0)
+ {
+ match = TRUE;
+ break;
+ }
}
}
+ vips->destroy(vips);
- /* schedule delete asynchronously */
- lib->processor->queue_job(lib->processor, (job_t*)
+ if (match)
+ {
+ /* schedule delete asynchronously */
+ lib->processor->queue_job(lib->processor, (job_t*)
delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+ }
}
enumerator->destroy(enumerator);
start->destroy(start);
diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c
new file mode 100644
index 000000000..523151efb
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_handler.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "stroke_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_stroke_handler_t private_stroke_handler_t;
+
+/**
+ * Private data of an stroke_handler_t object.
+ */
+struct private_stroke_handler_t {
+
+ /**
+ * Public stroke_handler_t interface.
+ */
+ stroke_handler_t public;
+
+ /**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+ /** name of the connection */
+ char *name;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+ configuration_attribute_type_t *type,
+ void *dummy, chunk_t *data)
+{
+ host_t *host = *in;
+
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ if (host->is_anyaddr(host))
+ {
+ *data = chunk_empty;
+ }
+ else
+ {
+ *data = host->get_address(host);
+ }
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+ private_stroke_handler_t *this, identification_t *server,
+ linked_list_t *vips)
+{
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
+ {
+ enumerator->destroy(enumerator);
+ return enumerator_create_filter(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)attr_filter, this->lock,
+ (void*)this->lock->unlock);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+ return enumerator_create_empty();
+}
+
+METHOD(stroke_handler_t, add_attributes, void,
+ private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.me.dns)
+ {
+ enumerator_t *enumerator;
+ attributes_t *attr = NULL;
+ host_t *host;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.me.dns, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token, "%config") || streq(token, "%config4"))
+ {
+ host = host_create_any(AF_INET);
+ }
+ else if (streq(token, "%config6"))
+ {
+ host = host_create_any(AF_INET6);
+ }
+ else
+ {
+ host = host_create_from_string(token, 0);
+ }
+ if (host)
+ {
+ if (!attr)
+ {
+ INIT(attr,
+ .name = strdup(msg->add_conn.name),
+ .dns = linked_list_create(),
+ );
+ }
+ attr->dns->insert_last(attr->dns, host);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (attr)
+ {
+ this->lock->write_lock(this->lock);
+ this->attrs->insert_last(this->attrs, attr);
+ this->lock->unlock(this->lock);
+ }
+ }
+}
+
+METHOD(stroke_handler_t, del_attributes, void,
+ private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(msg->del_conn.name, attr->name))
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_handler_t, destroy, void,
+ private_stroke_handler_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+stroke_handler_t *stroke_handler_create()
+{
+ private_stroke_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = (void*)return_false,
+ .release = (void*)return_false,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .add_attributes = _add_attributes,
+ .del_attributes = _del_attributes,
+ .destroy = _destroy,
+ },
+ .attrs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/stroke/stroke_handler.h b/src/libcharon/plugins/stroke/stroke_handler.h
new file mode 100644
index 000000000..ab76f80b0
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_handler.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup stroke_handler stroke_handler
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_HANDLER_H_
+#define STROKE_HANDLER_H_
+
+#include <stroke_msg.h>
+#include <attributes/attribute_handler.h>
+
+typedef struct stroke_handler_t stroke_handler_t;
+
+/**
+ * Handler requesting DNS attributes as defined with leftdns option.
+ */
+struct stroke_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Add connection specific configuration attributes.
+ *
+ * @param msg stroke message
+ */
+ void (*add_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+ /**
+ * Remove connection specific configuration attributes.
+ *
+ * @param msg stroke message
+ */
+ void (*del_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+ /**
+ * Destroy a stroke_handler_t.
+ */
+ void (*destroy)(stroke_handler_t *this);
+};
+
+/**
+ * Create a stroke_handler instance.
+ */
+stroke_handler_t *stroke_handler_create();
+
+#endif /** STROKE_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 6bf65cc7e..241f0fbf6 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -37,6 +37,7 @@
#include "stroke_cred.h"
#include "stroke_ca.h"
#include "stroke_attribute.h"
+#include "stroke_handler.h"
#include "stroke_list.h"
/**
@@ -99,6 +100,11 @@ struct private_stroke_socket_t {
stroke_attribute_t *attribute;
/**
+ * attribute handler (requests only)
+ */
+ stroke_handler_t *handler;
+
+ /**
* controller to control daemon
*/
stroke_control_t *control;
@@ -171,6 +177,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->address);
pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip);
+ pop_string(msg, &end->dns);
pop_string(msg, &end->auth);
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
@@ -188,6 +195,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
DBG2(DBG_CFG, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
+ DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
@@ -235,7 +243,8 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
this->config->add(this->config, msg);
- this->attribute->add_pool(this->attribute, msg);
+ this->attribute->add_dns(this->attribute, msg);
+ this->handler->add_attributes(this->handler, msg);
}
/**
@@ -247,7 +256,8 @@ static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
this->config->del(this->config, msg);
- this->attribute->del_pool(this->attribute, msg);
+ this->attribute->del_dns(this->attribute, msg);
+ this->handler->del_attributes(this->handler, msg);
}
/**
@@ -787,10 +797,12 @@ METHOD(stroke_socket_t, destroy, void,
lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->backends->remove_backend(charon->backends, &this->config->backend);
hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
this->cred->destroy(this->cred);
this->ca->destroy(this->ca);
this->config->destroy(this->config);
this->attribute->destroy(this->attribute);
+ this->handler->destroy(this->handler);
this->control->destroy(this->control);
this->list->destroy(this->list);
free(this);
@@ -817,8 +829,9 @@ stroke_socket_t *stroke_socket_create()
this->cred = stroke_cred_create();
this->attribute = stroke_attribute_create();
+ this->handler = stroke_handler_create();
this->ca = stroke_ca_create(this->cred);
- this->config = stroke_config_create(this->ca, this->cred);
+ this->config = stroke_config_create(this->ca, this->cred, this->attribute);
this->control = stroke_control_create();
this->list = stroke_list_create(this->attribute);
@@ -833,6 +846,7 @@ stroke_socket_t *stroke_socket_create()
lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
lib->processor->queue_job(lib->processor,
(job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index 5b698b8b2..1201f568e 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -178,7 +178,6 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
1800, 900, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
60, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
index 312c8d7e8..30683d83e 100644
--- a/src/libcharon/plugins/updown/Makefile.am
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -12,6 +12,7 @@ endif
libstrongswan_updown_la_SOURCES = \
updown_plugin.h updown_plugin.c \
+ updown_handler.h updown_handler.c \
updown_listener.h updown_listener.c
libstrongswan_updown_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/updown/updown_handler.c b/src/libcharon/plugins/updown/updown_handler.c
new file mode 100644
index 000000000..b2ac02e85
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_handler.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "updown_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_updown_handler_t private_updown_handler_t;
+
+/**
+ * Private data of an updown_handler_t object.
+ */
+struct private_updown_handler_t {
+
+ /**
+ * Public updown_handler_t interface.
+ */
+ updown_handler_t public;
+
+ /**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to an IKE_SA
+ */
+typedef struct {
+ /** unique IKE_SA identifier */
+ u_int id;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this);
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_updown_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attributes_t *current, *attr = NULL;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ host_t *host;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ host = host_create_from_chunk(AF_INET, data, 0);
+ break;
+ case INTERNAL_IP6_DNS:
+ host = host_create_from_chunk(AF_INET6, data, 0);
+ break;
+ default:
+ return FALSE;
+ }
+ if (!host)
+ {
+ return FALSE;
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->id == ike_sa->get_unique_id(ike_sa))
+ {
+ attr = current;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!attr)
+ {
+ INIT(attr,
+ .id = ike_sa->get_unique_id(ike_sa),
+ .dns = linked_list_create(),
+ );
+ this->attrs->insert_last(this->attrs, attr);
+ }
+ attr->dns->insert_last(attr->dns, host);
+ this->lock->unlock(this->lock);
+
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, release, void,
+ private_updown_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attributes_t *attr;
+ enumerator_t *enumerator, *servers;
+ ike_sa_t *ike_sa;
+ host_t *host;
+ bool found = FALSE;
+ int family;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ family = AF_INET;
+ break;
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ break;
+ default:
+ return;
+ }
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->id == ike_sa->get_unique_id(ike_sa))
+ {
+ servers = attr->dns->create_enumerator(attr->dns);
+ while (servers->enumerate(servers, &host))
+ {
+ if (host->get_family(host) == family &&
+ chunk_equals(data, host->get_address(host)))
+ {
+ attr->dns->remove_at(attr->dns, servers);
+ host->destroy(host);
+ found = TRUE;
+ break;
+ }
+ }
+ servers->destroy(servers);
+ if (attr->dns->get_count(attr->dns) == 0)
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ if (found)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+}
+
+METHOD(updown_handler_t, create_dns_enumerator, enumerator_t*,
+ private_updown_handler_t *this, u_int id)
+{
+ attributes_t *attr;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->id == ike_sa->get_unique_id(ike_sa))
+ {
+ enumerator->destroy(enumerator);
+ return enumerator_create_cleaner(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)this->lock->unlock, this->lock);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return enumerator_create_empty();
+}
+
+
+METHOD(updown_handler_t, destroy, void,
+ private_updown_handler_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+updown_handler_t *updown_handler_create()
+{
+ private_updown_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = _handle,
+ .release = _release,
+ .create_attribute_enumerator = enumerator_create_empty,
+ },
+ .create_dns_enumerator = _create_dns_enumerator,
+ .destroy = _destroy,
+ },
+ .attrs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/updown/updown_handler.h b/src/libcharon/plugins/updown/updown_handler.h
new file mode 100644
index 000000000..d4de880b8
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_handler.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup updown_handler updown_handler
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_HANDLER_H_
+#define UPDOWN_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct updown_handler_t updown_handler_t;
+
+/**
+ * Handler storing configuration attributes to pass to updown script.
+ */
+struct updown_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Create an enumerator over received DNS servers.
+ *
+ * @param id unique IKE_SA identifier to get attributes for
+ * @return enumerator over host_t*
+ */
+ enumerator_t* (*create_dns_enumerator)(updown_handler_t *this, u_int id);
+
+ /**
+ * Destroy a updown_handler_t.
+ */
+ void (*destroy)(updown_handler_t *this);
+};
+
+/**
+ * Create a updown_handler instance.
+ */
+updown_handler_t *updown_handler_create();
+
+#endif /** UPDOWN_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 2bd757ec7..2f9f2ef91 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -38,6 +38,11 @@ struct private_updown_listener_t {
* List of cached interface names
*/
linked_list_t *iface_cache;
+
+ /**
+ * DNS attribute handler
+ */
+ updown_handler_t *handler;
};
typedef struct cache_entry_t cache_entry_t;
@@ -90,6 +95,85 @@ static char* uncache_iface(private_updown_listener_t *this, u_int32_t reqid)
return iface;
}
+/**
+ * Create variables for handled DNS attributes
+ */
+static char *make_dns_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+ char total[512] = "", current[64];
+
+ if (!this->handler)
+ {
+ return strdup("");
+ }
+
+ enumerator = this->handler->create_dns_enumerator(this->handler,
+ ike_sa->get_unique_id(ike_sa));
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ snprintf(current, sizeof(current),
+ "PLUTO_DNS4_%d='%H' ", ++v4, host);
+ break;
+ case AF_INET6:
+ snprintf(current, sizeof(current),
+ "PLUTO_DNS6_%d='%H' ", ++v6, host);
+ break;
+ default:
+ continue;
+ }
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ enumerator->destroy(enumerator);
+
+ return strdup(total);
+}
+
+/**
+ * Create variables for local virtual IPs
+ */
+static char *make_vip_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+ char total[512] = "", current[64];
+ bool first = TRUE;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ if (first)
+ { /* legacy variable for first VIP */
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP='%H' ", host);
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP4_%d='%H' ", ++v4, host);
+ break;
+ case AF_INET6:
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP6_%d='%H' ", ++v6, host);
+ break;
+ default:
+ continue;
+ }
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ enumerator->destroy(enumerator);
+
+ return strdup(total);
+}
+
METHOD(listener_t, child_updown, bool,
private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
bool up)
@@ -97,11 +181,10 @@ METHOD(listener_t, child_updown, bool,
traffic_selector_t *my_ts, *other_ts;
enumerator_t *enumerator;
child_cfg_t *config;
- host_t *vip, *me, *other;
+ host_t *me, *other;
char *script;
config = child_sa->get_config(child_sa);
- vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
script = config->get_updown(config);
me = ike_sa->get_my_host(ike_sa);
other = ike_sa->get_other_host(ike_sa);
@@ -117,7 +200,7 @@ METHOD(listener_t, child_updown, bool,
char command[1024];
host_t *my_client, *other_client;
u_int8_t my_client_mask, other_client_mask;
- char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc;
+ char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc, *dns;
mark_t mark;
bool is_host, is_ipv6;
FILE *shell;
@@ -125,20 +208,7 @@ METHOD(listener_t, child_updown, bool,
my_ts->to_subnet(my_ts, &my_client, &my_client_mask);
other_ts->to_subnet(other_ts, &other_client, &other_client_mask);
- if (vip)
- {
- if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0)
- {
- virtual_ip = NULL;
- }
- }
- else
- {
- if (asprintf(&virtual_ip, "") < 0)
- {
- virtual_ip = NULL;
- }
- }
+ virtual_ip = make_vip_vars(this, ike_sa);
/* check for the presence of an inbound mark */
mark = config->get_mark(config, TRUE);
@@ -209,6 +279,8 @@ METHOD(listener_t, child_updown, bool,
iface = uncache_iface(this, child_sa->get_reqid(child_sa));
}
+ dns = make_dns_vars(this, ike_sa);
+
/* determine IPv4/IPv6 and client/host situation */
is_host = my_ts->is_host(my_ts, me);
is_ipv6 = is_host ? (me->get_family(me) == AF_INET6) :
@@ -239,6 +311,7 @@ METHOD(listener_t, child_updown, bool,
"%s"
"%s"
"%s"
+ "%s"
"%s",
up ? "up" : "down",
is_host ? "-host" : "-client",
@@ -259,6 +332,7 @@ METHOD(listener_t, child_updown, bool,
mark_out,
udp_enc,
config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
+ dns,
script);
my_client->destroy(my_client);
other_client->destroy(other_client);
@@ -266,6 +340,7 @@ METHOD(listener_t, child_updown, bool,
free(mark_in);
free(mark_out);
free(udp_enc);
+ free(dns);
free(iface);
DBG3(DBG_CHD, "running updown script: %s", command);
@@ -315,7 +390,7 @@ METHOD(updown_listener_t, destroy, void,
/**
* See header
*/
-updown_listener_t *updown_listener_create()
+updown_listener_t *updown_listener_create(updown_handler_t *handler)
{
private_updown_listener_t *this;
@@ -327,6 +402,7 @@ updown_listener_t *updown_listener_create()
.destroy = _destroy,
},
.iface_cache = linked_list_create(),
+ .handler = handler,
);
return &this->public;
diff --git a/src/libcharon/plugins/updown/updown_listener.h b/src/libcharon/plugins/updown/updown_listener.h
index 5b866c4e5..2d9b56ade 100644
--- a/src/libcharon/plugins/updown/updown_listener.h
+++ b/src/libcharon/plugins/updown/updown_listener.h
@@ -23,6 +23,8 @@
#include <bus/bus.h>
+#include "updown_handler.h"
+
typedef struct updown_listener_t updown_listener_t;
/**
@@ -44,6 +46,6 @@ struct updown_listener_t {
/**
* Create a updown_listener instance.
*/
-updown_listener_t *updown_listener_create();
+updown_listener_t *updown_listener_create(updown_handler_t *handler);
#endif /** UPDOWN_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c
index 2ce2d3257..e1f0d1380 100644
--- a/src/libcharon/plugins/updown/updown_plugin.c
+++ b/src/libcharon/plugins/updown/updown_plugin.c
@@ -15,8 +15,10 @@
#include "updown_plugin.h"
#include "updown_listener.h"
+#include "updown_handler.h"
#include <daemon.h>
+#include <hydra.h>
typedef struct private_updown_plugin_t private_updown_plugin_t;
@@ -34,6 +36,11 @@ struct private_updown_plugin_t {
* Listener interface, listens to CHILD_SA state changes
*/
updown_listener_t *listener;
+
+ /**
+ * Attribute handler, to pass DNS servers to updown
+ */
+ updown_handler_t *handler;
};
METHOD(plugin_t, get_name, char*,
@@ -47,6 +54,12 @@ METHOD(plugin_t, destroy, void,
{
charon->bus->remove_listener(charon->bus, &this->listener->listener);
this->listener->destroy(this->listener);
+ if (this->handler)
+ {
+ hydra->attributes->remove_handler(hydra->attributes,
+ &this->handler->handler);
+ this->handler->destroy(this->handler);
+ }
free(this);
}
@@ -65,9 +78,16 @@ plugin_t *updown_plugin_create()
.destroy = _destroy,
},
},
- .listener = updown_listener_create(),
);
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.updown.dns_handler", FALSE))
+ {
+ this->handler = updown_handler_create();
+ hydra->attributes->add_handler(hydra->attributes,
+ &this->handler->handler);
+ }
+ this->listener = updown_listener_create(this->handler);
charon->bus->add_listener(charon->bus, &this->listener->listener);
return &this->public.plugin;
diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c
index 57f344980..2ebfc6714 100644
--- a/src/libcharon/processing/jobs/migrate_job.c
+++ b/src/libcharon/processing/jobs/migrate_job.c
@@ -79,9 +79,10 @@ METHOD(job_t, execute, job_requeue_t,
}
if (ike_sa)
{
- enumerator_t *children;
+ enumerator_t *children, *enumerator;
child_sa_t *child_sa;
host_t *host;
+ linked_list_t *vips;
children = ike_sa->create_child_sa_enumerator(ike_sa);
while (children->enumerate(children, (void**)&child_sa))
@@ -104,14 +105,22 @@ METHOD(job_t, execute, job_requeue_t,
host->set_port(host, IKEV2_UDP_PORT);
ike_sa->set_other_host(ike_sa, host);
- if (child_sa->update(child_sa, this->local, this->remote,
- ike_sa->get_virtual_ip(ike_sa, TRUE),
+ vips = linked_list_create();
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (child_sa->update(child_sa, this->local, this->remote, vips,
ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
{
ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE));
}
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ vips->destroy(vips);
}
else
{
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index d5adb2527..c3fbd8b53 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -819,9 +819,18 @@ METHOD(child_sa_t, add_policies, status_t,
return status;
}
+/**
+ * Callback to reinstall a virtual IP
+ */
+static void reinstall_vip(host_t *vip, host_t *me)
+{
+ hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
+ hydra->kernel_interface->add_ip(hydra->kernel_interface, vip, me);
+}
+
METHOD(child_sa_t, update, status_t,
- private_child_sa_t *this, host_t *me, host_t *other, host_t *vip,
- bool encap)
+ private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
+ bool encap)
{
child_sa_state_t old;
bool transport_proxy_mode;
@@ -927,13 +936,7 @@ METHOD(child_sa_t, update, status_t,
/* we reinstall the virtual IP to handle interface roaming
* correctly */
- if (vip)
- {
- hydra->kernel_interface->del_ip(hydra->kernel_interface,
- vip);
- hydra->kernel_interface->add_ip(hydra->kernel_interface,
- vip, me);
- }
+ vips->invoke_function(vips, (void*)reinstall_vip, me);
/* reinstall updated policies */
install_policies_internal(this, me, other, my_ts, other_ts,
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index 712a4765c..dae3f2c18 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -346,12 +346,12 @@ struct child_sa_t {
*
* @param me the new local host
* @param other the new remote host
- * @param vip virtual IP, if any
+ * @param vips list of local virtual IPs
* @param TRUE to use UDP encapsulation for NAT traversal
* @return SUCCESS or FAILED
*/
status_t (*update)(child_sa_t *this, host_t *me, host_t *other,
- host_t *vip, bool encap);
+ linked_list_t *vips, bool encap);
/**
* Destroys a child_sa.
*/
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 1e3d00f02..7672accc4 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -182,14 +182,14 @@ struct private_ike_sa_t {
keymat_t *keymat;
/**
- * Virtual IP on local host, if any
+ * Virtual IPs on local host
*/
- host_t *my_virtual_ip;
+ linked_list_t *my_vips;
/**
- * Virtual IP on remote host, if any
+ * Virtual IPs on remote host
*/
- host_t *other_virtual_ip;
+ linked_list_t *other_vips;
/**
* List of configuration attributes (attribute_entry_t)
@@ -735,7 +735,7 @@ METHOD(ike_sa_t, get_keymat, keymat_t*,
return this->keymat;
}
-METHOD(ike_sa_t, set_virtual_ip, void,
+METHOD(ike_sa_t, add_virtual_ip, void,
private_ike_sa_t *this, bool local, host_t *ip)
{
if (local)
@@ -744,39 +744,27 @@ METHOD(ike_sa_t, set_virtual_ip, void,
if (hydra->kernel_interface->add_ip(hydra->kernel_interface, ip,
this->my_host) == SUCCESS)
{
- if (this->my_virtual_ip)
- {
- DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
- hydra->kernel_interface->del_ip(hydra->kernel_interface,
- this->my_virtual_ip);
- }
- DESTROY_IF(this->my_virtual_ip);
- this->my_virtual_ip = ip->clone(ip);
+ this->my_vips->insert_last(this->my_vips, ip->clone(ip));
}
else
{
DBG1(DBG_IKE, "installing virtual IP %H failed", ip);
- this->my_virtual_ip = NULL;
}
}
else
{
- DESTROY_IF(this->other_virtual_ip);
- this->other_virtual_ip = ip->clone(ip);
+ this->other_vips->insert_last(this->other_vips, ip->clone(ip));
}
}
-METHOD(ike_sa_t, get_virtual_ip, host_t*,
+METHOD(ike_sa_t, create_virtual_ip_enumerator, enumerator_t*,
private_ike_sa_t *this, bool local)
{
if (local)
{
- return this->my_virtual_ip;
- }
- else
- {
- return this->other_virtual_ip;
+ return this->my_vips->create_enumerator(this->my_vips);
}
+ return this->other_vips->create_enumerator(this->other_vips);
}
METHOD(ike_sa_t, add_peer_address, void,
@@ -909,7 +897,7 @@ METHOD(ike_sa_t, update_hosts, void,
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->update(child_sa, this->my_host,
- this->other_host, this->my_virtual_ip,
+ this->other_host, this->my_vips,
has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
{
this->public.rekey_child_sa(&this->public,
@@ -1458,7 +1446,7 @@ METHOD(ike_sa_t, reauth, status_t,
if (!has_condition(this, COND_ORIGINAL_INITIATOR))
{
DBG1(DBG_IKE, "initiator did not reauthenticate as requested");
- if (this->other_virtual_ip != NULL ||
+ if (this->other_vips->get_count(this->other_vips) != 0 ||
has_condition(this, COND_XAUTH_AUTHENTICATED) ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
@@ -1562,7 +1550,7 @@ METHOD(ike_sa_t, reestablish, status_t,
/* check if we are able to reestablish this IKE_SA */
if (!has_condition(this, COND_ORIGINAL_INITIATOR) &&
- (this->other_virtual_ip != NULL ||
+ (this->other_vips->get_count(this->other_vips) != 0 ||
has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME
|| this->is_mediation_server
@@ -1585,11 +1573,12 @@ METHOD(ike_sa_t, reestablish, status_t,
host = this->my_host;
new->set_my_host(new, host->clone(host));
/* if we already have a virtual IP, we reuse it */
- host = this->my_virtual_ip;
- if (host)
+ enumerator = this->my_vips->create_enumerator(this->my_vips);
+ while (enumerator->enumerate(enumerator, &host))
{
- new->set_virtual_ip(new, TRUE, host);
+ new->add_virtual_ip(new, TRUE, host);
}
+ enumerator->destroy(enumerator);
#ifdef ME
if (this->peer_cfg->is_mediation(this->peer_cfg))
@@ -1732,7 +1721,7 @@ METHOD(ike_sa_t, set_auth_lifetime, status_t,
* We send the notify in IKE_AUTH if not yet ESTABLISHED. */
send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 &&
!has_condition(this, COND_ORIGINAL_INITIATOR) &&
- (this->other_virtual_ip != NULL ||
+ (this->other_vips->get_count(this->other_vips) != 0 ||
has_condition(this, COND_EAP_AUTHENTICATED));
if (lifetime < diff)
@@ -1937,6 +1926,7 @@ METHOD(ike_sa_t, inherit, void,
attribute_entry_t *entry;
enumerator_t *enumerator;
auth_cfg_t *cfg;
+ host_t *vip;
/* apply hosts and ids */
this->my_host->destroy(this->my_host);
@@ -1948,16 +1938,15 @@ METHOD(ike_sa_t, inherit, void,
this->my_id = other->my_id->clone(other->my_id);
this->other_id = other->other_id->clone(other->other_id);
- /* apply virtual assigned IPs... */
- if (other->my_virtual_ip)
+ /* apply assigned virtual IPs... */
+ while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS)
{
- this->my_virtual_ip = other->my_virtual_ip;
- other->my_virtual_ip = NULL;
+ other->my_vips->insert_first(other->my_vips, vip);
}
- if (other->other_virtual_ip)
+ while (this->other_vips->remove_last(this->other_vips,
+ (void**)&vip) == SUCCESS)
{
- this->other_virtual_ip = other->other_virtual_ip;
- other->other_virtual_ip = NULL;
+ other->other_vips->insert_first(other->other_vips, vip);
}
/* authentication information */
@@ -2032,6 +2021,7 @@ METHOD(ike_sa_t, destroy, void,
private_ike_sa_t *this)
{
attribute_entry_t *entry;
+ host_t *vip;
charon->bus->set_sa(charon->bus, &this->public);
@@ -2056,22 +2046,34 @@ METHOD(ike_sa_t, destroy, void,
DESTROY_IF(this->keymat);
- if (this->my_virtual_ip)
+ while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS)
{
- hydra->kernel_interface->del_ip(hydra->kernel_interface,
- this->my_virtual_ip);
- this->my_virtual_ip->destroy(this->my_virtual_ip);
+ hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
+ vip->destroy(vip);
}
- if (this->other_virtual_ip)
+ this->my_vips->destroy(this->my_vips);
+ while (this->other_vips->remove_last(this->other_vips,
+ (void**)&vip) == SUCCESS)
{
- if (this->peer_cfg && this->peer_cfg->get_pool(this->peer_cfg))
+ if (this->peer_cfg)
{
- hydra->attributes->release_address(hydra->attributes,
- this->peer_cfg->get_pool(this->peer_cfg),
- this->other_virtual_ip, get_other_eap_id(this));
+ enumerator_t *enumerator;
+ char *pool;
+
+ enumerator = this->peer_cfg->create_pool_enumerator(this->peer_cfg);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (hydra->attributes->release_address(hydra->attributes, pool,
+ vip, get_other_eap_id(this)))
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
}
- this->other_virtual_ip->destroy(this->other_virtual_ip);
+ vip->destroy(vip);
}
+ this->other_vips->destroy(this->other_vips);
this->peer_addresses->destroy_offset(this->peer_addresses,
offsetof(host_t, destroy));
#ifdef ME
@@ -2190,8 +2192,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.generate_message = _generate_message,
.reset = _reset,
.get_unique_id = _get_unique_id,
- .set_virtual_ip = _set_virtual_ip,
- .get_virtual_ip = _get_virtual_ip,
+ .add_virtual_ip = _add_virtual_ip,
+ .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
.add_configuration_attribute = _add_configuration_attribute,
.set_kmaddress = _set_kmaddress,
.create_task_enumerator = _create_task_enumerator,
@@ -2226,6 +2228,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.other_auths = linked_list_create(),
.unique_id = ++unique_id,
.peer_addresses = linked_list_create(),
+ .my_vips = linked_list_create(),
+ .other_vips = linked_list_create(),
.attributes = linked_list_create(),
.keepalive_interval = lib->settings->get_time(lib->settings,
"%s.keep_alive", KEEPALIVE_INTERVAL, charon->name),
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index de9e0ede4..d2a394b6c 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -931,7 +931,7 @@ struct ike_sa_t {
status_t (*set_auth_lifetime)(ike_sa_t *this, u_int32_t lifetime);
/**
- * Set the virtual IP to use for this IKE_SA and its children.
+ * Add a virtual IP to use for this IKE_SA and its children.
*
* The virtual IP is assigned per IKE_SA, not per CHILD_SA. It has the same
* lifetime as the IKE_SA.
@@ -939,15 +939,15 @@ struct ike_sa_t {
* @param local TRUE to set local address, FALSE for remote
* @param ip IP to set as virtual IP
*/
- void (*set_virtual_ip) (ike_sa_t *this, bool local, host_t *ip);
+ void (*add_virtual_ip) (ike_sa_t *this, bool local, host_t *ip);
/**
- * Get the virtual IP configured.
+ * Create an enumerator over virtual IPs.
*
* @param local TRUE to get local virtual IP, FALSE for remote
- * @return host_t *virtual IP
+ * @return enumerator over host_t*
*/
- host_t* (*get_virtual_ip) (ike_sa_t *this, bool local);
+ enumerator_t* (*create_virtual_ip_enumerator) (ike_sa_t *this, bool local);
/**
* Register a configuration attribute to the IKE_SA.
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
index e5a48ec49..4096141ec 100644
--- a/src/libcharon/sa/ikev1/phase1.c
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -609,6 +609,34 @@ METHOD(phase1_t, get_id, identification_t*,
return id;
}
+METHOD(phase1_t, has_virtual_ip, bool,
+ private_phase1_t *this, peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ host_t *host;
+
+ enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
+ found = enumerator->enumerate(enumerator, &host);
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
+METHOD(phase1_t, has_pool, bool,
+ private_phase1_t *this, peer_cfg_t *peer_cfg)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE;
+ char *pool;
+
+ enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
+ found = enumerator->enumerate(enumerator, &pool);
+ enumerator->destroy(enumerator);
+
+ return found;
+}
+
METHOD(phase1_t, save_sa_payload, bool,
private_phase1_t *this, message_t *message)
{
@@ -748,6 +776,8 @@ phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
.get_auth_method = _get_auth_method,
.get_id = _get_id,
.select_config = _select_config,
+ .has_virtual_ip = _has_virtual_ip,
+ .has_pool = _has_pool,
.verify_auth = _verify_auth,
.build_auth = _build_auth,
.save_sa_payload = _save_sa_payload,
diff --git a/src/libcharon/sa/ikev1/phase1.h b/src/libcharon/sa/ikev1/phase1.h
index f1e95d88c..eaf8908e7 100644
--- a/src/libcharon/sa/ikev1/phase1.h
+++ b/src/libcharon/sa/ikev1/phase1.h
@@ -109,6 +109,22 @@ struct phase1_t {
identification_t* (*get_id)(phase1_t *this, peer_cfg_t *peer_cfg, bool local);
/**
+ * Check if peer config has virtual IPs pool assigned.
+ *
+ * @param peer_cfg peer_config to check
+ * @return TRUE if peer config contains at least one pool
+ */
+ bool (*has_pool)(phase1_t *this, peer_cfg_t *peer_cfg);
+
+ /**
+ * Check if peer config has virtual IPs to request
+ *
+ * @param peer_cfg peer_config to check
+ * @return TRUE if peer config contains at least one virtual IP
+ */
+ bool (*has_virtual_ip)(phase1_t *this, peer_cfg_t *peer_cfg);
+
+ /**
* Extract and store SA payload bytes from encoded message.
*
* @param message message to extract SA payload bytes from
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 3c84b5114..ea836b76e 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -346,15 +346,30 @@ METHOD(task_manager_t, retransmit, status_t,
*/
static bool mode_config_expected(private_task_manager_t *this)
{
+ enumerator_t *enumerator;
peer_cfg_t *peer_cfg;
+ char *pool;
+ host_t *host;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (peer_cfg && peer_cfg->get_pool(peer_cfg))
+ if (peer_cfg)
{
- if (!this->ike_sa->get_virtual_ip(this->ike_sa, FALSE))
- {
+ enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
+ if (!enumerator->enumerate(enumerator, &pool))
+ { /* no pool configured */
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
+ FALSE);
+ if (!enumerator->enumerate(enumerator, &host))
+ { /* have a pool, but no VIP assigned yet */
+ enumerator->destroy(enumerator);
return TRUE;
}
+ enumerator->destroy(enumerator);
}
return FALSE;
}
@@ -1309,11 +1324,12 @@ METHOD(task_manager_t, queue_ike_reauth, void,
new->set_other_host(new, host->clone(host));
host = this->ike_sa->get_my_host(this->ike_sa);
new->set_my_host(new, host->clone(host));
- host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (host)
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
{
- new->set_virtual_ip(new, TRUE, host);
+ new->add_virtual_ip(new, TRUE, host);
}
+ enumerator->destroy(enumerator);
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, &child_sa))
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 38962fc60..954dea880 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -320,7 +320,7 @@ METHOD(task_t, build_i, status_t,
}
break;
}
- if (this->peer_cfg->get_virtual_ip(this->peer_cfg))
+ if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
@@ -497,8 +497,8 @@ METHOD(task_t, process_r, status_t,
this->ike_sa->get_id(this->ike_sa)));
break;
}
- if (this->peer_cfg->get_pool(this->peer_cfg) == NULL &&
- this->peer_cfg->get_virtual_ip(this->peer_cfg))
+ if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
+ this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index 539286938..9ccf9abf5 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -524,8 +524,8 @@ METHOD(task_t, build_r, status_t,
this->ike_sa->get_id(this->ike_sa)));
break;
}
- if (this->peer_cfg->get_pool(this->peer_cfg) == NULL &&
- this->peer_cfg->get_virtual_ip(this->peer_cfg))
+ if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
+ this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
@@ -658,7 +658,7 @@ METHOD(task_t, process_i, status_t,
}
break;
}
- if (this->peer_cfg->get_virtual_ip(this->peer_cfg))
+ if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index ab3a81386..ef1b35c17 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -42,9 +42,9 @@ struct private_mode_config_t {
bool initiator;
/**
- * virtual ip
+ * Received list of virtual IPs, host_t*
*/
- host_t *virtual_ip;
+ linked_list_t *vips;
/**
* list of attributes requested and its handler, entry_t
@@ -174,8 +174,7 @@ static void process_attribute(private_mode_config_t *this,
}
if (ip)
{
- DESTROY_IF(this->virtual_ip);
- this->virtual_ip = ip;
+ this->vips->insert_last(this->vips, ip);
}
break;
}
@@ -239,23 +238,44 @@ METHOD(task_t, build_i, status_t,
peer_cfg_t *config;
configuration_attribute_type_t type;
chunk_t data;
- host_t *vip;
+ linked_list_t *vips;
+ host_t *host;
+
+ vips = linked_list_create();
/* reuse virtual IP if we already have one */
- vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (!vip)
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (vips->get_count(vips) == 0)
{
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = config->get_virtual_ip(config);
+ enumerator = config->create_virtual_ip_enumerator(config);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
}
- if (vip)
+
+ if (vips->get_count(vips))
{
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
- cp->add_attribute(cp, build_vip(vip));
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ cp->add_attribute(cp, build_vip(host));
+ }
+ enumerator->destroy(enumerator);
}
- enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
- this->ike_sa->get_other_id(this->ike_sa), vip);
+ enumerator = hydra->attributes->create_initiator_enumerator(
+ hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
configuration_attribute_t *ca;
@@ -279,6 +299,8 @@ METHOD(task_t, build_i, status_t,
}
enumerator->destroy(enumerator);
+ vips->destroy(vips);
+
if (cp)
{
message->add_payload(message, (payload_t*)cp);
@@ -299,37 +321,64 @@ METHOD(task_t, build_r, status_t,
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
- host_t *vip = NULL;
cp_payload_t *cp = NULL;
peer_cfg_t *config;
identification_t *id;
+ linked_list_t *vips, *pools;
+ host_t *requested;
id = this->ike_sa->get_other_eap_id(this->ike_sa);
-
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (this->virtual_ip)
+ vips = linked_list_create();
+ pools = linked_list_create();
+
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &requested))
{
- DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
- if (config->get_pool(config))
- {
- vip = hydra->attributes->acquire_address(hydra->attributes,
- config->get_pool(config), id, this->virtual_ip);
- }
- cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
- if (vip)
+ enumerator_t *poolenum;
+ char *pool;
+ host_t *found = NULL;
+
+ /* query all pools until we get an address */
+ DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
+
+ poolenum = config->create_pool_enumerator(config);
+ while (poolenum->enumerate(poolenum, &pool))
{
- DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
- this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
- cp->add_attribute(cp, build_vip(vip));
+ found = hydra->attributes->acquire_address(hydra->attributes,
+ pool, id, requested);
+ if (!found)
+ {
+ continue;
+ }
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
+ this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
+ if (!cp)
+ {
+ cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+ }
+ cp->add_attribute(cp, build_vip(found));
+ /* use pool to request other attributes */
+ if (pools->find_first(pools, NULL, (void**)&pool) == NOT_FOUND)
+ {
+ pools->insert_last(pools, pool);
+ }
+ vips->insert_last(vips, found);
+ break;
}
- else
+ poolenum->destroy(poolenum);
+
+ if (!found)
{
- DBG1(DBG_IKE, "no virtual IP found, sending empty config payload");
+ DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
+ requested, id);
}
}
+ enumerator->destroy(enumerator);
+
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, config->get_pool(config), id, vip);
+ hydra->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
@@ -343,25 +392,35 @@ METHOD(task_t, build_r, status_t,
type, value));
}
enumerator->destroy(enumerator);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ vips->destroy(vips);
if (cp)
{
cp->set_identifier(cp, this->identifier);
message->add_payload(message, (payload_t*)cp);
}
- DESTROY_IF(vip);
return SUCCESS;
}
METHOD(task_t, process_i, status_t,
private_mode_config_t *this, message_t *message)
{
+ enumerator_t *enumerator;
+ host_t *host;
+
process_payloads(this, message);
- if (this->virtual_ip)
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &host))
{
- this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
+ if (!host->is_anyaddr(host))
+ {
+ this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
+ }
}
+ enumerator->destroy(enumerator);
+
return SUCCESS;
}
@@ -374,10 +433,9 @@ METHOD(task_t, get_type, task_type_t,
METHOD(task_t, migrate, void,
private_mode_config_t *this, ike_sa_t *ike_sa)
{
- DESTROY_IF(this->virtual_ip);
-
this->ike_sa = ike_sa;
- this->virtual_ip = NULL;
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->vips = linked_list_create();
this->requested->destroy_function(this->requested, free);
this->requested = linked_list_create();
}
@@ -385,7 +443,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void,
private_mode_config_t *this)
{
- DESTROY_IF(this->virtual_ip);
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->requested->destroy_function(this->requested, free);
free(this);
}
@@ -408,6 +466,7 @@ mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
.initiator = initiator,
.ike_sa = ike_sa,
.requested = linked_list_create(),
+ .vips = linked_list_create(),
);
if (initiator)
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 67d1b45f1..73a23f4ea 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -398,11 +398,12 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
linked_list_t *supplied)
{
traffic_selector_t *ts;
+ enumerator_t *enumerator;
linked_list_t *list;
host_t *host;
- host = this->ike_sa->get_virtual_ip(this->ike_sa, local);
- if (!host)
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, local);
+ if (!enumerator->enumerate(enumerator, &host))
{
if (local)
{
@@ -413,6 +414,7 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
host = this->ike_sa->get_other_host(this->ike_sa);
}
}
+ enumerator->destroy(enumerator);
list = this->config->get_traffic_selectors(this->config, local,
supplied, host);
if (list->get_first(list, (void**)&ts) == SUCCESS)
@@ -831,6 +833,30 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
enumerator->destroy(enumerator);
}
+/**
+ * Get host to use for dynamic traffic selectors
+ */
+static host_t *get_dynamic_host(ike_sa_t *ike_sa, bool local)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
+ if (!enumerator->enumerate(enumerator, &host))
+ {
+ if (local)
+ {
+ host = ike_sa->get_my_host(ike_sa);
+ }
+ else
+ {
+ host = ike_sa->get_other_host(ike_sa);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return host;
+}
+
METHOD(task_t, process_r, status_t,
private_quick_mode_t *this, message_t *message)
{
@@ -841,7 +867,6 @@ METHOD(task_t, process_r, status_t,
sa_payload_t *sa_payload;
linked_list_t *tsi, *tsr, *list = NULL;
peer_cfg_t *peer_cfg;
- host_t *me, *other;
u_int16_t group;
bool private;
@@ -849,16 +874,6 @@ METHOD(task_t, process_r, status_t,
{
return FAILED;
}
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (!me)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (!other)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
tsi = linked_list_create();
tsr = linked_list_create();
@@ -866,7 +881,8 @@ METHOD(task_t, process_r, status_t,
tsr->insert_last(tsr, this->tsr);
this->tsi = this->tsr = NULL;
this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
- me, other);
+ get_dynamic_host(this->ike_sa, TRUE),
+ get_dynamic_host(this->ike_sa, FALSE));
if (this->config)
{
this->tsi = select_ts(this, FALSE, tsi);
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 5c5468dab..d7d912fdc 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -285,6 +285,30 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
}
/**
+ * Get host to use for dynamic traffic selectors
+ */
+static host_t *get_dynamic_host(ike_sa_t *ike_sa, bool local)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
+ if (!enumerator->enumerate(enumerator, &host))
+ {
+ if (local)
+ {
+ host = ike_sa->get_my_host(ike_sa);
+ }
+ else
+ {
+ host = ike_sa->get_other_host(ike_sa);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return host;
+}
+
+/**
* Install a CHILD_SA for usage, return value:
* - FAILED: no acceptable proposal
* - INVALID_ARG: diffie hellman group inacceptable
@@ -298,7 +322,7 @@ static status_t select_and_install(private_child_create_t *this,
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
linked_list_t *my_ts, *other_ts;
- host_t *me, *other, *other_vip, *my_vip;
+ host_t *me, *other;
bool private;
if (this->proposals == NULL)
@@ -314,8 +338,6 @@ static status_t select_and_install(private_child_create_t *this,
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
- my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
this->proposal = this->config->select_proposal(this->config,
@@ -354,15 +376,6 @@ static status_t select_and_install(private_child_create_t *this,
this->dh_group = MODP_NONE;
}
- if (my_vip == NULL)
- {
- my_vip = me;
- }
- if (other_vip == NULL)
- {
- other_vip = other;
- }
-
if (this->initiator)
{
nonce_i = this->my_nonce;
@@ -378,9 +391,9 @@ static status_t select_and_install(private_child_create_t *this,
other_ts = this->tsi;
}
my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts,
- my_vip);
+ get_dynamic_host(this->ike_sa, TRUE));
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
- other_vip);
+ get_dynamic_host(this->ike_sa, FALSE));
if (this->initiator)
{
@@ -723,7 +736,8 @@ static void process_payloads(private_child_create_t *this, message_t *message)
METHOD(task_t, build_i, status_t,
private_child_create_t *this, message_t *message)
{
- host_t *me, *other, *vip;
+ enumerator_t *enumerator;
+ host_t *vip;
peer_cfg_t *peer_cfg;
switch (message->get_exchange_type(message))
@@ -763,22 +777,10 @@ METHOD(task_t, build_i, status_t,
this->config->get_name(this->config));
}
- /* reuse virtual IP if we already have one */
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (me == NULL)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (other == NULL)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
-
/* check if we want a virtual IP, but don't have one */
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = peer_cfg->get_virtual_ip(peer_cfg);
- if (!this->reqid && vip)
+ enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
+ if (!this->reqid && enumerator->enumerate(enumerator, &vip))
{
/* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
vip = host_create_any(vip->get_family(vip));
@@ -788,11 +790,12 @@ METHOD(task_t, build_i, status_t,
}
else
{ /* but narrow it for host2host / if we already have a vip */
- this->tsi = this->config->get_traffic_selectors(this->config, TRUE,
- NULL, me);
+ this->tsi = this->config->get_traffic_selectors(this->config, TRUE, NULL,
+ get_dynamic_host(this->ike_sa, TRUE));
}
- this->tsr = this->config->get_traffic_selectors(this->config, FALSE,
- NULL, other);
+ enumerator->destroy(enumerator);
+ this->tsr = this->config->get_traffic_selectors(this->config, FALSE, NULL,
+ get_dynamic_host(this->ike_sa, FALSE));
if (this->packet_tsi)
{
@@ -948,20 +951,10 @@ METHOD(task_t, build_r, status_t,
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (!this->config && peer_cfg && this->tsi && this->tsr)
{
- host_t *me, *other;
-
- me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (me == NULL)
- {
- me = this->ike_sa->get_my_host(this->ike_sa);
- }
- other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
- if (other == NULL)
- {
- other = this->ike_sa->get_other_host(this->ike_sa);
- }
- this->config = peer_cfg->select_child_cfg(peer_cfg, this->tsr,
- this->tsi, me, other);
+ this->config = peer_cfg->select_child_cfg(peer_cfg,
+ this->tsr, this->tsi,
+ get_dynamic_host(this->ike_sa, TRUE),
+ get_dynamic_host(this->ike_sa, FALSE));
}
if (this->config == NULL)
diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c
index 932b02d42..e788bb5f9 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_config.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.c
@@ -43,9 +43,9 @@ struct private_ike_config_t {
bool initiator;
/**
- * virtual ip
+ * Received list of virtual IPs, host_t*
*/
- host_t *virtual_ip;
+ linked_list_t *vips;
/**
* list of attributes requested and its handler, entry_t
@@ -170,8 +170,7 @@ static void process_attribute(private_ike_config_t *this,
}
if (ip)
{
- DESTROY_IF(this->virtual_ip);
- this->virtual_ip = ip;
+ this->vips->insert_last(this->vips, ip);
}
break;
}
@@ -242,23 +241,45 @@ METHOD(task_t, build_i, status_t,
peer_cfg_t *config;
configuration_attribute_type_t type;
chunk_t data;
- host_t *vip;
+ linked_list_t *vips;
+ host_t *host;
+
+ vips = linked_list_create();
/* reuse virtual IP if we already have one */
- vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
- if (!vip)
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
+ TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
+
+ if (vips->get_count(vips) == 0)
{
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = config->get_virtual_ip(config);
+ enumerator = config->create_virtual_ip_enumerator(config);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
}
- if (vip)
+
+ if (vips->get_count(vips))
{
cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
- cp->add_attribute(cp, build_vip(vip));
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ cp->add_attribute(cp, build_vip(host));
+ }
+ enumerator->destroy(enumerator);
}
- enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
- this->ike_sa->get_other_id(this->ike_sa), vip);
+ enumerator = hydra->attributes->create_initiator_enumerator(
+ hydra->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
configuration_attribute_t *ca;
@@ -284,6 +305,8 @@ METHOD(task_t, build_i, status_t,
}
enumerator->destroy(enumerator);
+ vips->destroy(vips);
+
if (cp)
{
message->add_payload(message, (payload_t*)cp);
@@ -310,40 +333,75 @@ METHOD(task_t, build_r, status_t,
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
- host_t *vip = NULL;
cp_payload_t *cp = NULL;
peer_cfg_t *config;
identification_t *id;
+ linked_list_t *vips, *pools;
+ host_t *requested;
id = this->ike_sa->get_other_eap_id(this->ike_sa);
-
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- if (this->virtual_ip)
+ vips = linked_list_create();
+ pools = linked_list_create();
+
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &requested))
{
- DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
- if (config->get_pool(config))
+ enumerator_t *poolenum;
+ char *pool;
+ host_t *found = NULL;
+
+ /* query all pools until we get an address */
+ DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
+
+ poolenum = config->create_pool_enumerator(config);
+ while (poolenum->enumerate(poolenum, &pool))
{
- vip = hydra->attributes->acquire_address(hydra->attributes,
- config->get_pool(config), id, this->virtual_ip);
+ found = hydra->attributes->acquire_address(hydra->attributes,
+ pool, id, requested);
+ if (!found)
+ {
+ continue;
+ }
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
+ this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
+ if (!cp)
+ {
+ cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
+ }
+ cp->add_attribute(cp, build_vip(found));
+ /* use pool to request other attributes */
+ if (pools->find_first(pools, NULL, (void**)&pool) == NOT_FOUND)
+ {
+ pools->insert_last(pools, pool);
+ }
+ vips->insert_last(vips, found);
+ break;
}
- if (vip == NULL)
+ poolenum->destroy(poolenum);
+
+ if (!found)
{
- DBG1(DBG_IKE, "no virtual IP found, sending %N",
- notify_type_names, INTERNAL_ADDRESS_FAILURE);
- message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
- chunk_empty);
- return SUCCESS;
+ DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
+ requested, id);
}
- DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
- this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
+ }
+ enumerator->destroy(enumerator);
- cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
- cp->add_attribute(cp, build_vip(vip));
+ if (this->vips->get_count(this->vips) && !vips->get_count(vips))
+ {
+ DBG1(DBG_IKE, "no virtual IP found, sending %N",
+ notify_type_names, INTERNAL_ADDRESS_FAILURE);
+ message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
+ chunk_empty);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ pools->destroy(pools);
+ return SUCCESS;
}
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, config->get_pool(config), id, vip);
+ hydra->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
@@ -357,12 +415,13 @@ METHOD(task_t, build_r, status_t,
type, value));
}
enumerator->destroy(enumerator);
+ vips->destroy_offset(vips, offsetof(host_t, destroy));
+ pools->destroy(pools);
if (cp)
{
message->add_payload(message, (payload_t*)cp);
}
- DESTROY_IF(vip);
return SUCCESS;
}
return NEED_MORE;
@@ -373,14 +432,20 @@ METHOD(task_t, process_i, status_t,
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
+ enumerator_t *enumerator;
+ host_t *host;
process_payloads(this, message);
- if (this->virtual_ip &&
- !this->virtual_ip->is_anyaddr(this->virtual_ip))
+ enumerator = this->vips->create_enumerator(this->vips);
+ while (enumerator->enumerate(enumerator, &host))
{
- this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
+ if (!host->is_anyaddr(host))
+ {
+ this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
+ }
}
+ enumerator->destroy(enumerator);
return SUCCESS;
}
return NEED_MORE;
@@ -395,10 +460,9 @@ METHOD(task_t, get_type, task_type_t,
METHOD(task_t, migrate, void,
private_ike_config_t *this, ike_sa_t *ike_sa)
{
- DESTROY_IF(this->virtual_ip);
-
this->ike_sa = ike_sa;
- this->virtual_ip = NULL;
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
+ this->vips = linked_list_create();
this->requested->destroy_function(this->requested, free);
this->requested = linked_list_create();
}
@@ -406,7 +470,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void,
private_ike_config_t *this)
{
- DESTROY_IF(this->virtual_ip);
+ this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->requested->destroy_function(this->requested, free);
free(this);
}
@@ -428,6 +492,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
},
.initiator = initiator,
.ike_sa = ike_sa,
+ .vips = linked_list_create(),
.requested = linked_list_create(),
);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 133bc296e..8c30ed96c 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -250,15 +250,26 @@ static void update_children(private_ike_mobike_t *this)
{
enumerator_t *enumerator;
child_sa_t *child_sa;
+ linked_list_t *vips;
+ host_t *host;
+
+ vips = linked_list_create();
+
+ enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ vips->insert_last(vips, host);
+ }
+ enumerator->destroy(enumerator);
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, (void**)&child_sa))
{
if (child_sa->update(child_sa,
this->ike_sa->get_my_host(this->ike_sa),
- this->ike_sa->get_other_host(this->ike_sa),
- this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
- this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
+ this->ike_sa->get_other_host(this->ike_sa), vips,
+ this->ike_sa->has_condition(this->ike_sa,
+ COND_NAT_ANY)) == NOT_SUPPORTED)
{
this->ike_sa->rekey_child_sa(this->ike_sa,
child_sa->get_protocol(child_sa),
@@ -266,6 +277,8 @@ static void update_children(private_ike_mobike_t *this)
}
}
enumerator->destroy(enumerator);
+
+ vips->destroy(vips);
}
/**
diff --git a/src/libhydra/attributes/attribute_handler.h b/src/libhydra/attributes/attribute_handler.h
index d042f47ef..6014ef0fa 100644
--- a/src/libhydra/attributes/attribute_handler.h
+++ b/src/libhydra/attributes/attribute_handler.h
@@ -22,8 +22,8 @@
#define ATTRIBUTE_HANDLER_H_
#include <chunk.h>
-#include <utils/host.h>
#include <utils/identification.h>
+#include <utils/linked_list.h>
#include "attributes.h"
@@ -62,11 +62,11 @@ struct attribute_handler_t {
* Enumerate attributes to request from a server.
*
* @param server server identity to request attributes from
- * @param vip virtual IP we are requesting, if any
+ * @param vips list of virtual IPs (host_t*) we are requesting
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
- identification_t *server, host_t *vip);
+ identification_t *server, linked_list_t *vips);
};
#endif /** ATTRIBUTE_HANDLER_H_ @}*/
diff --git a/src/libhydra/attributes/attribute_manager.c b/src/libhydra/attributes/attribute_manager.c
index 95520531e..64dc9c7c9 100644
--- a/src/libhydra/attributes/attribute_manager.c
+++ b/src/libhydra/attributes/attribute_manager.c
@@ -51,12 +51,12 @@ struct private_attribute_manager_t {
* Data to pass to enumerator filters
*/
typedef struct {
- /** attribute group pool */
- char *pool;
+ /** attribute group pools */
+ linked_list_t *pools;
/** server/peer identity */
identification_t *id;
- /** requesting/assigned virtual IP */
- host_t *vip;
+ /** requesting/assigned virtual IPs */
+ linked_list_t *vips;
} enum_data_t;
METHOD(attribute_manager_t, acquire_address, host_t*,
@@ -80,14 +80,10 @@ METHOD(attribute_manager_t, acquire_address, host_t*,
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
- if (!host)
- {
- DBG1(DBG_CFG, "acquiring address from pool '%s' failed", pool);
- }
return host;
}
-METHOD(attribute_manager_t, release_address, void,
+METHOD(attribute_manager_t, release_address, bool,
private_attribute_manager_t *this, char *pool, host_t *address,
identification_t *id)
{
@@ -108,10 +104,7 @@ METHOD(attribute_manager_t, release_address, void,
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
- if (!found)
- {
- DBG1(DBG_CFG, "releasing address to pool '%s' failed", pool);
- }
+ return found;
}
/**
@@ -120,19 +113,21 @@ METHOD(attribute_manager_t, release_address, void,
static enumerator_t *responder_enum_create(attribute_provider_t *provider,
enum_data_t *data)
{
- return provider->create_attribute_enumerator(provider, data->pool,
- data->id, data->vip);
+ return provider->create_attribute_enumerator(provider, data->pools,
+ data->id, data->vips);
}
METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
- private_attribute_manager_t *this, char *pool, identification_t *id,
- host_t *vip)
+ private_attribute_manager_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
{
- enum_data_t *data = malloc_thing(enum_data_t);
+ enum_data_t *data;
- data->pool = pool;
- data->id = id;
- data->vip = vip;
+ INIT(data,
+ .pools = pools,
+ .id = id,
+ .vips = vips,
+ );
this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_nested(
@@ -238,8 +233,8 @@ typedef struct {
enumerator_t *inner;
/** server ID we want attributes for */
identification_t *id;
- /** virtual IP we are requesting along with attriubutes */
- host_t *vip;
+ /** virtual IPs we are requesting along with attriubutes */
+ linked_list_t *vips;
} initiator_enumerator_t;
/**
@@ -259,7 +254,7 @@ static bool initiator_enumerate(initiator_enumerator_t *this,
}
DESTROY_IF(this->inner);
this->inner = this->handler->create_attribute_enumerator(this->handler,
- this->id, this->vip);
+ this->id, this->vips);
}
/* inject the handler as additional attribute */
*handler = this->handler;
@@ -278,20 +273,22 @@ static void initiator_destroy(initiator_enumerator_t *this)
}
METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
- private_attribute_manager_t *this, identification_t *id, host_t *vip)
+ private_attribute_manager_t *this, identification_t *id, linked_list_t *vips)
{
- initiator_enumerator_t *enumerator = malloc_thing(initiator_enumerator_t);
+ initiator_enumerator_t *enumerator;
this->lock->read_lock(this->lock);
- enumerator->public.enumerate = (void*)initiator_enumerate;
- enumerator->public.destroy = (void*)initiator_destroy;
- enumerator->this = this;
- enumerator->id = id;
- enumerator->vip = vip;
- enumerator->outer = this->handlers->create_enumerator(this->handlers);
- enumerator->inner = NULL;
- enumerator->handler = NULL;
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)initiator_enumerate,
+ .destroy = (void*)initiator_destroy,
+ },
+ .this = this,
+ .id = id,
+ .vips = vips,
+ .outer = this->handlers->create_enumerator(this->handlers),
+ );
return &enumerator->public;
}
diff --git a/src/libhydra/attributes/attribute_manager.h b/src/libhydra/attributes/attribute_manager.h
index 56afef7c6..8bc80ca11 100644
--- a/src/libhydra/attributes/attribute_manager.h
+++ b/src/libhydra/attributes/attribute_manager.h
@@ -54,20 +54,22 @@ struct attribute_manager_t {
* @param pool pool name from which the address was acquired
* @param address address to release
* @param id peer identity to get address for
+ * @return TRUE if address released to pool
*/
- void (*release_address)(attribute_manager_t *this,
+ bool (*release_address)(attribute_manager_t *this,
char *pool, host_t *address, identification_t *id);
/**
* Create an enumerator over attributes to hand out to a peer.
*
- * @param pool pool name to get attributes from
+ * @param pool list of pools names (char*) to query attributes from
* @param id peer identity to hand out attributes to
- * @param vip virtual IP to assign to peer, if any
+ * @param vip list of virtual IPs (host_t*) to assign to peer
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
- char *pool, identification_t *id, host_t *vip);
+ linked_list_t *pool, identification_t *id,
+ linked_list_t *vips);
/**
* Register an attribute provider to the manager.
@@ -114,11 +116,11 @@ struct attribute_manager_t {
* Create an enumerator over attributes to request from server.
*
* @param id server identity to hand out attributes to
- * @param vip virtual IP going to request, if any
+ * @param vip list of virtual IPs (host_t*) going to request
* @return enumerator (attribute_handler_t, ca_type_t, chunk_t)
*/
enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this,
- identification_t *id, host_t *vip);
+ identification_t *id, linked_list_t *vips);
/**
* Register an attribute handler to the manager.
diff --git a/src/libhydra/attributes/attribute_provider.h b/src/libhydra/attributes/attribute_provider.h
index e4b4e13f3..327135ffe 100644
--- a/src/libhydra/attributes/attribute_provider.h
+++ b/src/libhydra/attributes/attribute_provider.h
@@ -23,6 +23,7 @@
#include <utils/host.h>
#include <utils/identification.h>
+#include <utils/linked_list.h>
typedef struct attribute_provider_t attribute_provider_t;
@@ -56,13 +57,14 @@ struct attribute_provider_t {
/**
* Create an enumerator over attributes to hand out to a peer.
*
- * @param pool pool name to get attributes from
+ * @param pool list of pools names (char*) to query attributes from
* @param id peer ID
- * @param vip virtual IP to assign to peer, if any
+ * @param vip list of virtual IPs (host_t*) to assign to peer
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
- char *pool, identification_t *id, host_t *vip);
+ linked_list_t *pools, identification_t *id,
+ linked_list_t *vips);
};
#endif /** ATTRIBUTE_PROVIDER_H_ @}*/
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c
index f55b3a7d1..b2fed2703 100644
--- a/src/libhydra/attributes/mem_pool.c
+++ b/src/libhydra/attributes/mem_pool.c
@@ -162,6 +162,12 @@ METHOD(mem_pool_t, get_name, const char*,
return this->name;
}
+METHOD(mem_pool_t, get_base, host_t*,
+ private_mem_pool_t *this)
+{
+ return this->base;
+}
+
METHOD(mem_pool_t, get_size, u_int,
private_mem_pool_t *this)
{
@@ -220,11 +226,9 @@ METHOD(mem_pool_t, acquire_address, host_t*,
return requested->clone(requested);
}
- if (!requested->is_anyaddr(requested) &&
- requested->get_family(requested) !=
+ if (requested->get_family(requested) !=
this->base->get_family(this->base))
{
- DBG1(DBG_CFG, "IP pool address family mismatch");
return NULL;
}
@@ -463,6 +467,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
INIT(this,
.public = {
.get_name = _get_name,
+ .get_base = _get_base,
.get_size = _get_size,
.get_online = _get_online,
.get_offline = _get_offline,
diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h
index bb963de93..7b7e58af7 100644
--- a/src/libhydra/attributes/mem_pool.h
+++ b/src/libhydra/attributes/mem_pool.h
@@ -39,6 +39,13 @@ struct mem_pool_t {
const char* (*get_name)(mem_pool_t *this);
/**
+ * Get the base (first) address of this pool.
+ *
+ * @return base address, internal host
+ */
+ host_t* (*get_base)(mem_pool_t *this);
+
+ /**
* Get the size (i.e. number of addresses) of this pool.
*
* @return the size of this pool
diff --git a/src/libhydra/plugins/attr/attr_provider.c b/src/libhydra/plugins/attr/attr_provider.c
index 6af8b473b..673c72116 100644
--- a/src/libhydra/plugins/attr/attr_provider.c
+++ b/src/libhydra/plugins/attr/attr_provider.c
@@ -77,10 +77,10 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in,
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_attr_provider_t *this, char *pool,
- identification_t *id, host_t *vip)
+ private_attr_provider_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
{
- if (vip)
+ if (vips->get_count(vips))
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c
index 714bbcd72..8055be71c 100644
--- a/src/libhydra/plugins/attr_sql/sql_attribute.c
+++ b/src/libhydra/plugins/attr_sql/sql_attribute.c
@@ -233,7 +233,7 @@ static host_t* get_lease(private_sql_attribute_t *this, char *name,
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_sql_attribute_t *this, char *names, identification_t *id,
+ private_sql_attribute_t *this, char *name, identification_t *id,
host_t *requested)
{
host_t *address = NULL;
@@ -242,59 +242,17 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
identity = get_identity(this, id);
if (identity)
{
- /* check for a single pool first (no concatenation and enumeration) */
- if (strchr(names, ',') == NULL)
+ pool = get_pool(this, name, &timeout);
+ if (pool)
{
- pool = get_pool(this, names, &timeout);
- if (pool)
+ /* check for an existing lease */
+ address = check_lease(this, name, pool, identity);
+ if (address == NULL)
{
- /* check for an existing lease */
- address = check_lease(this, names, pool, identity);
- if (address == NULL)
- {
- /* get an unallocated address or expired lease */
- address = get_lease(this, names, pool, timeout, identity);
- }
+ /* get an unallocated address or expired lease */
+ address = get_lease(this, name, pool, timeout, identity);
}
}
- else
- {
- enumerator_t *enumerator;
- char *name;
-
- /* in a first step check for an existing lease over all pools */
- enumerator = enumerator_create_token(names, ",", " ");
- while (enumerator->enumerate(enumerator, &name))
- {
- pool = get_pool(this, name, &timeout);
- if (pool)
- {
- address = check_lease(this, name, pool, identity);
- if (address)
- {
- enumerator->destroy(enumerator);
- return address;
- }
- }
- }
- enumerator->destroy(enumerator);
-
- /* in a second step get an unallocated address or expired lease */
- enumerator = enumerator_create_token(names, ",", " ");
- while (enumerator->enumerate(enumerator, &name))
- {
- pool = get_pool(this, name, &timeout);
- if (pool)
- {
- address = get_lease(this, name, pool, timeout, identity);
- if (address)
- {
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- }
}
return address;
}
@@ -303,50 +261,41 @@ METHOD(attribute_provider_t, release_address, bool,
private_sql_attribute_t *this, char *name, host_t *address,
identification_t *id)
{
- enumerator_t *enumerator;
- bool found = FALSE;
+ u_int pool, timeout;
time_t now = time(NULL);
- enumerator = enumerator_create_token(name, ",", " ");
- while (enumerator->enumerate(enumerator, &name))
+ pool = get_pool(this, name, &timeout);
+ if (pool)
{
- u_int pool, timeout;
-
- pool = get_pool(this, name, &timeout);
- if (pool)
+ if (this->history)
{
- if (this->history)
- {
- this->db->execute(this->db, NULL,
- "INSERT INTO leases (address, identity, acquired, released)"
- " SELECT id, identity, acquired, ? FROM addresses "
- " WHERE pool = ? AND address = ?",
- DB_UINT, now, DB_UINT, pool,
- DB_BLOB, address->get_address(address));
- }
- if (this->db->execute(this->db, NULL,
- "UPDATE addresses SET released = ? WHERE "
- "pool = ? AND address = ?", DB_UINT, time(NULL),
- DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
- {
- found = TRUE;
- break;
- }
+ this->db->execute(this->db, NULL,
+ "INSERT INTO leases (address, identity, acquired, released)"
+ " SELECT id, identity, acquired, ? FROM addresses "
+ " WHERE pool = ? AND address = ?",
+ DB_UINT, now, DB_UINT, pool,
+ DB_BLOB, address->get_address(address));
+ }
+ if (this->db->execute(this->db, NULL,
+ "UPDATE addresses SET released = ? WHERE "
+ "pool = ? AND address = ?", DB_UINT, time(NULL),
+ DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
+ {
+ return TRUE;
}
}
- enumerator->destroy(enumerator);
- return found;
+ return FALSE;
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_sql_attribute_t *this, char *names, identification_t *id,
- host_t *vip)
+ private_sql_attribute_t *this, linked_list_t *pools, identification_t *id,
+ linked_list_t *vips)
{
enumerator_t *attr_enumerator = NULL;
- if (vip)
+ if (vips->get_count(vips))
{
- enumerator_t *names_enumerator;
+ enumerator_t *pool_enumerator;
u_int count;
char *name;
@@ -357,8 +306,8 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
{
u_int identity = get_identity(this, id);
- names_enumerator = enumerator_create_token(names, ",", " ");
- while (names_enumerator->enumerate(names_enumerator, &name))
+ pool_enumerator = pools->create_enumerator(pools);
+ while (pool_enumerator->enumerate(pool_enumerator, &name))
{
u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool)
@@ -385,14 +334,14 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
DESTROY_IF(attr_enumerator);
attr_enumerator = NULL;
}
- names_enumerator->destroy(names_enumerator);
+ pool_enumerator->destroy(pool_enumerator);
}
/* in a second step check for attributes that match name */
if (!attr_enumerator)
{
- names_enumerator = enumerator_create_token(names, ",", " ");
- while (names_enumerator->enumerate(names_enumerator, &name))
+ pool_enumerator = pools->create_enumerator(pools);
+ while (pool_enumerator->enumerate(pool_enumerator, &name))
{
u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool)
@@ -419,7 +368,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
DESTROY_IF(attr_enumerator);
attr_enumerator = NULL;
}
- names_enumerator->destroy(names_enumerator);
+ pool_enumerator->destroy(pool_enumerator);
}
this->db->execute(this->db, NULL, "END TRANSACTION");
diff --git a/src/libhydra/plugins/resolve/resolve_handler.c b/src/libhydra/plugins/resolve/resolve_handler.c
index 011ebbaaf..2bee45d0d 100644
--- a/src/libhydra/plugins/resolve/resolve_handler.c
+++ b/src/libhydra/plugins/resolve/resolve_handler.c
@@ -267,46 +267,71 @@ METHOD(attribute_handler_t, release, void,
typedef struct {
/** implements enumerator_t interface */
enumerator_t public;
- /** virtual IP we are requesting */
- host_t *vip;
+ /** request IPv4 DNS? */
+ bool v4;
+ /** request IPv6 DNS? */
+ bool v6;
} attribute_enumerator_t;
static bool attribute_enumerate(attribute_enumerator_t *this,
configuration_attribute_type_t *type,
chunk_t *data)
{
- switch (this->vip->get_family(this->vip))
+ if (this->v4)
{
- case AF_INET:
- *type = INTERNAL_IP4_DNS;
- break;
- case AF_INET6:
- *type = INTERNAL_IP6_DNS;
- break;
- default:
- return FALSE;
+ *type = INTERNAL_IP4_DNS;
+ *data = chunk_empty;
+ this->v4 = FALSE;
+ return TRUE;
}
- *data = chunk_empty;
- /* enumerate only once */
- this->public.enumerate = (void*)return_false;
- return TRUE;
+ if (this->v6)
+ {
+ *type = INTERNAL_IP6_DNS;
+ *data = chunk_empty;
+ this->v6 = FALSE;
+ return TRUE;
+ }
+ return FALSE;
}
-METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
- private_resolve_handler_t *this, identification_t *server, host_t *vip)
+/**
+ * Check if a list has a host of given family
+ */
+static bool has_host_family(linked_list_t *list, int family)
{
- if (vip)
+ enumerator_t *enumerator;
+ host_t *host;
+ bool found = FALSE;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &host))
{
- attribute_enumerator_t *enumerator;
+ if (host->get_family(host) == family)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
- enumerator = malloc_thing(attribute_enumerator_t);
- enumerator->public.enumerate = (void*)attribute_enumerate;
- enumerator->public.destroy = (void*)free;
- enumerator->vip = vip;
+ return found;
+}
- return &enumerator->public;
- }
- return enumerator_create_empty();
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+ private_resolve_handler_t *this, identification_t *server,
+ linked_list_t *vips)
+{
+ attribute_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)attribute_enumerate,
+ .destroy = (void*)free,
+ },
+ .v4 = has_host_family(vips, AF_INET),
+ .v6 = has_host_family(vips, AF_INET6),
+ );
+ return &enumerator->public;
}
METHOD(resolve_handler_t, destroy, void,
diff --git a/src/starter/args.c b/src/starter/args.c
index 640cc43d6..eb25b2abb 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -186,7 +186,7 @@ static const token_info_t token_info[] =
{ ARG_STR, offsetof(starter_end_t, subnet), NULL },
{ ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
{ ARG_STR, offsetof(starter_end_t, sourceip), NULL },
- { ARG_MISC, 0, NULL /* KW_NATIP */ },
+ { ARG_STR, offsetof(starter_end_t, dns), NULL },
{ ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool },
diff --git a/src/starter/cmp.c b/src/starter/cmp.c
index 724dc7804..aaba7b11d 100644
--- a/src/starter/cmp.c
+++ b/src/starter/cmp.c
@@ -26,7 +26,6 @@ static bool starter_cmp_end(starter_end_t *c1, starter_end_t *c2)
if ((c1 == NULL) || (c2 == NULL))
return FALSE;
- VARCMP(has_natip);
VARCMP(modecfg);
VARCMP(port);
VARCMP(protocol);
diff --git a/src/starter/confread.c b/src/starter/confread.c
index 642fc551b..f30f2188c 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -231,64 +231,6 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
end->host = strdupnull(value);
break;
case KW_SOURCEIP:
- if (end->has_natip)
- {
- DBG1(DBG_APP, "# natip and sourceip cannot be defined at the same time");
- goto err;
- }
- if (value[0] == '%')
- {
- if (streq(value, "%modeconfig") || streq(value, "%modecfg") ||
- streq(value, "%config") || streq(value, "%cfg"))
- {
- /* request ip via config payload */
- free(end->sourceip);
- end->sourceip = NULL;
- end->sourceip_mask = 1;
- }
- else
- { /* %poolname, strip %, serve ip requests */
- free(end->sourceip);
- end->sourceip = strdupnull(value+1);
- end->sourceip_mask = 0;
- }
- end->modecfg = TRUE;
- }
- else
- {
- host_t *host;
- char *sep;
-
- sep = strchr(value, '/');
- if (sep)
- { /* CIDR notation, address pool */
- *sep = '\0';
- host = host_create_from_string(value, 0);
- if (!host)
- {
- DBG1(DBG_APP, "# bad subnet: %s=%s", name, value);
- goto err;
- }
- host->destroy(host);
- free(end->sourceip);
- end->sourceip = strdupnull(value);
- end->sourceip_mask = atoi(sep + 1);
- /* restore the original text in case also= is used */
- *sep = '/';
- }
- else
- { /* fixed srcip */
- host = host_create_from_string(value, 0);
- if (!host)
- {
- DBG1(DBG_APP, "# bad addr: %s=%s", name, value);
- goto err;
- }
- end->sourceip_mask = (host->get_family(host) == AF_INET) ?
- 32 : 128;
- host->destroy(host);
- }
- }
conn->mode = MODE_TUNNEL;
conn->proxy_mode = FALSE;
break;
@@ -370,27 +312,6 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
}
break;
}
- case KW_NATIP:
- {
- host_t *host;
- if (end->sourceip)
- {
- DBG1(DBG_APP, "# natip and sourceip cannot be defined at the same time");
- goto err;
- }
- host = host_create_from_string(value, 0);
- if (!host)
- {
- DBG1(DBG_APP, "# bad addr: %s=%s", name, value);
- goto err;
- }
- host->destroy(host);
- end->sourceip = strdupnull(value);
- end->has_natip = TRUE;
- conn->mode = MODE_TUNNEL;
- conn->proxy_mode = FALSE;
- break;
- }
default:
break;
}
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 0c284229b..3f2079883 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -102,7 +102,6 @@ struct starter_end {
char *host;
u_int ikeport;
char *subnet;
- bool has_natip;
bool modecfg;
certpolicy_t sendcert;
bool firewall;
@@ -112,7 +111,7 @@ struct starter_end {
u_int16_t port;
u_int8_t protocol;
char *sourceip;
- int sourceip_mask;
+ char *dns;
};
typedef struct also also_t;
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index bd9affe6c..537bceb07 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -97,7 +97,7 @@ typedef enum {
KW_SUBNET,
KW_PROTOPORT,
KW_SOURCEIP,
- KW_NATIP,
+ KW_DNS,
KW_FIREWALL,
KW_HOSTACCESS,
KW_ALLOWANY,
@@ -126,7 +126,7 @@ typedef enum {
KW_LEFTSUBNET,
KW_LEFTPROTOPORT,
KW_LEFTSOURCEIP,
- KW_LEFTNATIP,
+ KW_LEFTDNS,
KW_LEFTFIREWALL,
KW_LEFTHOSTACCESS,
KW_LEFTALLOWANY,
@@ -155,7 +155,7 @@ typedef enum {
KW_RIGHTSUBNET,
KW_RIGHTPROTOPORT,
KW_RIGHTSOURCEIP,
- KW_RIGHTNATIP,
+ KW_RIGHTDNS,
KW_RIGHTFIREWALL,
KW_RIGHTHOSTACCESS,
KW_RIGHTALLOWANY,
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index 30d89f924..8366f5209 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -85,7 +85,7 @@ leftsubnet, KW_LEFTSUBNET
leftsubnetwithin, KW_LEFTSUBNET
leftprotoport, KW_LEFTPROTOPORT
leftsourceip, KW_LEFTSOURCEIP
-leftnatip, KW_LEFTNATIP
+leftdns, KW_LEFTDNS
leftfirewall, KW_LEFTFIREWALL
lefthostaccess, KW_LEFTHOSTACCESS
leftallowany, KW_LEFTALLOWANY
@@ -109,7 +109,7 @@ rightsubnet, KW_RIGHTSUBNET
rightsubnetwithin, KW_RIGHTSUBNET
rightprotoport, KW_RIGHTPROTOPORT
rightsourceip, KW_RIGHTSOURCEIP
-rightnatip, KW_RIGHTNATIP
+rightdns, KW_RIGHTDNS
rightfirewall, KW_RIGHTFIREWALL
righthostaccess, KW_RIGHTHOSTACCESS
rightallowany, KW_RIGHTALLOWANY
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 0fbc5d245..d6ad3eb89 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -140,7 +140,7 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
msg_end->ikeport = conn_end->ikeport;
msg_end->subnets = push_string(msg, conn_end->subnet);
msg_end->sourceip = push_string(msg, conn_end->sourceip);
- msg_end->sourceip_mask = conn_end->sourceip_mask;
+ msg_end->dns = push_string(msg, conn_end->dns);
msg_end->sendcert = conn_end->sendcert;
msg_end->hostaccess = conn_end->hostaccess;
msg_end->tohost = !conn_end->subnet;
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 95de7d69b..662feed69 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -158,7 +158,7 @@ struct stroke_end_t {
char *address;
u_int16_t ikeport;
char *sourceip;
- int sourceip_mask;
+ char *dns;
char *subnets;
int sendcert;
int hostaccess;