Merge branch 'multi-vip'

Brings support for multiple virtual IPs and multiple pools in
left/rigthsourceip definitions. Also introduces the new left/rightdns
options to configure requested DNS server address family and respond
with multiple connection specific servers.
This commit is contained in:
Martin Willi
2012-08-31 12:55:56 +02:00
71 changed files with 2004 additions and 760 deletions
+14
View File
@@ -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.
+16 -6
View File
@@ -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
+12 -2
View File
@@ -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@"
+9 -7
View File
@@ -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();
+5 -2
View File
@@ -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);
+1 -1
View File
@@ -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);
@@ -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;
@@ -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);
+72 -22
View File
@@ -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*,
private_peer_cfg_t *this)
METHOD(peer_cfg_t, add_virtual_ip, void,
private_peer_cfg_t *this, host_t *vip)
{
return this->virtual_ip;
this->vips->insert_last(this->vips, vip);
}
METHOD(peer_cfg_t, get_pool, char*,
METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*,
private_peer_cfg_t *this)
{
return this->pool;
return this->vips->create_enumerator(this->vips);
}
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->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,
+24 -15
View File
@@ -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 suggestion NULL, %any or specific
* @return virtual IP, %any or NULL
* @param vip virtual IP to request, may be %any or %any6
*/
host_t* (*get_virtual_ip) (peer_cfg_t *this);
void (*add_virtual_ip)(peer_cfg_t *this, host_t *vip);
/**
* Get the name of the pool to acquire configuration attributes from.
* Create an enumerator over virtual IPs to request.
*
* @return pool name, NULL if none defined
* The returned enumerator enumerates over IPs added with add_virtual_ip().
*
* @return enumerator over host_t*
*/
char* (*get_pool)(peer_cfg_t *this);
enumerator_t* (*create_virtual_ip_enumerator)(peer_cfg_t *this);
/**
* Add a pool name this configuration uses to select virtual IPs.
*
* @param name pool name to use for virtual IP lookup
*/
void (*add_pool)(peer_cfg_t *this, char *name);
/**
* Create an enumerator over pool names of this config.
*
* @return enumerator over char*
*/
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_ @}*/
@@ -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;
@@ -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);
+18 -11
View File
@@ -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)
{
return NULL;
}
this->mutex->lock(this->mutex);
transaction = this->transactions->get(this->transactions,
(void*)hash_id_host(id, vip));
enumerator = vips->create_enumerator(vips);
while (enumerator->enumerate(enumerator, &vip))
{
transaction = this->transactions->get(this->transactions,
(void*)hash_id_host(id, vip));
if (transaction)
{
break;
}
}
enumerator->destroy(enumerator);
if (!transaction)
{
this->mutex->unlock(this->mutex);
@@ -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)
enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
while (enumerator->enumerate(enumerator, &vip))
{
message->add(message, RAT_FRAMED_IP_ADDRESS, vip->get_address(vip));
}
if (vip && vip->get_family(vip) == 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);
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;
}
}
}
+6
View File
@@ -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)
+13 -7
View File
@@ -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)
+30 -22
View File
@@ -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 &&
+1 -1
View File
@@ -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);
@@ -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);
+2 -2
View File
@@ -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);
@@ -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();
@@ -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);
+17 -1
View File
@@ -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);
+1
View File
@@ -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
+183 -43
View File
@@ -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>
@@ -38,12 +37,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
*/
@@ -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;
/* if %config, add an empty pool, otherwise */
if (msg->add_conn.other.sourceip)
{
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)
{
DBG1(DBG_CFG, "virtual IP address invalid, discarded");
return;
}
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);
this->lock->unlock(this->lock);
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;
}
METHOD(stroke_attribute_t, del_pool, void,
private_stroke_attribute_t *this, stroke_msg_t *msg)
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))
{
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_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),
);
@@ -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, stroke_msg_t *msg);
void (*add_pool)(stroke_attribute_t *this, mem_pool_t *pool);
/**
* Remove a virtual IP address pool.
* Add connection specific DNS servers.
*
* @param msg stroke message
* @param msg stroke add message
*/
void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
void (*add_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
* Remove connection specific DNS servers.
*
* @param msg stroke del message
*/
void (*del_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
* Create an enumerator over installed pools.
+126 -47
View File
@@ -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;
+3 -1
View File
@@ -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_ @}*/
+34 -27
View File
@@ -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)
{
if (!vip->ip_equals(vip, start))
{
continue;
}
}
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)
{
continue;
}
}
bool match = FALSE;
/* schedule delete asynchronously */
lib->processor->queue_job(lib->processor, (job_t*)
vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
while (vips->enumerate(vips, &vip))
{
if (!end)
{
if (vip->ip_equals(vip, start))
{
match = TRUE;
break;
}
}
else
{
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);
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);
@@ -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;
}
@@ -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_ @}*/
+17 -3
View File
@@ -37,6 +37,7 @@
#include "stroke_cred.h"
#include "stroke_ca.h"
#include "stroke_attribute.h"
#include "stroke_handler.h"
#include "stroke_list.h"
/**
@@ -98,6 +99,11 @@ struct private_stroke_socket_t {
*/
stroke_attribute_t *attribute;
/**
* attribute handler (requests only)
*/
stroke_handler_t *handler;
/**
* controller to control daemon
*/
@@ -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,
-1
View File
@@ -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);
+1
View File
@@ -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
@@ -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;
}
@@ -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_ @}*/
+94 -18
View File
@@ -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;
@@ -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_ @}*/
+21 -1
View File
@@ -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;
+12 -3
View File
@@ -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
{
+12 -9
View File
@@ -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,
+2 -2
View File
@@ -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.
*/
+52 -48
View File
@@ -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),
+5 -5
View File
@@ -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.
+30
View File
@@ -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,
+16
View File
@@ -108,6 +108,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.
*
+22 -6
View File
@@ -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))
@@ -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));
+3 -3
View File
@@ -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));
+98 -39
View File
@@ -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);
}
if (vip)
{
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
cp->add_attribute(cp, build_vip(vip));
enumerator = config->create_virtual_ip_enumerator(config);
while (enumerator->enumerate(enumerator, &host))
{
vips->insert_last(vips, host);
}
enumerator->destroy(enumerator);
}
enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), vip);
if (vips->get_count(vips))
{
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
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), 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))
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_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;
}
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
if (vip)
poolenum->destroy(poolenum);
if (!found)
{
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));
}
else
{
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)
+30 -14
View File
@@ -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);
+40 -47
View File
@@ -284,6 +284,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
@@ -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)
+111 -46
View File
@@ -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);
}
if (vip)
{
cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
cp->add_attribute(cp, build_vip(vip));
enumerator = config->create_virtual_ip_enumerator(config);
while (enumerator->enumerate(enumerator, &host))
{
vips->insert_last(vips, host);
}
enumerator->destroy(enumerator);
}
enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), vip);
if (vips->get_count(vips))
{
cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
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), 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)
{
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);
}
if (vip == NULL)
{
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, "assigning virtual IP %H to peer '%Y'", vip, id);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
vips = linked_list_create();
pools = linked_list_create();
cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
cp->add_attribute(cp, build_vip(vip));
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &requested))
{
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))
{
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;
}
poolenum->destroy(poolenum);
if (!found)
{
DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
requested, id);
}
}
enumerator->destroy(enumerator);
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(),
);
+16 -3
View File
@@ -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);
}
/**
+3 -3
View File
@@ -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_ @}*/
+31 -34
View File
@@ -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;
}
+8 -6
View File
@@ -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.
+5 -3
View File
@@ -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_ @}*/
+8 -3
View File
@@ -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,
+7
View File
@@ -38,6 +38,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.
*
+3 -3
View File
@@ -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(
+36 -87
View File
@@ -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");
+52 -27
View File
@@ -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;
}
/**
* Check if a list has a host of given family
*/
static bool has_host_family(linked_list_t *list, int family)
{
enumerator_t *enumerator;
host_t *host;
bool found = FALSE;
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &host))
{
if (host->get_family(host) == family)
{
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
return found;
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
private_resolve_handler_t *this, identification_t *server, host_t *vip)
private_resolve_handler_t *this, identification_t *server,
linked_list_t *vips)
{
if (vip)
{
attribute_enumerator_t *enumerator;
attribute_enumerator_t *enumerator;
enumerator = malloc_thing(attribute_enumerator_t);
enumerator->public.enumerate = (void*)attribute_enumerate;
enumerator->public.destroy = (void*)free;
enumerator->vip = vip;
return &enumerator->public;
}
return enumerator_create_empty();
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,
+1 -1
View File
@@ -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 },
-1
View File
@@ -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);
-79
View File
@@ -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;
}
+1 -2
View File
@@ -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;
+3 -3
View File
@@ -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,
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;