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 The plugin initially requests the first registered method or the first method
configured with charon.plugins.eap-dynamic.preferred. 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 - The autotools build has been migrated to use a config.h header. strongSwan
development headers will get installed during "make install" if development headers will get installed during "make install" if
--with-dev-headers has been passed to ./configure. --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. have.
OIDs are specified using the numerical dotted representation. OIDs are specified using the numerical dotted representation.
.TP .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 .BR leftfirewall " = yes | " no
whether the left participant is doing forwarding-firewalling whether the left participant is doing forwarding-firewalling
(including masquerading) using iptables for traffic from \fIleftsubnet\fR, (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 the latter meaning that the peer must send a certificate request payload in
order to get a certificate in return. order to get a certificate in return.
.TP .TP
.BR leftsourceip " = %config | %cfg | %modeconfig | %modecfg | <ip address>" .BR leftsourceip " = %config4 | %config6 | <ip address>"
The internal source IP to use in a tunnel, also known as virtual IP. If the Comma separated list of internal source IPs to use in a tunnel, also known as
value is one of the synonyms virtual IP. If the value is one of the synonyms
.BR %config , .BR %config ,
.BR %cfg , .BR %cfg ,
.BR %modeconfig , .BR %modeconfig ,
or or
.BR %modecfg , .BR %modecfg ,
an address is requested from the peer. an address (from the tunnel address family) is requested from the peer.
.TP .TP
.BR rightsourceip " = %config | <network>/<netmask> | %poolname" .BR rightsourceip " = %config | <network>/<netmask> | %poolname"
The internal source IP to use in a tunnel for the remote peer. If the Comma separated list of internal source IPs to use in a tunnel for the remote
value is peer. If the value is
.B %config .B %config
on the responder side, the initiator must propose an address which is then on the responder side, the initiator must propose an address which is then
echoed back. Also supported are address pools expressed as 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. # just the host, this will be 255.255.255.255.
# #
# PLUTO_MY_SOURCEIP # PLUTO_MY_SOURCEIP
# if non-empty, then the source address for the route will be # PLUTO_MY_SOURCEIP4_$i
# set to this IP address. # 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 # PLUTO_MY_PROTOCOL
# is the IP protocol that will be transported. # is the IP protocol that will be transported.
@@ -128,6 +132,12 @@
# contains the remote UDP port in the case of ESP_IN_UDP # contains the remote UDP port in the case of ESP_IN_UDP
# encapsulation # 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 # define a minimum PATH environment in case it is not set
PATH="/sbin:/bin:/usr/sbin:/usr/bin:@sbindir@" 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*, 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) if (vips->get_count(vips))
{ /* no IPv6 attributes yet */ {
enumerator_t *enumerator = malloc_thing(enumerator_t); enumerator_t *enumerator;
/* enumerate DNS attribute first ... */
enumerator->enumerate = (void*)enumerate_dns;
enumerator->destroy = (void*)free;
INIT(enumerator,
/* enumerate DNS attribute first ... */
.enumerate = (void*)enumerate_dns,
.destroy = (void*)free,
);
return enumerator; return enumerator;
} }
return enumerator_create_empty(); return enumerator_create_empty();
+5 -2
View File
@@ -507,8 +507,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
600, 600, /* jitter, over 10min */ 600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */ 0, 0, /* DPD delay, timeout */
virtual ? host_create_from_string("0.0.0.0", 0) : NULL, FALSE, NULL, NULL); /* mediation */
NULL, FALSE, NULL, NULL); /* pool, mediation */ if (virtual)
{
peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
}
auth = auth_cfg_create(); auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class); auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_class);
auth->add(auth, AUTH_RULE_IDENTITY, user); 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); ike_cfg = load_ike_config(this, settings, config);
peer_cfg = peer_cfg_create(config, IKEV2, ike_cfg, CERT_ALWAYS_SEND, peer_cfg = peer_cfg_create(config, IKEV2, ike_cfg, CERT_ALWAYS_SEND,
UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, 0, 0, UNIQUE_NO, 1, 0, 0, 0, 0, FALSE, FALSE, 0, 0,
NULL, NULL, FALSE, NULL, NULL); FALSE, NULL, NULL);
auth = auth_cfg_create(); auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); 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*, 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; 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) ike_sa_t *ike_sa, child_sa_t *child_sa)
{ {
vpnservice_builder_t *builder; vpnservice_builder_t *builder;
enumerator_t *enumerator;
bool vip_found = FALSE;
host_t *vip; host_t *vip;
int tunfd; int tunfd;
DBG1(DBG_DMN, "setting up TUN device for CHILD_SA %s{%u}", DBG1(DBG_DMN, "setting up TUN device for CHILD_SA %s{%u}",
child_sa->get_name(child_sa), child_sa->get_reqid(child_sa)); 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"); DBG1(DBG_DMN, "setting up TUN device failed, no virtual IP found");
return FALSE; return FALSE;
} }
if (!add_routes(builder, child_sa) ||
builder = charonservice->get_vpnservice_builder(charonservice);
if (!builder->add_address(builder, vip) ||
!add_routes(builder, child_sa) ||
!builder->set_mtu(builder, TUN_DEFAULT_MTU)) !builder->set_mtu(builder, TUN_DEFAULT_MTU))
{ {
return FALSE; return FALSE;
@@ -427,9 +442,8 @@ static job_requeue_t initiate(private_android_service_t *this)
600, 600, /* jitter, over 10min */ 600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */ 0, 0, /* DPD delay, timeout */
host_create_from_string("0.0.0.0", 0) /* virt */, FALSE, NULL, NULL); /* mediation */
NULL, FALSE, NULL, NULL); /* pool, mediation */ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create(); auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); 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; 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) * local authentication configs (rulesets)
@@ -409,16 +409,28 @@ METHOD(peer_cfg_t, get_dpd_timeout, u_int32_t,
return this->dpd_timeout; return this->dpd_timeout;
} }
METHOD(peer_cfg_t, get_virtual_ip, host_t*, METHOD(peer_cfg_t, add_virtual_ip, void,
private_peer_cfg_t *this) 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) 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, 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, METHOD(peer_cfg_t, equals, bool,
private_peer_cfg_t *this, private_peer_cfg_t *other) private_peer_cfg_t *this, private_peer_cfg_t *other)
{ {
enumerator_t *e1, *e2;
host_t *vip1, *vip2;
char *pool1, *pool2;
if (this == other) if (this == other)
{ {
return TRUE; return TRUE;
@@ -530,6 +546,43 @@ METHOD(peer_cfg_t, equals, bool,
return FALSE; 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 ( return (
this->ike_version == other->ike_version && this->ike_version == other->ike_version &&
this->cert_policy == other->cert_policy && this->cert_policy == other->cert_policy &&
@@ -541,11 +594,6 @@ METHOD(peer_cfg_t, equals, bool,
this->jitter_time == other->jitter_time && this->jitter_time == other->jitter_time &&
this->over_time == other->over_time && this->over_time == other->over_time &&
this->dpd == other->dpd && 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) auth_cfg_equal(this, other)
#ifdef ME #ifdef ME
&& this->mediation == other->mediation && && this->mediation == other->mediation &&
@@ -572,18 +620,18 @@ METHOD(peer_cfg_t, destroy, void,
this->ike_cfg->destroy(this->ike_cfg); this->ike_cfg->destroy(this->ike_cfg);
this->child_cfgs->destroy_offset(this->child_cfgs, this->child_cfgs->destroy_offset(this->child_cfgs,
offsetof(child_cfg_t, destroy)); offsetof(child_cfg_t, destroy));
DESTROY_IF(this->virtual_ip);
this->local_auth->destroy_offset(this->local_auth, this->local_auth->destroy_offset(this->local_auth,
offsetof(auth_cfg_t, destroy)); offsetof(auth_cfg_t, destroy));
this->remote_auth->destroy_offset(this->remote_auth, this->remote_auth->destroy_offset(this->remote_auth,
offsetof(auth_cfg_t, destroy)); offsetof(auth_cfg_t, destroy));
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->pools->destroy_function(this->pools, free);
#ifdef ME #ifdef ME
DESTROY_IF(this->mediated_by); DESTROY_IF(this->mediated_by);
DESTROY_IF(this->peer_id); DESTROY_IF(this->peer_id);
#endif /* ME */ #endif /* ME */
this->mutex->destroy(this->mutex); this->mutex->destroy(this->mutex);
free(this->name); free(this->name);
free(this->pool);
free(this); 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 rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time, u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd, bool mobike, bool aggressive, u_int32_t dpd,
u_int32_t dpd_timeout, host_t *virtual_ip, u_int32_t dpd_timeout,
char *pool, bool mediation, peer_cfg_t *mediated_by, bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id) identification_t *peer_id)
{ {
private_peer_cfg_t *this; 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, .use_aggressive = _use_aggressive,
.get_dpd = _get_dpd, .get_dpd = _get_dpd,
.get_dpd_timeout = _get_dpd_timeout, .get_dpd_timeout = _get_dpd_timeout,
.get_virtual_ip = _get_virtual_ip, .add_virtual_ip = _add_virtual_ip,
.get_pool = _get_pool, .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
.add_pool = _add_pool,
.create_pool_enumerator = _create_pool_enumerator,
.add_auth_cfg = _add_auth_cfg, .add_auth_cfg = _add_auth_cfg,
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator, .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
.equals = (void*)_equals, .equals = (void*)_equals,
@@ -660,8 +710,8 @@ peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version,
.aggressive = aggressive, .aggressive = aggressive,
.dpd = dpd, .dpd = dpd,
.dpd_timeout = dpd_timeout, .dpd_timeout = dpd_timeout,
.virtual_ip = virtual_ip, .vips = linked_list_create(),
.pool = strdupnull(pool), .pools = linked_list_create(),
.local_auth = linked_list_create(), .local_auth = linked_list_create(),
.remote_auth = linked_list_create(), .remote_auth = linked_list_create(),
.refcount = 1, .refcount = 1,
+24 -15
View File
@@ -278,23 +278,34 @@ struct peer_cfg_t {
u_int32_t (*get_dpd_timeout) (peer_cfg_t *this); 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 * @param vip virtual IP to request, may be %any or %any6
* 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
*/ */
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 #ifdef ME
/** /**
@@ -374,8 +385,6 @@ struct peer_cfg_t {
* @param aggressive use/accept aggressive mode with IKEv1 * @param aggressive use/accept aggressive mode with IKEv1
* @param dpd DPD check interval, 0 to disable * @param dpd DPD check interval, 0 to disable
* @param dpd_timeout DPD timeout interval (IKEv1 only), if 0 default applies * @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 mediation TRUE if this is a mediation connection
* @param mediated_by peer_cfg_t of the mediation connection to mediate through * @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 * @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 rekey_time, u_int32_t reauth_time,
u_int32_t jitter_time, u_int32_t over_time, u_int32_t jitter_time, u_int32_t over_time,
bool mobike, bool aggressive, u_int32_t dpd, bool mobike, bool aggressive, u_int32_t dpd,
u_int32_t dpd_timeout, host_t *virtual_ip, u_int32_t dpd_timeout,
char *pool, bool mediation, peer_cfg_t *mediated_by, bool mediation, peer_cfg_t *mediated_by,
identification_t *peer_id); identification_t *peer_id);
#endif /** PEER_CFG_H_ @}*/ #endif /** PEER_CFG_H_ @}*/
@@ -196,7 +196,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
} }
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, 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; enumerator_t *enumerator;
@@ -275,8 +275,8 @@ static job_requeue_t initiate(private_android_service_t *this)
600, 600, /* jitter, over 10min */ 600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */ 0, 0, /* DPD delay, timeout */
host_create_from_string("0.0.0.0", 0) /* virt */, FALSE, NULL, NULL); /* mediation */
NULL, FALSE, NULL, NULL); /* pool, mediation */ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create(); auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+16 -9
View File
@@ -84,7 +84,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
private_dhcp_provider_t *this, char *pool, private_dhcp_provider_t *this, char *pool,
identification_t *id, host_t *requested) 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; dhcp_transaction_t *transaction, *old;
host_t *vip; host_t *vip;
@@ -110,7 +110,7 @@ METHOD(attribute_provider_t, release_address, bool,
private_dhcp_provider_t *this, char *pool, private_dhcp_provider_t *this, char *pool,
host_t *address, identification_t *id) host_t *address, identification_t *id)
{ {
if (streq(pool, "dhcp")) if (streq(pool, "dhcp") && address->get_family(address) == AF_INET)
{ {
dhcp_transaction_t *transaction; dhcp_transaction_t *transaction;
@@ -129,18 +129,25 @@ METHOD(attribute_provider_t, release_address, bool,
} }
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
private_dhcp_provider_t *this, char *pool, identification_t *id, private_dhcp_provider_t *this, linked_list_t *pools, identification_t *id,
host_t *vip) 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); this->mutex->lock(this->mutex);
enumerator = vips->create_enumerator(vips);
while (enumerator->enumerate(enumerator, &vip))
{
transaction = this->transactions->get(this->transactions, transaction = this->transactions->get(this->transactions,
(void*)hash_id_host(id, vip)); (void*)hash_id_host(id, vip));
if (transaction)
{
break;
}
}
enumerator->destroy(enumerator);
if (!transaction) if (!transaction)
{ {
this->mutex->unlock(this->mutex); 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) static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
{ {
enumerator_t *enumerator;
host_t *vip; host_t *vip;
char buf[64]; char buf[64];
chunk_t data; 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))); message->add(message, RAT_USER_NAME, chunk_create(buf, strlen(buf)));
snprintf(buf, sizeof(buf), "%#H", ike_sa->get_other_host(ike_sa)); snprintf(buf, sizeof(buf), "%#H", ike_sa->get_other_host(ike_sa));
message->add(message, RAT_CALLING_STATION_ID, chunk_create(buf, strlen(buf))); 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)); switch (vip->get_family(vip))
}
if (vip && vip->get_family(vip) == AF_INET6)
{ {
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) */ /* we currently assign /128 prefixes, only (reserved, length) */
data = chunk_from_chars(0, 128); data = chunk_from_chars(0, 128);
data = chunk_cata("cc", data, vip->get_address(vip)); data = chunk_cata("cc", data, vip->get_address(vip));
message->add(message, RAT_FRAMED_IPV6_PREFIX, data); 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); pool = get_pool(this, name);
if (pool) 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++) for (byte = 0; byte < pool->size / 8; byte++)
{ {
if (pool->mask[byte] != 0xFF) if (pool->mask[byte] != 0xFF)
+12 -6
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)); ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
break; break;
case HA_LOCAL_VIP: 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; break;
case HA_REMOTE_VIP: 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; received_vip = TRUE;
break; break;
case HA_PEER_ADDR: case HA_PEER_ADDR:
@@ -413,18 +413,24 @@ static void process_ike_update(private_ha_dispatcher_t *this,
} }
if (received_vip) if (received_vip)
{ {
enumerator_t *pools, *vips;
host_t *vip; host_t *vip;
char *pool; char *pool;
peer_cfg = ike_sa->get_peer_cfg(ike_sa); peer_cfg = ike_sa->get_peer_cfg(ike_sa);
vip = ike_sa->get_virtual_ip(ike_sa, FALSE); if (peer_cfg)
if (peer_cfg && vip)
{ {
pool = peer_cfg->get_pool(peer_cfg); pools = peer_cfg->create_pool_enumerator(peer_cfg);
if (pool) while (pools->enumerate(pools, &pool))
{
vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
while (vips->enumerate(vips, &vip))
{ {
this->attr->reserve(this->attr, pool, vip); this->attr->reserve(this->attr, pool, vip);
} }
vips->destroy(vips);
}
pools->destroy(pools);
} }
} }
if (ike_sa->get_version(ike_sa) == IKEV1) 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; 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, METHOD(listener_t, message_hook, bool,
private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming, bool plain) bool incoming, bool plain)
@@ -276,18 +304,7 @@ METHOD(listener_t, message_hook, bool,
{ /* After IKE_SA has been established, sync peers virtual IP. { /* After IKE_SA has been established, sync peers virtual IP.
* We cannot sync it in the state_change hook, it is installed later. * We cannot sync it in the state_change hook, it is installed later.
* TODO: where to sync local VIP? */ * TODO: where to sync local VIP? */
ha_message_t *m; sync_vips(this, ike_sa);
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);
}
} }
} }
if (!plain && ike_sa->get_version(ike_sa) == IKEV1) if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
@@ -296,7 +313,6 @@ METHOD(listener_t, message_hook, bool,
keymat_v1_t *keymat; keymat_v1_t *keymat;
u_int32_t mid; u_int32_t mid;
chunk_t iv; chunk_t iv;
host_t *vip;
mid = message->get_message_id(message); mid = message->get_message_id(message);
if (mid == 0) if (mid == 0)
@@ -313,15 +329,7 @@ METHOD(listener_t, message_hook, bool,
} }
if (!incoming && message->get_exchange_type(message) == TRANSACTION) if (!incoming && message->get_exchange_type(message) == TRANSACTION)
{ {
vip = ike_sa->get_virtual_ip(ike_sa, FALSE); sync_vips(this, ike_sa);
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);
}
} }
} }
if (plain && ike_sa->get_version(ike_sa) == IKEV1 && 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)); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND, peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30, 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 = auth_cfg_create();
auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); 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 */ FALSE, FALSE, /* mobike, aggressive mode */
this->dpd_delay, /* dpd_delay */ this->dpd_delay, /* dpd_delay */
this->dpd_timeout, /* dpd_timeout */ this->dpd_timeout, /* dpd_timeout */
this->vip ? this->vip->clone(this->vip) : NULL, FALSE, NULL, NULL);
this->pool, 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) if (num)
{ /* initiator */ { /* initiator */
generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num); 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 */ 600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */ 0, 0, /* DPD delay, timeout */
host_create_from_string("0.0.0.0", 0) /* virt */, FALSE, NULL, NULL); /* mediation */
NULL, FALSE, NULL, NULL); /* pool, mediation */ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create(); auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); 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 */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */ this->dpd, 0, /* DPD delay, timeout */
NULL, NULL, /* vip, pool */
TRUE, NULL, NULL); /* mediation, med by, peer id */ TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e); 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 */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */ this->dpd, 0, /* DPD delay, timeout */
NULL, NULL, /* vip, pool */
FALSE, med_cfg, /* mediation, med by */ FALSE, med_cfg, /* mediation, med by */
identification_create_from_encoding(ID_KEY_ID, other)); 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 */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */ this->dpd, 0, /* DPD delay, timeout */
NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */ FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create(); 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 */ this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressiv */ TRUE, FALSE, /* mobike, aggressiv */
this->dpd, 0, /* DPD delay, timeout */ this->dpd, 0, /* DPD delay, timeout */
NULL, NULL, /* vip, pool */
TRUE, NULL, NULL); /* mediation, med by, peer id */ TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e); 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; mediation, mediated_by, p_type;
chunk_t l_data, r_data, p_data; chunk_t l_data, r_data, p_data;
char *name, *virtual, *pool; char *name, *virtual, *pool;
enumerator_t *enumerator;
while (e->enumerate(e, while (e->enumerate(e,
&id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data, &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( peer_cfg = peer_cfg_create(
name, IKEV2, ike, cert_policy, uniqueid, name, IKEV2, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime, keyingtries, rekeytime, reauthtime, jitter, overtime,
mobike, FALSE, dpd_delay, 0, vip, pool, mobike, FALSE, dpd_delay, 0,
mediation, mediated_cfg, peer_id); 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 = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method); auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
auth->add(auth, AUTH_RULE_IDENTITY, local_id); 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_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \ stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \ stroke_attribute.h stroke_attribute.c \
stroke_handler.h stroke_handler.c \
stroke_list.h stroke_list.c stroke_list.h stroke_list.c
libstrongswan_stroke_la_LDFLAGS = -module -avoid-version libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
+175 -35
View File
@@ -17,7 +17,6 @@
#include "stroke_attribute.h" #include "stroke_attribute.h"
#include <daemon.h> #include <daemon.h>
#include <attributes/mem_pool.h>
#include <utils/linked_list.h> #include <utils/linked_list.h>
#include <threading/rwlock.h> #include <threading/rwlock.h>
@@ -38,12 +37,37 @@ struct private_stroke_attribute_t {
*/ */
linked_list_t *pools; linked_list_t *pools;
/**
* List of connection specific attributes, as attributes_t
*/
linked_list_t *attrs;
/** /**
* rwlock to lock access to pools * rwlock to lock access to pools
*/ */
rwlock_t *lock; 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 * find a pool by name
*/ */
@@ -71,6 +95,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
{ {
mem_pool_t *pool; mem_pool_t *pool;
host_t *addr = NULL; host_t *addr = NULL;
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
pool = find_pool(this, name); pool = find_pool(this, name);
if (pool) if (pool)
@@ -87,6 +112,7 @@ METHOD(attribute_provider_t, release_address, bool,
{ {
mem_pool_t *pool; mem_pool_t *pool;
bool found = FALSE; bool found = FALSE;
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
pool = find_pool(this, name); pool = find_pool(this, name);
if (pool) if (pool)
@@ -97,56 +123,162 @@ METHOD(attribute_provider_t, release_address, bool,
return found; 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;
{
mem_pool_t *pool;
host_t *base = NULL;
u_int32_t bits = 0;
/* if %config, add an empty pool, otherwise */ switch (host->get_family(host))
if (msg->add_conn.other.sourceip)
{ {
DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d", case AF_INET:
msg->add_conn.name, msg->add_conn.other.sourceip, *type = INTERNAL_IP4_DNS;
msg->add_conn.other.sourceip_mask); break;
base = host_create_from_string(msg->add_conn.other.sourceip, 0); case AF_INET6:
if (!base) *type = INTERNAL_IP6_DNS;
{ break;
DBG1(DBG_CFG, "virtual IP address invalid, discarded"); default:
return; return FALSE;
}
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);
} }
*data = host->get_address(host);
return TRUE;
} }
METHOD(stroke_attribute_t, del_pool, void, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
private_stroke_attribute_t *this, stroke_msg_t *msg) 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; 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); this->lock->write_lock(this->lock);
enumerator = this->pools->create_enumerator(this->pools); 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->destroy(pool);
pool = NULL;
DBG1(DBG_CFG, "reusing virtual IP address pool %H/%d", base, size);
break; break;
} }
} }
enumerator->destroy(enumerator); 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); 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) void *d3, u_int *offline)
{ {
mem_pool_t *pool = *poolp; mem_pool_t *pool = *poolp;
if (pool->get_size(pool) == 0)
{
return FALSE;
}
*name = pool->get_name(pool); *name = pool->get_name(pool);
*size = pool->get_size(pool); *size = pool->get_size(pool);
*online = pool->get_online(pool); *online = pool->get_online(pool);
@@ -194,6 +331,7 @@ METHOD(stroke_attribute_t, destroy, void,
{ {
this->lock->destroy(this->lock); this->lock->destroy(this->lock);
this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy)); this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
free(this); free(this);
} }
@@ -209,15 +347,17 @@ stroke_attribute_t *stroke_attribute_create()
.provider = { .provider = {
.acquire_address = _acquire_address, .acquire_address = _acquire_address,
.release_address = _release_address, .release_address = _release_address,
.create_attribute_enumerator = enumerator_create_empty, .create_attribute_enumerator = _create_attribute_enumerator,
}, },
.add_pool = _add_pool, .add_pool = _add_pool,
.del_pool = _del_pool, .add_dns = _add_dns,
.del_dns = _del_dns,
.create_pool_enumerator = _create_pool_enumerator, .create_pool_enumerator = _create_pool_enumerator,
.create_lease_enumerator = _create_lease_enumerator, .create_lease_enumerator = _create_lease_enumerator,
.destroy = _destroy, .destroy = _destroy,
}, },
.pools = linked_list_create(), .pools = linked_list_create(),
.attrs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
); );
@@ -23,6 +23,7 @@
#include <stroke_msg.h> #include <stroke_msg.h>
#include <attributes/attribute_provider.h> #include <attributes/attribute_provider.h>
#include <attributes/mem_pool.h>
typedef struct stroke_attribute_t stroke_attribute_t; typedef struct stroke_attribute_t stroke_attribute_t;
@@ -37,18 +38,28 @@ struct stroke_attribute_t {
attribute_provider_t provider; 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. * Create an enumerator over installed pools.
+113 -34
View File
@@ -52,6 +52,11 @@ struct private_stroke_config_t {
* credentials * credentials
*/ */
stroke_cred_t *cred; stroke_cred_t *cred;
/**
* Virtual IP pool / DNS backend
*/
stroke_attribute_t *attributes;
}; };
METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, 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; identification_t *peer_id = NULL;
peer_cfg_t *mediated_by = NULL; peer_cfg_t *mediated_by = NULL;
host_t *vip = NULL;
unique_policy_t unique; unique_policy_t unique;
u_int32_t rekey = 0, reauth = 0, over, jitter; u_int32_t rekey = 0, reauth = 0, over, jitter;
peer_cfg_t *peer_cfg; peer_cfg_t *peer_cfg;
@@ -677,14 +681,94 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{ {
rekey = msg->add_conn.rekey.ike_lifetime - over; rekey = msg->add_conn.rekey.ike_lifetime - over;
} }
if (msg->add_conn.me.sourceip_mask) switch (msg->add_conn.unique)
{ {
case 1: /* yes */
case 2: /* replace */
unique = UNIQUE_REPLACE;
break;
case 3: /* keep */
unique = UNIQUE_KEEP;
break;
default: /* no */
unique = UNIQUE_NO;
break;
}
if (msg->add_conn.dpd.action == 0)
{ /* dpdaction=none disables DPD */
msg->add_conn.dpd.delay = 0;
}
/* other.sourceip is managed in stroke_attributes. If it is set, we define
* the pool name as the connection name, which the attribute provider
* uses to serve pool addresses. */
peer_cfg = peer_cfg_create(msg->add_conn.name,
msg->add_conn.version, ike_cfg,
msg->add_conn.me.sendcert, unique,
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,
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) if (msg->add_conn.me.sourceip)
{ {
vip = host_create_from_string(msg->add_conn.me.sourceip, 0); enumerator_t *enumerator;
} char *token;
if (!vip)
{ /* if it is set to something like %poolname, request an address */ 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) if (msg->add_conn.me.subnets)
{ /* use the same family as in local subnet, if any */ { /* use the same family as in local subnet, if any */
if (strchr(msg->add_conn.me.subnets, '.')) if (strchr(msg->add_conn.me.subnets, '.'))
@@ -719,37 +803,30 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
} }
} }
} }
} else if (streq(token, "%config4"))
switch (msg->add_conn.unique)
{ {
case 1: /* yes */ vip = host_create_any(AF_INET);
case 2: /* replace */ }
unique = UNIQUE_REPLACE; else if (streq(token, "%config6"))
break; {
case 3: /* keep */ vip = host_create_any(AF_INET6);
unique = UNIQUE_KEEP; }
break; else
default: /* no */ {
unique = UNIQUE_NO; vip = host_create_from_string(token, 0);
break; if (vip)
{
DBG1(DBG_CFG, "ignored invalid subnet token: %s", token);
} }
if (msg->add_conn.dpd.action == 0)
{ /* dpdaction=none disables DPD */
msg->add_conn.dpd.delay = 0;
} }
/* other.sourceip is managed in stroke_attributes. If it is set, we define if (vip)
* the pool name as the connection name, which the attribute provider {
* uses to serve pool addresses. */ peer_cfg->add_virtual_ip(peer_cfg, vip);
peer_cfg = peer_cfg_create(msg->add_conn.name, }
msg->add_conn.version, ike_cfg, }
msg->add_conn.me.sendcert, unique, enumerator->destroy(enumerator);
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);
/* build leftauth= */ /* build leftauth= */
auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE); auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
@@ -1209,7 +1286,8 @@ METHOD(stroke_config_t, destroy, void,
/* /*
* see header file * 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; 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), .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
.ca = ca, .ca = ca,
.cred = cred, .cred = cred,
.attributes = attributes,
); );
return &this->public; return &this->public;
+3 -1
View File
@@ -26,6 +26,7 @@
#include <stroke_msg.h> #include <stroke_msg.h>
#include "stroke_ca.h" #include "stroke_ca.h"
#include "stroke_cred.h" #include "stroke_cred.h"
#include "stroke_attribute.h"
typedef struct stroke_config_t stroke_config_t; typedef struct stroke_config_t stroke_config_t;
@@ -71,6 +72,7 @@ struct stroke_config_t {
/** /**
* Create a stroke_config instance. * 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_ @}*/ #endif /** STROKE_CONFIG_H_ @}*/
+21 -14
View File
@@ -407,10 +407,10 @@ METHOD(stroke_control_t, rekey, void,
METHOD(stroke_control_t, terminate_srcip, void, METHOD(stroke_control_t, terminate_srcip, void,
private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{ {
enumerator_t *enumerator; enumerator_t *enumerator, *vips;
ike_sa_t *ike_sa; ike_sa_t *ike_sa;
host_t *start = NULL, *end = NULL, *vip; 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) if (msg->terminate_srcip.start)
{ {
@@ -438,34 +438,41 @@ METHOD(stroke_control_t, terminate_srcip, void,
charon->controller, TRUE); charon->controller, TRUE);
while (enumerator->enumerate(enumerator, &ike_sa)) while (enumerator->enumerate(enumerator, &ike_sa))
{ {
vip = ike_sa->get_virtual_ip(ike_sa, FALSE); bool match = FALSE;
if (!vip)
vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
while (vips->enumerate(vips, &vip))
{ {
continue;
}
if (!end) if (!end)
{ {
if (!vip->ip_equals(vip, start)) if (vip->ip_equals(vip, start))
{ {
continue; match = TRUE;
break;
} }
} }
else else
{ {
chunk_vip = vip->get_address(vip); chunk = vip->get_address(vip);
if (chunk_vip.len != chunk_start.len || if (chunk.len == chunk_start.len &&
chunk_vip.len != chunk_end.len || chunk.len == chunk_end.len &&
memcmp(chunk_vip.ptr, chunk_start.ptr, chunk_vip.len) < 0 || memcmp(chunk.ptr, chunk_start.ptr, chunk.len) >= 0 &&
memcmp(chunk_vip.ptr, chunk_end.ptr, chunk_vip.len) > 0) memcmp(chunk.ptr, chunk_end.ptr, chunk.len) <= 0)
{ {
continue; match = TRUE;
break;
} }
} }
}
vips->destroy(vips);
if (match)
{
/* schedule delete asynchronously */ /* schedule delete asynchronously */
lib->processor->queue_job(lib->processor, (job_t*) lib->processor->queue_job(lib->processor, (job_t*)
delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE)); delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
} }
}
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
start->destroy(start); start->destroy(start);
DESTROY_IF(end); DESTROY_IF(end);
@@ -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_cred.h"
#include "stroke_ca.h" #include "stroke_ca.h"
#include "stroke_attribute.h" #include "stroke_attribute.h"
#include "stroke_handler.h"
#include "stroke_list.h" #include "stroke_list.h"
/** /**
@@ -98,6 +99,11 @@ struct private_stroke_socket_t {
*/ */
stroke_attribute_t *attribute; stroke_attribute_t *attribute;
/**
* attribute handler (requests only)
*/
stroke_handler_t *handler;
/** /**
* controller to control daemon * 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->address);
pop_string(msg, &end->subnets); pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip); pop_string(msg, &end->sourceip);
pop_string(msg, &end->dns);
pop_string(msg, &end->auth); pop_string(msg, &end->auth);
pop_string(msg, &end->auth2); pop_string(msg, &end->auth2);
pop_string(msg, &end->id); 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, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets); DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip); 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, " %sauth=%s", label, end->auth);
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2); DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id); 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); DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
this->config->add(this->config, msg); 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); DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
this->config->del(this->config, msg); 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); lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->backends->remove_backend(charon->backends, &this->config->backend); charon->backends->remove_backend(charon->backends, &this->config->backend);
hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider); hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
this->cred->destroy(this->cred); this->cred->destroy(this->cred);
this->ca->destroy(this->ca); this->ca->destroy(this->ca);
this->config->destroy(this->config); this->config->destroy(this->config);
this->attribute->destroy(this->attribute); this->attribute->destroy(this->attribute);
this->handler->destroy(this->handler);
this->control->destroy(this->control); this->control->destroy(this->control);
this->list->destroy(this->list); this->list->destroy(this->list);
free(this); free(this);
@@ -817,8 +829,9 @@ stroke_socket_t *stroke_socket_create()
this->cred = stroke_cred_create(); this->cred = stroke_cred_create();
this->attribute = stroke_attribute_create(); this->attribute = stroke_attribute_create();
this->handler = stroke_handler_create();
this->ca = stroke_ca_create(this->cred); 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->control = stroke_control_create();
this->list = stroke_list_create(this->attribute); 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); lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->backends->add_backend(charon->backends, &this->config->backend); charon->backends->add_backend(charon->backends, &this->config->backend);
hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider); hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
lib->processor->queue_job(lib->processor, lib->processor->queue_job(lib->processor,
(job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this, (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 */ 1800, 900, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */ TRUE, FALSE, /* mobike, aggressive */
60, 0, /* DPD delay, timeout */ 60, 0, /* DPD delay, timeout */
NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */ FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create(); auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+1
View File
@@ -12,6 +12,7 @@ endif
libstrongswan_updown_la_SOURCES = \ libstrongswan_updown_la_SOURCES = \
updown_plugin.h updown_plugin.c \ updown_plugin.h updown_plugin.c \
updown_handler.h updown_handler.c \
updown_listener.h updown_listener.c updown_listener.h updown_listener.c
libstrongswan_updown_la_LDFLAGS = -module -avoid-version 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 * List of cached interface names
*/ */
linked_list_t *iface_cache; linked_list_t *iface_cache;
/**
* DNS attribute handler
*/
updown_handler_t *handler;
}; };
typedef struct cache_entry_t cache_entry_t; 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; 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, METHOD(listener_t, child_updown, bool,
private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
bool up) bool up)
@@ -97,11 +181,10 @@ METHOD(listener_t, child_updown, bool,
traffic_selector_t *my_ts, *other_ts; traffic_selector_t *my_ts, *other_ts;
enumerator_t *enumerator; enumerator_t *enumerator;
child_cfg_t *config; child_cfg_t *config;
host_t *vip, *me, *other; host_t *me, *other;
char *script; char *script;
config = child_sa->get_config(child_sa); config = child_sa->get_config(child_sa);
vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
script = config->get_updown(config); script = config->get_updown(config);
me = ike_sa->get_my_host(ike_sa); me = ike_sa->get_my_host(ike_sa);
other = ike_sa->get_other_host(ike_sa); other = ike_sa->get_other_host(ike_sa);
@@ -117,7 +200,7 @@ METHOD(listener_t, child_updown, bool,
char command[1024]; char command[1024];
host_t *my_client, *other_client; host_t *my_client, *other_client;
u_int8_t my_client_mask, other_client_mask; 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; mark_t mark;
bool is_host, is_ipv6; bool is_host, is_ipv6;
FILE *shell; FILE *shell;
@@ -125,20 +208,7 @@ METHOD(listener_t, child_updown, bool,
my_ts->to_subnet(my_ts, &my_client, &my_client_mask); my_ts->to_subnet(my_ts, &my_client, &my_client_mask);
other_ts->to_subnet(other_ts, &other_client, &other_client_mask); other_ts->to_subnet(other_ts, &other_client, &other_client_mask);
if (vip) virtual_ip = make_vip_vars(this, ike_sa);
{
if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0)
{
virtual_ip = NULL;
}
}
else
{
if (asprintf(&virtual_ip, "") < 0)
{
virtual_ip = NULL;
}
}
/* check for the presence of an inbound mark */ /* check for the presence of an inbound mark */
mark = config->get_mark(config, TRUE); 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)); iface = uncache_iface(this, child_sa->get_reqid(child_sa));
} }
dns = make_dns_vars(this, ike_sa);
/* determine IPv4/IPv6 and client/host situation */ /* determine IPv4/IPv6 and client/host situation */
is_host = my_ts->is_host(my_ts, me); is_host = my_ts->is_host(my_ts, me);
is_ipv6 = is_host ? (me->get_family(me) == AF_INET6) : 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" "%s"
"%s"
"%s", "%s",
up ? "up" : "down", up ? "up" : "down",
is_host ? "-host" : "-client", is_host ? "-host" : "-client",
@@ -259,6 +332,7 @@ METHOD(listener_t, child_updown, bool,
mark_out, mark_out,
udp_enc, udp_enc,
config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "", config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
dns,
script); script);
my_client->destroy(my_client); my_client->destroy(my_client);
other_client->destroy(other_client); other_client->destroy(other_client);
@@ -266,6 +340,7 @@ METHOD(listener_t, child_updown, bool,
free(mark_in); free(mark_in);
free(mark_out); free(mark_out);
free(udp_enc); free(udp_enc);
free(dns);
free(iface); free(iface);
DBG3(DBG_CHD, "running updown script: %s", command); DBG3(DBG_CHD, "running updown script: %s", command);
@@ -315,7 +390,7 @@ METHOD(updown_listener_t, destroy, void,
/** /**
* See header * See header
*/ */
updown_listener_t *updown_listener_create() updown_listener_t *updown_listener_create(updown_handler_t *handler)
{ {
private_updown_listener_t *this; private_updown_listener_t *this;
@@ -327,6 +402,7 @@ updown_listener_t *updown_listener_create()
.destroy = _destroy, .destroy = _destroy,
}, },
.iface_cache = linked_list_create(), .iface_cache = linked_list_create(),
.handler = handler,
); );
return &this->public; return &this->public;
@@ -23,6 +23,8 @@
#include <bus/bus.h> #include <bus/bus.h>
#include "updown_handler.h"
typedef struct updown_listener_t updown_listener_t; typedef struct updown_listener_t updown_listener_t;
/** /**
@@ -44,6 +46,6 @@ struct updown_listener_t {
/** /**
* Create a updown_listener instance. * 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_ @}*/ #endif /** UPDOWN_LISTENER_H_ @}*/
+21 -1
View File
@@ -15,8 +15,10 @@
#include "updown_plugin.h" #include "updown_plugin.h"
#include "updown_listener.h" #include "updown_listener.h"
#include "updown_handler.h"
#include <daemon.h> #include <daemon.h>
#include <hydra.h>
typedef struct private_updown_plugin_t private_updown_plugin_t; 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 * Listener interface, listens to CHILD_SA state changes
*/ */
updown_listener_t *listener; updown_listener_t *listener;
/**
* Attribute handler, to pass DNS servers to updown
*/
updown_handler_t *handler;
}; };
METHOD(plugin_t, get_name, char*, METHOD(plugin_t, get_name, char*,
@@ -47,6 +54,12 @@ METHOD(plugin_t, destroy, void,
{ {
charon->bus->remove_listener(charon->bus, &this->listener->listener); charon->bus->remove_listener(charon->bus, &this->listener->listener);
this->listener->destroy(this->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); free(this);
} }
@@ -65,9 +78,16 @@ plugin_t *updown_plugin_create()
.destroy = _destroy, .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); charon->bus->add_listener(charon->bus, &this->listener->listener);
return &this->public.plugin; return &this->public.plugin;
+12 -3
View File
@@ -79,9 +79,10 @@ METHOD(job_t, execute, job_requeue_t,
} }
if (ike_sa) if (ike_sa)
{ {
enumerator_t *children; enumerator_t *children, *enumerator;
child_sa_t *child_sa; child_sa_t *child_sa;
host_t *host; host_t *host;
linked_list_t *vips;
children = ike_sa->create_child_sa_enumerator(ike_sa); children = ike_sa->create_child_sa_enumerator(ike_sa);
while (children->enumerate(children, (void**)&child_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); host->set_port(host, IKEV2_UDP_PORT);
ike_sa->set_other_host(ike_sa, host); ike_sa->set_other_host(ike_sa, host);
if (child_sa->update(child_sa, this->local, this->remote, vips = linked_list_create();
ike_sa->get_virtual_ip(ike_sa, TRUE), 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->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
{ {
ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
child_sa->get_spi(child_sa, TRUE)); child_sa->get_spi(child_sa, TRUE));
} }
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
vips->destroy(vips);
} }
else else
{ {
+11 -8
View File
@@ -819,8 +819,17 @@ METHOD(child_sa_t, add_policies, status_t,
return status; 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, METHOD(child_sa_t, update, status_t,
private_child_sa_t *this, host_t *me, host_t *other, host_t *vip, private_child_sa_t *this, host_t *me, host_t *other, linked_list_t *vips,
bool encap) bool encap)
{ {
child_sa_state_t old; child_sa_state_t old;
@@ -927,13 +936,7 @@ METHOD(child_sa_t, update, status_t,
/* we reinstall the virtual IP to handle interface roaming /* we reinstall the virtual IP to handle interface roaming
* correctly */ * correctly */
if (vip) vips->invoke_function(vips, (void*)reinstall_vip, me);
{
hydra->kernel_interface->del_ip(hydra->kernel_interface,
vip);
hydra->kernel_interface->add_ip(hydra->kernel_interface,
vip, me);
}
/* reinstall updated policies */ /* reinstall updated policies */
install_policies_internal(this, me, other, my_ts, other_ts, 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 me the new local host
* @param other the new remote 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 * @param TRUE to use UDP encapsulation for NAT traversal
* @return SUCCESS or FAILED * @return SUCCESS or FAILED
*/ */
status_t (*update)(child_sa_t *this, host_t *me, host_t *other, 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. * Destroys a child_sa.
*/ */
+52 -48
View File
@@ -182,14 +182,14 @@ struct private_ike_sa_t {
keymat_t *keymat; 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) * List of configuration attributes (attribute_entry_t)
@@ -735,7 +735,7 @@ METHOD(ike_sa_t, get_keymat, keymat_t*,
return this->keymat; 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) private_ike_sa_t *this, bool local, host_t *ip)
{ {
if (local) if (local)
@@ -744,39 +744,27 @@ METHOD(ike_sa_t, set_virtual_ip, void,
if (hydra->kernel_interface->add_ip(hydra->kernel_interface, ip, if (hydra->kernel_interface->add_ip(hydra->kernel_interface, ip,
this->my_host) == SUCCESS) this->my_host) == SUCCESS)
{ {
if (this->my_virtual_ip) this->my_vips->insert_last(this->my_vips, ip->clone(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);
} }
else else
{ {
DBG1(DBG_IKE, "installing virtual IP %H failed", ip); DBG1(DBG_IKE, "installing virtual IP %H failed", ip);
this->my_virtual_ip = NULL;
} }
} }
else else
{ {
DESTROY_IF(this->other_virtual_ip); this->other_vips->insert_last(this->other_vips, ip->clone(ip));
this->other_virtual_ip = 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) private_ike_sa_t *this, bool local)
{ {
if (local) if (local)
{ {
return this->my_virtual_ip; return this->my_vips->create_enumerator(this->my_vips);
}
else
{
return this->other_virtual_ip;
} }
return this->other_vips->create_enumerator(this->other_vips);
} }
METHOD(ike_sa_t, add_peer_address, void, 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)) while (enumerator->enumerate(enumerator, (void**)&child_sa))
{ {
if (child_sa->update(child_sa, this->my_host, 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) has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
{ {
this->public.rekey_child_sa(&this->public, 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)) if (!has_condition(this, COND_ORIGINAL_INITIATOR))
{ {
DBG1(DBG_IKE, "initiator did not reauthenticate as requested"); 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_XAUTH_AUTHENTICATED) ||
has_condition(this, COND_EAP_AUTHENTICATED) has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME #ifdef ME
@@ -1562,7 +1550,7 @@ METHOD(ike_sa_t, reestablish, status_t,
/* check if we are able to reestablish this IKE_SA */ /* check if we are able to reestablish this IKE_SA */
if (!has_condition(this, COND_ORIGINAL_INITIATOR) && 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) has_condition(this, COND_EAP_AUTHENTICATED)
#ifdef ME #ifdef ME
|| this->is_mediation_server || this->is_mediation_server
@@ -1585,11 +1573,12 @@ METHOD(ike_sa_t, reestablish, status_t,
host = this->my_host; host = this->my_host;
new->set_my_host(new, host->clone(host)); new->set_my_host(new, host->clone(host));
/* if we already have a virtual IP, we reuse it */ /* if we already have a virtual IP, we reuse it */
host = this->my_virtual_ip; enumerator = this->my_vips->create_enumerator(this->my_vips);
if (host) while (enumerator->enumerate(enumerator, &host))
{ {
new->set_virtual_ip(new, TRUE, host); new->add_virtual_ip(new, TRUE, host);
} }
enumerator->destroy(enumerator);
#ifdef ME #ifdef ME
if (this->peer_cfg->is_mediation(this->peer_cfg)) 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. */ * We send the notify in IKE_AUTH if not yet ESTABLISHED. */
send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 && send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 &&
!has_condition(this, COND_ORIGINAL_INITIATOR) && !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)); has_condition(this, COND_EAP_AUTHENTICATED));
if (lifetime < diff) if (lifetime < diff)
@@ -1937,6 +1926,7 @@ METHOD(ike_sa_t, inherit, void,
attribute_entry_t *entry; attribute_entry_t *entry;
enumerator_t *enumerator; enumerator_t *enumerator;
auth_cfg_t *cfg; auth_cfg_t *cfg;
host_t *vip;
/* apply hosts and ids */ /* apply hosts and ids */
this->my_host->destroy(this->my_host); 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->my_id = other->my_id->clone(other->my_id);
this->other_id = other->other_id->clone(other->other_id); this->other_id = other->other_id->clone(other->other_id);
/* apply virtual assigned IPs... */ /* apply assigned virtual IPs... */
if (other->my_virtual_ip) while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS)
{ {
this->my_virtual_ip = other->my_virtual_ip; other->my_vips->insert_first(other->my_vips, vip);
other->my_virtual_ip = NULL;
} }
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_vips->insert_first(other->other_vips, vip);
other->other_virtual_ip = NULL;
} }
/* authentication information */ /* authentication information */
@@ -2032,6 +2021,7 @@ METHOD(ike_sa_t, destroy, void,
private_ike_sa_t *this) private_ike_sa_t *this)
{ {
attribute_entry_t *entry; attribute_entry_t *entry;
host_t *vip;
charon->bus->set_sa(charon->bus, &this->public); charon->bus->set_sa(charon->bus, &this->public);
@@ -2056,22 +2046,34 @@ METHOD(ike_sa_t, destroy, void,
DESTROY_IF(this->keymat); 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, hydra->kernel_interface->del_ip(hydra->kernel_interface, vip);
this->my_virtual_ip); vip->destroy(vip);
this->my_virtual_ip->destroy(this->my_virtual_ip);
} }
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, enumerator_t *enumerator;
this->peer_cfg->get_pool(this->peer_cfg), char *pool;
this->other_virtual_ip, get_other_eap_id(this));
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;
} }
this->other_virtual_ip->destroy(this->other_virtual_ip);
} }
enumerator->destroy(enumerator);
}
vip->destroy(vip);
}
this->other_vips->destroy(this->other_vips);
this->peer_addresses->destroy_offset(this->peer_addresses, this->peer_addresses->destroy_offset(this->peer_addresses,
offsetof(host_t, destroy)); offsetof(host_t, destroy));
#ifdef ME #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, .generate_message = _generate_message,
.reset = _reset, .reset = _reset,
.get_unique_id = _get_unique_id, .get_unique_id = _get_unique_id,
.set_virtual_ip = _set_virtual_ip, .add_virtual_ip = _add_virtual_ip,
.get_virtual_ip = _get_virtual_ip, .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
.add_configuration_attribute = _add_configuration_attribute, .add_configuration_attribute = _add_configuration_attribute,
.set_kmaddress = _set_kmaddress, .set_kmaddress = _set_kmaddress,
.create_task_enumerator = _create_task_enumerator, .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(), .other_auths = linked_list_create(),
.unique_id = ++unique_id, .unique_id = ++unique_id,
.peer_addresses = linked_list_create(), .peer_addresses = linked_list_create(),
.my_vips = linked_list_create(),
.other_vips = linked_list_create(),
.attributes = linked_list_create(), .attributes = linked_list_create(),
.keepalive_interval = lib->settings->get_time(lib->settings, .keepalive_interval = lib->settings->get_time(lib->settings,
"%s.keep_alive", KEEPALIVE_INTERVAL, charon->name), "%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); 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 * The virtual IP is assigned per IKE_SA, not per CHILD_SA. It has the same
* lifetime as the IKE_SA. * lifetime as the IKE_SA.
@@ -939,15 +939,15 @@ struct ike_sa_t {
* @param local TRUE to set local address, FALSE for remote * @param local TRUE to set local address, FALSE for remote
* @param ip IP to set as virtual IP * @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 * @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. * Register a configuration attribute to the IKE_SA.
+30
View File
@@ -609,6 +609,34 @@ METHOD(phase1_t, get_id, identification_t*,
return id; 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, METHOD(phase1_t, save_sa_payload, bool,
private_phase1_t *this, message_t *message) 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_auth_method = _get_auth_method,
.get_id = _get_id, .get_id = _get_id,
.select_config = _select_config, .select_config = _select_config,
.has_virtual_ip = _has_virtual_ip,
.has_pool = _has_pool,
.verify_auth = _verify_auth, .verify_auth = _verify_auth,
.build_auth = _build_auth, .build_auth = _build_auth,
.save_sa_payload = _save_sa_payload, .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); 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. * 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) static bool mode_config_expected(private_task_manager_t *this)
{ {
enumerator_t *enumerator;
peer_cfg_t *peer_cfg; peer_cfg_t *peer_cfg;
char *pool;
host_t *host;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); 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; return TRUE;
} }
enumerator->destroy(enumerator);
} }
return FALSE; return FALSE;
} }
@@ -1309,11 +1324,12 @@ METHOD(task_manager_t, queue_ike_reauth, void,
new->set_other_host(new, host->clone(host)); new->set_other_host(new, host->clone(host));
host = this->ike_sa->get_my_host(this->ike_sa); host = this->ike_sa->get_my_host(this->ike_sa);
new->set_my_host(new, host->clone(host)); new->set_my_host(new, host->clone(host));
host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
if (host) 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); enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, &child_sa)) while (enumerator->enumerate(enumerator, &child_sa))
@@ -320,7 +320,7 @@ METHOD(task_t, build_i, status_t,
} }
break; 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, this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE)); (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))); this->ike_sa->get_id(this->ike_sa)));
break; break;
} }
if (this->peer_cfg->get_pool(this->peer_cfg) == NULL && if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
this->peer_cfg->get_virtual_ip(this->peer_cfg)) this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{ {
this->ike_sa->queue_task(this->ike_sa, this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE)); (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))); this->ike_sa->get_id(this->ike_sa)));
break; break;
} }
if (this->peer_cfg->get_pool(this->peer_cfg) == NULL && if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
this->peer_cfg->get_virtual_ip(this->peer_cfg)) this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{ {
this->ike_sa->queue_task(this->ike_sa, this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE)); (task_t*)mode_config_create(this->ike_sa, TRUE));
@@ -658,7 +658,7 @@ METHOD(task_t, process_i, status_t,
} }
break; 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, this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE)); (task_t*)mode_config_create(this->ike_sa, TRUE));
+94 -35
View File
@@ -42,9 +42,9 @@ struct private_mode_config_t {
bool initiator; 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 * list of attributes requested and its handler, entry_t
@@ -174,8 +174,7 @@ static void process_attribute(private_mode_config_t *this,
} }
if (ip) if (ip)
{ {
DESTROY_IF(this->virtual_ip); this->vips->insert_last(this->vips, ip);
this->virtual_ip = ip;
} }
break; break;
} }
@@ -239,23 +238,44 @@ METHOD(task_t, build_i, status_t,
peer_cfg_t *config; peer_cfg_t *config;
configuration_attribute_type_t type; configuration_attribute_type_t type;
chunk_t data; 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 */ /* reuse virtual IP if we already have one */
vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
if (!vip) 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); config = this->ike_sa->get_peer_cfg(this->ike_sa);
vip = config->get_virtual_ip(config); enumerator = config->create_virtual_ip_enumerator(config);
} while (enumerator->enumerate(enumerator, &host))
if (vip)
{ {
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST); vips->insert_last(vips, host);
cp->add_attribute(cp, build_vip(vip)); }
enumerator->destroy(enumerator);
} }
enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes, if (vips->get_count(vips))
this->ike_sa->get_other_id(this->ike_sa), vip); {
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)) while (enumerator->enumerate(enumerator, &handler, &type, &data))
{ {
configuration_attribute_t *ca; configuration_attribute_t *ca;
@@ -279,6 +299,8 @@ METHOD(task_t, build_i, status_t,
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
vips->destroy(vips);
if (cp) if (cp)
{ {
message->add_payload(message, (payload_t*)cp); message->add_payload(message, (payload_t*)cp);
@@ -299,37 +321,64 @@ METHOD(task_t, build_r, status_t,
enumerator_t *enumerator; enumerator_t *enumerator;
configuration_attribute_type_t type; configuration_attribute_type_t type;
chunk_t value; chunk_t value;
host_t *vip = NULL;
cp_payload_t *cp = NULL; cp_payload_t *cp = NULL;
peer_cfg_t *config; peer_cfg_t *config;
identification_t *id; identification_t *id;
linked_list_t *vips, *pools;
host_t *requested;
id = this->ike_sa->get_other_eap_id(this->ike_sa); id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(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); enumerator_t *poolenum;
if (config->get_pool(config)) 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, found = hydra->attributes->acquire_address(hydra->attributes,
config->get_pool(config), id, this->virtual_ip); 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 = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
if (vip) }
cp->add_attribute(cp, build_vip(found));
/* use pool to request other attributes */
if (pools->find_first(pools, NULL, (void**)&pool) == NOT_FOUND)
{ {
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id); pools->insert_last(pools, pool);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp->add_attribute(cp, build_vip(vip));
} }
else vips->insert_last(vips, found);
break;
}
poolenum->destroy(poolenum);
if (!found)
{ {
DBG1(DBG_IKE, "no virtual IP found, sending empty config payload"); DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
requested, id);
} }
} }
enumerator->destroy(enumerator);
/* query registered providers for additional attributes to include */ /* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator( 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)) while (enumerator->enumerate(enumerator, &type, &value))
{ {
if (!cp) if (!cp)
@@ -343,25 +392,35 @@ METHOD(task_t, build_r, status_t,
type, value)); type, value));
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
vips->destroy_offset(vips, offsetof(host_t, destroy));
vips->destroy(vips);
if (cp) if (cp)
{ {
cp->set_identifier(cp, this->identifier); cp->set_identifier(cp, this->identifier);
message->add_payload(message, (payload_t*)cp); message->add_payload(message, (payload_t*)cp);
} }
DESTROY_IF(vip);
return SUCCESS; return SUCCESS;
} }
METHOD(task_t, process_i, status_t, METHOD(task_t, process_i, status_t,
private_mode_config_t *this, message_t *message) private_mode_config_t *this, message_t *message)
{ {
enumerator_t *enumerator;
host_t *host;
process_payloads(this, message); 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; return SUCCESS;
} }
@@ -374,10 +433,9 @@ METHOD(task_t, get_type, task_type_t,
METHOD(task_t, migrate, void, METHOD(task_t, migrate, void,
private_mode_config_t *this, ike_sa_t *ike_sa) private_mode_config_t *this, ike_sa_t *ike_sa)
{ {
DESTROY_IF(this->virtual_ip);
this->ike_sa = ike_sa; 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->destroy_function(this->requested, free);
this->requested = linked_list_create(); this->requested = linked_list_create();
} }
@@ -385,7 +443,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void, METHOD(task_t, destroy, void,
private_mode_config_t *this) 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); this->requested->destroy_function(this->requested, free);
free(this); free(this);
} }
@@ -408,6 +466,7 @@ mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
.initiator = initiator, .initiator = initiator,
.ike_sa = ike_sa, .ike_sa = ike_sa,
.requested = linked_list_create(), .requested = linked_list_create(),
.vips = linked_list_create(),
); );
if (initiator) 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) linked_list_t *supplied)
{ {
traffic_selector_t *ts; traffic_selector_t *ts;
enumerator_t *enumerator;
linked_list_t *list; linked_list_t *list;
host_t *host; host_t *host;
host = this->ike_sa->get_virtual_ip(this->ike_sa, local); enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, local);
if (!host) if (!enumerator->enumerate(enumerator, &host))
{ {
if (local) 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); host = this->ike_sa->get_other_host(this->ike_sa);
} }
} }
enumerator->destroy(enumerator);
list = this->config->get_traffic_selectors(this->config, local, list = this->config->get_traffic_selectors(this->config, local,
supplied, host); supplied, host);
if (list->get_first(list, (void**)&ts) == SUCCESS) 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); 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, METHOD(task_t, process_r, status_t,
private_quick_mode_t *this, message_t *message) private_quick_mode_t *this, message_t *message)
{ {
@@ -841,7 +867,6 @@ METHOD(task_t, process_r, status_t,
sa_payload_t *sa_payload; sa_payload_t *sa_payload;
linked_list_t *tsi, *tsr, *list = NULL; linked_list_t *tsi, *tsr, *list = NULL;
peer_cfg_t *peer_cfg; peer_cfg_t *peer_cfg;
host_t *me, *other;
u_int16_t group; u_int16_t group;
bool private; bool private;
@@ -849,16 +874,6 @@ METHOD(task_t, process_r, status_t,
{ {
return FAILED; 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); peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
tsi = linked_list_create(); tsi = linked_list_create();
tsr = linked_list_create(); tsr = linked_list_create();
@@ -866,7 +881,8 @@ METHOD(task_t, process_r, status_t,
tsr->insert_last(tsr, this->tsr); tsr->insert_last(tsr, this->tsr);
this->tsi = this->tsr = NULL; this->tsi = this->tsr = NULL;
this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi, 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) if (this->config)
{ {
this->tsi = select_ts(this, FALSE, tsi); 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: * Install a CHILD_SA for usage, return value:
* - FAILED: no acceptable proposal * - 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 encr_i = chunk_empty, encr_r = chunk_empty;
chunk_t integ_i = chunk_empty, integ_r = chunk_empty; chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
linked_list_t *my_ts, *other_ts; linked_list_t *my_ts, *other_ts;
host_t *me, *other, *other_vip, *my_vip; host_t *me, *other;
bool private; bool private;
if (this->proposals == NULL) 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); me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_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); private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
this->proposal = this->config->select_proposal(this->config, 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; this->dh_group = MODP_NONE;
} }
if (my_vip == NULL)
{
my_vip = me;
}
if (other_vip == NULL)
{
other_vip = other;
}
if (this->initiator) if (this->initiator)
{ {
nonce_i = this->my_nonce; nonce_i = this->my_nonce;
@@ -378,9 +391,9 @@ static status_t select_and_install(private_child_create_t *this,
other_ts = this->tsi; other_ts = this->tsi;
} }
my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts, 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_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
other_vip); get_dynamic_host(this->ike_sa, FALSE));
if (this->initiator) 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, METHOD(task_t, build_i, status_t,
private_child_create_t *this, message_t *message) private_child_create_t *this, message_t *message)
{ {
host_t *me, *other, *vip; enumerator_t *enumerator;
host_t *vip;
peer_cfg_t *peer_cfg; peer_cfg_t *peer_cfg;
switch (message->get_exchange_type(message)) switch (message->get_exchange_type(message))
@@ -763,22 +777,10 @@ METHOD(task_t, build_i, status_t,
this->config->get_name(this->config)); 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 */ /* check if we want a virtual IP, but don't have one */
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
vip = peer_cfg->get_virtual_ip(peer_cfg); enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
if (!this->reqid && vip) if (!this->reqid && enumerator->enumerate(enumerator, &vip))
{ {
/* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */ /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
vip = host_create_any(vip->get_family(vip)); vip = host_create_any(vip->get_family(vip));
@@ -788,11 +790,12 @@ METHOD(task_t, build_i, status_t,
} }
else else
{ /* but narrow it for host2host / if we already have a vip */ { /* but narrow it for host2host / if we already have a vip */
this->tsi = this->config->get_traffic_selectors(this->config, TRUE, this->tsi = this->config->get_traffic_selectors(this->config, TRUE, NULL,
NULL, me); get_dynamic_host(this->ike_sa, TRUE));
} }
this->tsr = this->config->get_traffic_selectors(this->config, FALSE, enumerator->destroy(enumerator);
NULL, other); this->tsr = this->config->get_traffic_selectors(this->config, FALSE, NULL,
get_dynamic_host(this->ike_sa, FALSE));
if (this->packet_tsi) 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); peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (!this->config && peer_cfg && this->tsi && this->tsr) if (!this->config && peer_cfg && this->tsi && this->tsr)
{ {
host_t *me, *other; this->config = peer_cfg->select_child_cfg(peer_cfg,
this->tsr, this->tsi,
me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); get_dynamic_host(this->ike_sa, TRUE),
if (me == NULL) get_dynamic_host(this->ike_sa, FALSE));
{
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);
} }
if (this->config == NULL) if (this->config == NULL)
+102 -37
View File
@@ -43,9 +43,9 @@ struct private_ike_config_t {
bool initiator; 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 * list of attributes requested and its handler, entry_t
@@ -170,8 +170,7 @@ static void process_attribute(private_ike_config_t *this,
} }
if (ip) if (ip)
{ {
DESTROY_IF(this->virtual_ip); this->vips->insert_last(this->vips, ip);
this->virtual_ip = ip;
} }
break; break;
} }
@@ -242,23 +241,45 @@ METHOD(task_t, build_i, status_t,
peer_cfg_t *config; peer_cfg_t *config;
configuration_attribute_type_t type; configuration_attribute_type_t type;
chunk_t data; 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 */ /* reuse virtual IP if we already have one */
vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
if (!vip) 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); config = this->ike_sa->get_peer_cfg(this->ike_sa);
vip = config->get_virtual_ip(config); enumerator = config->create_virtual_ip_enumerator(config);
} while (enumerator->enumerate(enumerator, &host))
if (vip)
{ {
cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST); vips->insert_last(vips, host);
cp->add_attribute(cp, build_vip(vip)); }
enumerator->destroy(enumerator);
} }
enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes, if (vips->get_count(vips))
this->ike_sa->get_other_id(this->ike_sa), vip); {
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)) while (enumerator->enumerate(enumerator, &handler, &type, &data))
{ {
configuration_attribute_t *ca; configuration_attribute_t *ca;
@@ -284,6 +305,8 @@ METHOD(task_t, build_i, status_t,
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
vips->destroy(vips);
if (cp) if (cp)
{ {
message->add_payload(message, (payload_t*)cp); message->add_payload(message, (payload_t*)cp);
@@ -310,40 +333,75 @@ METHOD(task_t, build_r, status_t,
enumerator_t *enumerator; enumerator_t *enumerator;
configuration_attribute_type_t type; configuration_attribute_type_t type;
chunk_t value; chunk_t value;
host_t *vip = NULL;
cp_payload_t *cp = NULL; cp_payload_t *cp = NULL;
peer_cfg_t *config; peer_cfg_t *config;
identification_t *id; identification_t *id;
linked_list_t *vips, *pools;
host_t *requested;
id = this->ike_sa->get_other_eap_id(this->ike_sa); id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(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); enumerator_t *poolenum;
if (config->get_pool(config)) 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, found = hydra->attributes->acquire_address(hydra->attributes,
config->get_pool(config), id, this->virtual_ip); pool, id, requested);
if (!found)
{
continue;
} }
if (vip == NULL) 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", DBG1(DBG_IKE, "no virtual IP found, sending %N",
notify_type_names, INTERNAL_ADDRESS_FAILURE); notify_type_names, INTERNAL_ADDRESS_FAILURE);
message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE, message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
chunk_empty); chunk_empty);
vips->destroy_offset(vips, offsetof(host_t, destroy));
pools->destroy(pools);
return SUCCESS; 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);
cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
cp->add_attribute(cp, build_vip(vip));
}
/* query registered providers for additional attributes to include */ /* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator( 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)) while (enumerator->enumerate(enumerator, &type, &value))
{ {
if (!cp) if (!cp)
@@ -357,12 +415,13 @@ METHOD(task_t, build_r, status_t,
type, value)); type, value));
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
vips->destroy_offset(vips, offsetof(host_t, destroy));
pools->destroy(pools);
if (cp) if (cp)
{ {
message->add_payload(message, (payload_t*)cp); message->add_payload(message, (payload_t*)cp);
} }
DESTROY_IF(vip);
return SUCCESS; return SUCCESS;
} }
return NEED_MORE; 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) if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */ { /* in last IKE_AUTH exchange */
enumerator_t *enumerator;
host_t *host;
process_payloads(this, message); process_payloads(this, message);
if (this->virtual_ip && enumerator = this->vips->create_enumerator(this->vips);
!this->virtual_ip->is_anyaddr(this->virtual_ip)) 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 SUCCESS;
} }
return NEED_MORE; return NEED_MORE;
@@ -395,10 +460,9 @@ METHOD(task_t, get_type, task_type_t,
METHOD(task_t, migrate, void, METHOD(task_t, migrate, void,
private_ike_config_t *this, ike_sa_t *ike_sa) private_ike_config_t *this, ike_sa_t *ike_sa)
{ {
DESTROY_IF(this->virtual_ip);
this->ike_sa = ike_sa; 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->destroy_function(this->requested, free);
this->requested = linked_list_create(); this->requested = linked_list_create();
} }
@@ -406,7 +470,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void, METHOD(task_t, destroy, void,
private_ike_config_t *this) 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); this->requested->destroy_function(this->requested, free);
free(this); free(this);
} }
@@ -428,6 +492,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
}, },
.initiator = initiator, .initiator = initiator,
.ike_sa = ike_sa, .ike_sa = ike_sa,
.vips = linked_list_create(),
.requested = 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; enumerator_t *enumerator;
child_sa_t *child_sa; 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); enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, (void**)&child_sa)) while (enumerator->enumerate(enumerator, (void**)&child_sa))
{ {
if (child_sa->update(child_sa, if (child_sa->update(child_sa,
this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_my_host(this->ike_sa),
this->ike_sa->get_other_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), vips,
this->ike_sa->get_virtual_ip(this->ike_sa, TRUE), this->ike_sa->has_condition(this->ike_sa,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED) COND_NAT_ANY)) == NOT_SUPPORTED)
{ {
this->ike_sa->rekey_child_sa(this->ike_sa, this->ike_sa->rekey_child_sa(this->ike_sa,
child_sa->get_protocol(child_sa), child_sa->get_protocol(child_sa),
@@ -266,6 +277,8 @@ static void update_children(private_ike_mobike_t *this)
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
vips->destroy(vips);
} }
/** /**
+3 -3
View File
@@ -22,8 +22,8 @@
#define ATTRIBUTE_HANDLER_H_ #define ATTRIBUTE_HANDLER_H_
#include <chunk.h> #include <chunk.h>
#include <utils/host.h>
#include <utils/identification.h> #include <utils/identification.h>
#include <utils/linked_list.h>
#include "attributes.h" #include "attributes.h"
@@ -62,11 +62,11 @@ struct attribute_handler_t {
* Enumerate attributes to request from a server. * Enumerate attributes to request from a server.
* *
* @param server server identity to request attributes from * @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) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this, 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_ @}*/ #endif /** ATTRIBUTE_HANDLER_H_ @}*/
+31 -34
View File
@@ -51,12 +51,12 @@ struct private_attribute_manager_t {
* Data to pass to enumerator filters * Data to pass to enumerator filters
*/ */
typedef struct { typedef struct {
/** attribute group pool */ /** attribute group pools */
char *pool; linked_list_t *pools;
/** server/peer identity */ /** server/peer identity */
identification_t *id; identification_t *id;
/** requesting/assigned virtual IP */ /** requesting/assigned virtual IPs */
host_t *vip; linked_list_t *vips;
} enum_data_t; } enum_data_t;
METHOD(attribute_manager_t, acquire_address, host_t*, METHOD(attribute_manager_t, acquire_address, host_t*,
@@ -80,14 +80,10 @@ METHOD(attribute_manager_t, acquire_address, host_t*,
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock); this->lock->unlock(this->lock);
if (!host)
{
DBG1(DBG_CFG, "acquiring address from pool '%s' failed", pool);
}
return host; 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, private_attribute_manager_t *this, char *pool, host_t *address,
identification_t *id) identification_t *id)
{ {
@@ -108,10 +104,7 @@ METHOD(attribute_manager_t, release_address, void,
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock); this->lock->unlock(this->lock);
if (!found) return found;
{
DBG1(DBG_CFG, "releasing address to pool '%s' failed", pool);
}
} }
/** /**
@@ -120,19 +113,21 @@ METHOD(attribute_manager_t, release_address, void,
static enumerator_t *responder_enum_create(attribute_provider_t *provider, static enumerator_t *responder_enum_create(attribute_provider_t *provider,
enum_data_t *data) enum_data_t *data)
{ {
return provider->create_attribute_enumerator(provider, data->pool, return provider->create_attribute_enumerator(provider, data->pools,
data->id, data->vip); data->id, data->vips);
} }
METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*, METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
private_attribute_manager_t *this, char *pool, identification_t *id, private_attribute_manager_t *this, linked_list_t *pools,
host_t *vip) identification_t *id, linked_list_t *vips)
{ {
enum_data_t *data = malloc_thing(enum_data_t); enum_data_t *data;
data->pool = pool; INIT(data,
data->id = id; .pools = pools,
data->vip = vip; .id = id,
.vips = vips,
);
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
return enumerator_create_cleaner( return enumerator_create_cleaner(
enumerator_create_nested( enumerator_create_nested(
@@ -238,8 +233,8 @@ typedef struct {
enumerator_t *inner; enumerator_t *inner;
/** server ID we want attributes for */ /** server ID we want attributes for */
identification_t *id; identification_t *id;
/** virtual IP we are requesting along with attriubutes */ /** virtual IPs we are requesting along with attriubutes */
host_t *vip; linked_list_t *vips;
} initiator_enumerator_t; } initiator_enumerator_t;
/** /**
@@ -259,7 +254,7 @@ static bool initiator_enumerate(initiator_enumerator_t *this,
} }
DESTROY_IF(this->inner); DESTROY_IF(this->inner);
this->inner = this->handler->create_attribute_enumerator(this->handler, this->inner = this->handler->create_attribute_enumerator(this->handler,
this->id, this->vip); this->id, this->vips);
} }
/* inject the handler as additional attribute */ /* inject the handler as additional attribute */
*handler = this->handler; *handler = this->handler;
@@ -278,20 +273,22 @@ static void initiator_destroy(initiator_enumerator_t *this)
} }
METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*, 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); 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; 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 pool pool name from which the address was acquired
* @param address address to release * @param address address to release
* @param id peer identity to get address for * @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); char *pool, host_t *address, identification_t *id);
/** /**
* Create an enumerator over attributes to hand out to a peer. * 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 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) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this, 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. * Register an attribute provider to the manager.
@@ -114,11 +116,11 @@ struct attribute_manager_t {
* Create an enumerator over attributes to request from server. * Create an enumerator over attributes to request from server.
* *
* @param id server identity to hand out attributes to * @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) * @return enumerator (attribute_handler_t, ca_type_t, chunk_t)
*/ */
enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this, 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. * Register an attribute handler to the manager.
+5 -3
View File
@@ -23,6 +23,7 @@
#include <utils/host.h> #include <utils/host.h>
#include <utils/identification.h> #include <utils/identification.h>
#include <utils/linked_list.h>
typedef struct attribute_provider_t attribute_provider_t; 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. * 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 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) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this, 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_ @}*/ #endif /** ATTRIBUTE_PROVIDER_H_ @}*/
+8 -3
View File
@@ -162,6 +162,12 @@ METHOD(mem_pool_t, get_name, const char*,
return this->name; 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, METHOD(mem_pool_t, get_size, u_int,
private_mem_pool_t *this) private_mem_pool_t *this)
{ {
@@ -220,11 +226,9 @@ METHOD(mem_pool_t, acquire_address, host_t*,
return requested->clone(requested); return requested->clone(requested);
} }
if (!requested->is_anyaddr(requested) && if (requested->get_family(requested) !=
requested->get_family(requested) !=
this->base->get_family(this->base)) this->base->get_family(this->base))
{ {
DBG1(DBG_CFG, "IP pool address family mismatch");
return NULL; return NULL;
} }
@@ -463,6 +467,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
INIT(this, INIT(this,
.public = { .public = {
.get_name = _get_name, .get_name = _get_name,
.get_base = _get_base,
.get_size = _get_size, .get_size = _get_size,
.get_online = _get_online, .get_online = _get_online,
.get_offline = _get_offline, .get_offline = _get_offline,
+7
View File
@@ -38,6 +38,13 @@ struct mem_pool_t {
*/ */
const char* (*get_name)(mem_pool_t *this); 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. * 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*, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
private_attr_provider_t *this, char *pool, private_attr_provider_t *this, linked_list_t *pools,
identification_t *id, host_t *vip) identification_t *id, linked_list_t *vips)
{ {
if (vip) if (vips->get_count(vips))
{ {
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
return enumerator_create_filter( return enumerator_create_filter(
+16 -67
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*, 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 *requested)
{ {
host_t *address = NULL; host_t *address = NULL;
@@ -242,60 +242,18 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
identity = get_identity(this, id); identity = get_identity(this, id);
if (identity) if (identity)
{ {
/* check for a single pool first (no concatenation and enumeration) */ pool = get_pool(this, name, &timeout);
if (strchr(names, ',') == NULL)
{
pool = get_pool(this, names, &timeout);
if (pool) if (pool)
{ {
/* check for an existing lease */ /* check for an existing lease */
address = check_lease(this, names, pool, identity); address = check_lease(this, name, pool, identity);
if (address == NULL) if (address == NULL)
{ {
/* get an unallocated address or expired lease */ /* get an unallocated address or expired lease */
address = get_lease(this, names, 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); address = get_lease(this, name, pool, timeout, identity);
if (address)
{
break;
} }
} }
} }
enumerator->destroy(enumerator);
}
}
return address; return address;
} }
@@ -303,14 +261,8 @@ METHOD(attribute_provider_t, release_address, bool,
private_sql_attribute_t *this, char *name, host_t *address, private_sql_attribute_t *this, char *name, host_t *address,
identification_t *id) identification_t *id)
{ {
enumerator_t *enumerator;
bool found = FALSE;
time_t now = time(NULL);
enumerator = enumerator_create_token(name, ",", " ");
while (enumerator->enumerate(enumerator, &name))
{
u_int pool, timeout; u_int pool, timeout;
time_t now = time(NULL);
pool = get_pool(this, name, &timeout); pool = get_pool(this, name, &timeout);
if (pool) if (pool)
@@ -329,24 +281,21 @@ METHOD(attribute_provider_t, release_address, bool,
"pool = ? AND address = ?", DB_UINT, time(NULL), "pool = ? AND address = ?", DB_UINT, time(NULL),
DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0) DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0)
{ {
found = TRUE; return TRUE;
break;
} }
} }
} return FALSE;
enumerator->destroy(enumerator);
return found;
} }
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
private_sql_attribute_t *this, char *names, identification_t *id, private_sql_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *vip) linked_list_t *vips)
{ {
enumerator_t *attr_enumerator = NULL; enumerator_t *attr_enumerator = NULL;
if (vip) if (vips->get_count(vips))
{ {
enumerator_t *names_enumerator; enumerator_t *pool_enumerator;
u_int count; u_int count;
char *name; char *name;
@@ -357,8 +306,8 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
{ {
u_int identity = get_identity(this, id); u_int identity = get_identity(this, id);
names_enumerator = enumerator_create_token(names, ",", " "); pool_enumerator = pools->create_enumerator(pools);
while (names_enumerator->enumerate(names_enumerator, &name)) while (pool_enumerator->enumerate(pool_enumerator, &name))
{ {
u_int attr_pool = get_attr_pool(this, name); u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool) if (!attr_pool)
@@ -385,14 +334,14 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
DESTROY_IF(attr_enumerator); DESTROY_IF(attr_enumerator);
attr_enumerator = NULL; attr_enumerator = NULL;
} }
names_enumerator->destroy(names_enumerator); pool_enumerator->destroy(pool_enumerator);
} }
/* in a second step check for attributes that match name */ /* in a second step check for attributes that match name */
if (!attr_enumerator) if (!attr_enumerator)
{ {
names_enumerator = enumerator_create_token(names, ",", " "); pool_enumerator = pools->create_enumerator(pools);
while (names_enumerator->enumerate(names_enumerator, &name)) while (pool_enumerator->enumerate(pool_enumerator, &name))
{ {
u_int attr_pool = get_attr_pool(this, name); u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool) if (!attr_pool)
@@ -419,7 +368,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
DESTROY_IF(attr_enumerator); DESTROY_IF(attr_enumerator);
attr_enumerator = NULL; attr_enumerator = NULL;
} }
names_enumerator->destroy(names_enumerator); pool_enumerator->destroy(pool_enumerator);
} }
this->db->execute(this->db, NULL, "END TRANSACTION"); this->db->execute(this->db, NULL, "END TRANSACTION");
+48 -23
View File
@@ -267,46 +267,71 @@ METHOD(attribute_handler_t, release, void,
typedef struct { typedef struct {
/** implements enumerator_t interface */ /** implements enumerator_t interface */
enumerator_t public; enumerator_t public;
/** virtual IP we are requesting */ /** request IPv4 DNS? */
host_t *vip; bool v4;
/** request IPv6 DNS? */
bool v6;
} attribute_enumerator_t; } attribute_enumerator_t;
static bool attribute_enumerate(attribute_enumerator_t *this, static bool attribute_enumerate(attribute_enumerator_t *this,
configuration_attribute_type_t *type, configuration_attribute_type_t *type,
chunk_t *data) chunk_t *data)
{ {
switch (this->vip->get_family(this->vip)) if (this->v4)
{ {
case AF_INET:
*type = INTERNAL_IP4_DNS; *type = INTERNAL_IP4_DNS;
break;
case AF_INET6:
*type = INTERNAL_IP6_DNS;
break;
default:
return FALSE;
}
*data = chunk_empty; *data = chunk_empty;
/* enumerate only once */ this->v4 = FALSE;
this->public.enumerate = (void*)return_false;
return TRUE; 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*, 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); INIT(enumerator,
enumerator->public.enumerate = (void*)attribute_enumerate; .public = {
enumerator->public.destroy = (void*)free; .enumerate = (void*)attribute_enumerate,
enumerator->vip = vip; .destroy = (void*)free,
},
.v4 = has_host_family(vips, AF_INET),
.v6 = has_host_family(vips, AF_INET6),
);
return &enumerator->public; return &enumerator->public;
}
return enumerator_create_empty();
} }
METHOD(resolve_handler_t, destroy, void, 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_STR, offsetof(starter_end_t, subnet), NULL },
{ ARG_MISC, 0, NULL /* KW_PROTOPORT */ }, { ARG_MISC, 0, NULL /* KW_PROTOPORT */ },
{ ARG_STR, offsetof(starter_end_t, sourceip), NULL }, { 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, firewall), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool }, { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool },
{ ARG_ENUM, offsetof(starter_end_t, allow_any), 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)) if ((c1 == NULL) || (c2 == NULL))
return FALSE; return FALSE;
VARCMP(has_natip);
VARCMP(modecfg); VARCMP(modecfg);
VARCMP(port); VARCMP(port);
VARCMP(protocol); 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); end->host = strdupnull(value);
break; break;
case KW_SOURCEIP: 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->mode = MODE_TUNNEL;
conn->proxy_mode = FALSE; conn->proxy_mode = FALSE;
break; break;
@@ -370,27 +312,6 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
} }
break; 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: default:
break; break;
} }
+1 -2
View File
@@ -102,7 +102,6 @@ struct starter_end {
char *host; char *host;
u_int ikeport; u_int ikeport;
char *subnet; char *subnet;
bool has_natip;
bool modecfg; bool modecfg;
certpolicy_t sendcert; certpolicy_t sendcert;
bool firewall; bool firewall;
@@ -112,7 +111,7 @@ struct starter_end {
u_int16_t port; u_int16_t port;
u_int8_t protocol; u_int8_t protocol;
char *sourceip; char *sourceip;
int sourceip_mask; char *dns;
}; };
typedef struct also also_t; typedef struct also also_t;
+3 -3
View File
@@ -97,7 +97,7 @@ typedef enum {
KW_SUBNET, KW_SUBNET,
KW_PROTOPORT, KW_PROTOPORT,
KW_SOURCEIP, KW_SOURCEIP,
KW_NATIP, KW_DNS,
KW_FIREWALL, KW_FIREWALL,
KW_HOSTACCESS, KW_HOSTACCESS,
KW_ALLOWANY, KW_ALLOWANY,
@@ -126,7 +126,7 @@ typedef enum {
KW_LEFTSUBNET, KW_LEFTSUBNET,
KW_LEFTPROTOPORT, KW_LEFTPROTOPORT,
KW_LEFTSOURCEIP, KW_LEFTSOURCEIP,
KW_LEFTNATIP, KW_LEFTDNS,
KW_LEFTFIREWALL, KW_LEFTFIREWALL,
KW_LEFTHOSTACCESS, KW_LEFTHOSTACCESS,
KW_LEFTALLOWANY, KW_LEFTALLOWANY,
@@ -155,7 +155,7 @@ typedef enum {
KW_RIGHTSUBNET, KW_RIGHTSUBNET,
KW_RIGHTPROTOPORT, KW_RIGHTPROTOPORT,
KW_RIGHTSOURCEIP, KW_RIGHTSOURCEIP,
KW_RIGHTNATIP, KW_RIGHTDNS,
KW_RIGHTFIREWALL, KW_RIGHTFIREWALL,
KW_RIGHTHOSTACCESS, KW_RIGHTHOSTACCESS,
KW_RIGHTALLOWANY, KW_RIGHTALLOWANY,
+2 -2
View File
@@ -85,7 +85,7 @@ leftsubnet, KW_LEFTSUBNET
leftsubnetwithin, KW_LEFTSUBNET leftsubnetwithin, KW_LEFTSUBNET
leftprotoport, KW_LEFTPROTOPORT leftprotoport, KW_LEFTPROTOPORT
leftsourceip, KW_LEFTSOURCEIP leftsourceip, KW_LEFTSOURCEIP
leftnatip, KW_LEFTNATIP leftdns, KW_LEFTDNS
leftfirewall, KW_LEFTFIREWALL leftfirewall, KW_LEFTFIREWALL
lefthostaccess, KW_LEFTHOSTACCESS lefthostaccess, KW_LEFTHOSTACCESS
leftallowany, KW_LEFTALLOWANY leftallowany, KW_LEFTALLOWANY
@@ -109,7 +109,7 @@ rightsubnet, KW_RIGHTSUBNET
rightsubnetwithin, KW_RIGHTSUBNET rightsubnetwithin, KW_RIGHTSUBNET
rightprotoport, KW_RIGHTPROTOPORT rightprotoport, KW_RIGHTPROTOPORT
rightsourceip, KW_RIGHTSOURCEIP rightsourceip, KW_RIGHTSOURCEIP
rightnatip, KW_RIGHTNATIP rightdns, KW_RIGHTDNS
rightfirewall, KW_RIGHTFIREWALL rightfirewall, KW_RIGHTFIREWALL
righthostaccess, KW_RIGHTHOSTACCESS righthostaccess, KW_RIGHTHOSTACCESS
rightallowany, KW_RIGHTALLOWANY 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->ikeport = conn_end->ikeport;
msg_end->subnets = push_string(msg, conn_end->subnet); msg_end->subnets = push_string(msg, conn_end->subnet);
msg_end->sourceip = push_string(msg, conn_end->sourceip); 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->sendcert = conn_end->sendcert;
msg_end->hostaccess = conn_end->hostaccess; msg_end->hostaccess = conn_end->hostaccess;
msg_end->tohost = !conn_end->subnet; msg_end->tohost = !conn_end->subnet;
+1 -1
View File
@@ -158,7 +158,7 @@ struct stroke_end_t {
char *address; char *address;
u_int16_t ikeport; u_int16_t ikeport;
char *sourceip; char *sourceip;
int sourceip_mask; char *dns;
char *subnets; char *subnets;
int sendcert; int sendcert;
int hostaccess; int hostaccess;