aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2012-08-31 12:55:56 +0200
committerMartin Willi <martin@revosec.ch>2012-08-31 12:55:56 +0200
commit1323dc1138246a6e2819bcc20b167b75d52e6d7c (patch)
tree5081fcc1d015a8cd0ec6dfe39a8df14f12d86ac5 /src/libcharon/plugins
parent868409139b00f24607baab2d81b873cb1a5a9e5b (diff)
parent69e056a2c13ac7da9ed4e48f846d642aa01a362b (diff)
downloadstrongswan-1323dc1138246a6e2819bcc20b167b75d52e6d7c.tar.bz2
strongswan-1323dc1138246a6e2819bcc20b167b75d52e6d7c.tar.xz
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.
Diffstat (limited to 'src/libcharon/plugins')
-rw-r--r--src/libcharon/plugins/android/android_handler.c2
-rw-r--r--src/libcharon/plugins/android/android_service.c4
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c27
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c29
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c6
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c20
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c52
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c11
-rw-r--r--src/libcharon/plugins/maemo/maemo_service.c4
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c3
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_config.c1
-rw-r--r--src/libcharon/plugins/sql/sql_config.c18
-rw-r--r--src/libcharon/plugins/stroke/Makefile.am1
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c214
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.h23
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c173
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.h4
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c49
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.c231
-rw-r--r--src/libcharon/plugins/stroke/stroke_handler.h64
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c20
-rw-r--r--src/libcharon/plugins/uci/uci_config.c1
-rw-r--r--src/libcharon/plugins/updown/Makefile.am1
-rw-r--r--src/libcharon/plugins/updown/updown_handler.c243
-rw-r--r--src/libcharon/plugins/updown/updown_handler.h57
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c112
-rw-r--r--src/libcharon/plugins/updown/updown_listener.h4
-rw-r--r--src/libcharon/plugins/updown/updown_plugin.c22
29 files changed, 1200 insertions, 198 deletions
diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c
index a53962f16..f1d3045ca 100644
--- a/src/libcharon/plugins/android/android_handler.c
+++ b/src/libcharon/plugins/android/android_handler.c
@@ -196,7 +196,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
}
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
- android_handler_t *this, identification_t *id, host_t *vip)
+ android_handler_t *this, identification_t *id, linked_list_t *vips)
{
enumerator_t *enumerator;
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index f2d8ddce9..81628b80a 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -275,8 +275,8 @@ static job_requeue_t initiate(private_android_service_t *this)
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
index a6a887780..e46cc4d90 100644
--- a/src/libcharon/plugins/dhcp/dhcp_provider.c
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -84,7 +84,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
private_dhcp_provider_t *this, char *pool,
identification_t *id, host_t *requested)
{
- if (streq(pool, "dhcp"))
+ if (streq(pool, "dhcp") && requested->get_family(requested) == AF_INET)
{
dhcp_transaction_t *transaction, *old;
host_t *vip;
@@ -110,7 +110,7 @@ METHOD(attribute_provider_t, release_address, bool,
private_dhcp_provider_t *this, char *pool,
host_t *address, identification_t *id)
{
- if (streq(pool, "dhcp"))
+ if (streq(pool, "dhcp") && address->get_family(address) == AF_INET)
{
dhcp_transaction_t *transaction;
@@ -129,18 +129,25 @@ METHOD(attribute_provider_t, release_address, bool,
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_dhcp_provider_t *this, char *pool, identification_t *id,
- host_t *vip)
+ private_dhcp_provider_t *this, linked_list_t *pools, identification_t *id,
+ linked_list_t *vips)
{
- dhcp_transaction_t *transaction;
+ dhcp_transaction_t *transaction = NULL;
+ enumerator_t *enumerator;
+ host_t *vip;
- if (!vip)
+ this->mutex->lock(this->mutex);
+ enumerator = vips->create_enumerator(vips);
+ while (enumerator->enumerate(enumerator, &vip))
{
- return NULL;
+ transaction = this->transactions->get(this->transactions,
+ (void*)hash_id_host(id, vip));
+ if (transaction)
+ {
+ break;
+ }
}
- this->mutex->lock(this->mutex);
- transaction = this->transactions->get(this->transactions,
- (void*)hash_id_host(id, vip));
+ enumerator->destroy(enumerator);
if (!transaction)
{
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index 243c76304..7690cf9f8 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -149,6 +149,7 @@ static bool send_message(private_eap_radius_accounting_t *this,
*/
static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
{
+ enumerator_t *enumerator;
host_t *vip;
char buf[64];
chunk_t data;
@@ -157,17 +158,25 @@ static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa)
message->add(message, RAT_USER_NAME, chunk_create(buf, strlen(buf)));
snprintf(buf, sizeof(buf), "%#H", ike_sa->get_other_host(ike_sa));
message->add(message, RAT_CALLING_STATION_ID, chunk_create(buf, strlen(buf)));
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip && vip->get_family(vip) == AF_INET)
- {
- message->add(message, RAT_FRAMED_IP_ADDRESS, vip->get_address(vip));
- }
- if (vip && vip->get_family(vip) == AF_INET6)
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &vip))
{
- /* we currently assign /128 prefixes, only (reserved, length) */
- data = chunk_from_chars(0, 128);
- data = chunk_cata("cc", data, vip->get_address(vip));
- message->add(message, RAT_FRAMED_IPV6_PREFIX, data);
+ switch (vip->get_family(vip))
+ {
+ case AF_INET:
+ message->add(message, RAT_FRAMED_IP_ADDRESS,
+ vip->get_address(vip));
+ break;
+ case AF_INET6:
+ /* we currently assign /128 prefixes, only (reserved, length) */
+ data = chunk_from_chars(0, 128);
+ data = chunk_cata("cc", data, vip->get_address(vip));
+ message->add(message, RAT_FRAMED_IPV6_PREFIX, data);
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c
index 64bd2b8b7..f18c58b6a 100644
--- a/src/libcharon/plugins/ha/ha_attribute.c
+++ b/src/libcharon/plugins/ha/ha_attribute.c
@@ -181,6 +181,12 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
pool = get_pool(this, name);
if (pool)
{
+ if (pool->base->get_family(pool->base) !=
+ requested->get_family(requested))
+ {
+ this->mutex->unlock(this->mutex);
+ return NULL;
+ }
for (byte = 0; byte < pool->size / 8; byte++)
{
if (pool->mask[byte] != 0xFF)
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 8b6ec9180..f07b4ea21 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -344,10 +344,10 @@ static void process_ike_update(private_ha_dispatcher_t *this,
ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
break;
case HA_LOCAL_VIP:
- ike_sa->set_virtual_ip(ike_sa, TRUE, value.host);
+ ike_sa->add_virtual_ip(ike_sa, TRUE, value.host);
break;
case HA_REMOTE_VIP:
- ike_sa->set_virtual_ip(ike_sa, FALSE, value.host);
+ ike_sa->add_virtual_ip(ike_sa, FALSE, value.host);
received_vip = TRUE;
break;
case HA_PEER_ADDR:
@@ -413,18 +413,24 @@ static void process_ike_update(private_ha_dispatcher_t *this,
}
if (received_vip)
{
+ enumerator_t *pools, *vips;
host_t *vip;
char *pool;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (peer_cfg && vip)
+ if (peer_cfg)
{
- pool = peer_cfg->get_pool(peer_cfg);
- if (pool)
+ pools = peer_cfg->create_pool_enumerator(peer_cfg);
+ while (pools->enumerate(pools, &pool))
{
- this->attr->reserve(this->attr, pool, vip);
+ vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (vips->enumerate(vips, &vip))
+ {
+ this->attr->reserve(this->attr, pool, vip);
+ }
+ vips->destroy(vips);
}
+ pools->destroy(pools);
}
}
if (ike_sa->get_version(ike_sa) == IKEV1)
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index d523e8919..442a3a23d 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -241,6 +241,34 @@ METHOD(listener_t, ike_state_change, bool,
return TRUE;
}
+/**
+ * Send a virtual IP sync message for remote VIPs
+ */
+static void sync_vips(private_ha_ike_t *this, ike_sa_t *ike_sa)
+{
+ ha_message_t *m = NULL;
+ enumerator_t *enumerator;
+ host_t *vip;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &vip))
+ {
+ if (!m)
+ {
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ }
+ m->add_attribute(m, HA_REMOTE_VIP, vip);
+ }
+ enumerator->destroy(enumerator);
+
+ if (m)
+ {
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
+}
+
METHOD(listener_t, message_hook, bool,
private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message,
bool incoming, bool plain)
@@ -276,18 +304,7 @@ METHOD(listener_t, message_hook, bool,
{ /* After IKE_SA has been established, sync peers virtual IP.
* We cannot sync it in the state_change hook, it is installed later.
* TODO: where to sync local VIP? */
- ha_message_t *m;
- host_t *vip;
-
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip)
- {
- m = ha_message_create(HA_IKE_UPDATE);
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_REMOTE_VIP, vip);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
- }
+ sync_vips(this, ike_sa);
}
}
if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
@@ -296,7 +313,6 @@ METHOD(listener_t, message_hook, bool,
keymat_v1_t *keymat;
u_int32_t mid;
chunk_t iv;
- host_t *vip;
mid = message->get_message_id(message);
if (mid == 0)
@@ -313,15 +329,7 @@ METHOD(listener_t, message_hook, bool,
}
if (!incoming && message->get_exchange_type(message) == TRANSACTION)
{
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip)
- {
- m = ha_message_create(HA_IKE_UPDATE);
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_REMOTE_VIP, vip);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
- }
+ sync_vips(this, ike_sa);
}
}
if (plain && ike_sa->get_version(ike_sa) == IKEV1 &&
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index ad458caad..541dd9313 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -209,7 +209,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND,
UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30,
- 0, NULL, NULL, FALSE, NULL, NULL);
+ 0, FALSE, NULL, NULL);
auth_cfg = auth_cfg_create();
auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index f5da8b892..735f17985 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -268,8 +268,15 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
FALSE, FALSE, /* mobike, aggressive mode */
this->dpd_delay, /* dpd_delay */
this->dpd_timeout, /* dpd_timeout */
- this->vip ? this->vip->clone(this->vip) : NULL,
- this->pool, FALSE, NULL, NULL);
+ FALSE, NULL, NULL);
+ if (this->vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, this->vip->clone(this->vip));
+ }
+ if (this->pool)
+ {
+ peer_cfg->add_pool(peer_cfg, this->pool);
+ }
if (num)
{ /* initiator */
generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index f638a81b7..cb2fc9ebb 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -335,8 +335,8 @@ static gboolean initiate_connection(private_maemo_service_t *this,
600, 600, /* jitter, over 10min */
TRUE, FALSE, /* mobike, aggressive */
0, 0, /* DPD delay, timeout */
- host_create_from_string("0.0.0.0", 0) /* virt */,
- NULL, FALSE, NULL, NULL); /* pool, mediation */
+ FALSE, NULL, NULL); /* mediation */
+ peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0));
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 829c8f05e..a1825effc 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -129,7 +129,6 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
@@ -167,7 +166,6 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
FALSE, med_cfg, /* mediation, med by */
identification_create_from_encoding(ID_KEY_ID, other));
@@ -243,7 +241,6 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index ebc142de2..ff33c53e1 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -94,7 +94,6 @@ METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
this->rekey*5, this->rekey*3, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressiv */
this->dpd, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
TRUE, NULL, NULL); /* mediation, med by, peer id */
e->destroy(e);
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 890077157..c614c679e 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -333,6 +333,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
mediation, mediated_by, p_type;
chunk_t l_data, r_data, p_data;
char *name, *virtual, *pool;
+ enumerator_t *enumerator;
while (e->enumerate(e,
&id, &name, &ike_cfg, &l_type, &l_data, &r_type, &r_data,
@@ -371,8 +372,23 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
peer_cfg = peer_cfg_create(
name, IKEV2, ike, cert_policy, uniqueid,
keyingtries, rekeytime, reauthtime, jitter, overtime,
- mobike, FALSE, dpd_delay, 0, vip, pool,
+ mobike, FALSE, dpd_delay, 0,
mediation, mediated_cfg, peer_id);
+ if (vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, vip);
+ }
+ if (pool)
+ {
+ /* attr-sql used comma separated pools, but we now completely
+ * support multiple pools directly. Support old SQL configs: */
+ enumerator = enumerator_create_token(pool, ",", " ");
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ peer_cfg->add_pool(peer_cfg, pool);
+ }
+ enumerator->destroy(enumerator);
+ }
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, auth_method);
auth->add(auth, AUTH_RULE_IDENTITY, local_id);
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index e561224e9..cebcd984f 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -21,6 +21,7 @@ libstrongswan_stroke_la_SOURCES = \
stroke_cred.h stroke_cred.c \
stroke_ca.h stroke_ca.c \
stroke_attribute.h stroke_attribute.c \
+ stroke_handler.h stroke_handler.c \
stroke_list.h stroke_list.c
libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index 1e4615e12..3e012230a 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -17,7 +17,6 @@
#include "stroke_attribute.h"
#include <daemon.h>
-#include <attributes/mem_pool.h>
#include <utils/linked_list.h>
#include <threading/rwlock.h>
@@ -39,12 +38,37 @@ struct private_stroke_attribute_t {
linked_list_t *pools;
/**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
* rwlock to lock access to pools
*/
rwlock_t *lock;
};
/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+ /** name of the connection */
+ char *name;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this->name);
+ free(this);
+}
+
+/**
* find a pool by name
*/
static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
@@ -66,11 +90,12 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_stroke_attribute_t *this, char *name, identification_t *id,
- host_t *requested)
+ private_stroke_attribute_t *this, char *name, identification_t *id,
+ host_t *requested)
{
mem_pool_t *pool;
host_t *addr = NULL;
+
this->lock->read_lock(this->lock);
pool = find_pool(this, name);
if (pool)
@@ -82,11 +107,12 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
METHOD(attribute_provider_t, release_address, bool,
- private_stroke_attribute_t *this, char *name, host_t *address,
- identification_t *id)
+ private_stroke_attribute_t *this, char *name, host_t *address,
+ identification_t *id)
{
mem_pool_t *pool;
bool found = FALSE;
+
this->lock->read_lock(this->lock);
pool = find_pool(this, name);
if (pool)
@@ -97,56 +123,162 @@ METHOD(attribute_provider_t, release_address, bool,
return found;
}
-METHOD(stroke_attribute_t, add_pool, void,
- private_stroke_attribute_t *this, stroke_msg_t *msg)
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+ configuration_attribute_type_t *type,
+ void *dummy, chunk_t *data)
{
- if (msg->add_conn.other.sourceip_mask)
+ host_t *host = *in;
+
+ switch (host->get_family(host))
{
- mem_pool_t *pool;
- host_t *base = NULL;
- u_int32_t bits = 0;
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ *data = host->get_address(host);
+ return TRUE;
+}
- /* if %config, add an empty pool, otherwise */
- if (msg->add_conn.other.sourceip)
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+ private_stroke_attribute_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
+{
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
{
- DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d",
- msg->add_conn.name, msg->add_conn.other.sourceip,
- msg->add_conn.other.sourceip_mask);
- base = host_create_from_string(msg->add_conn.other.sourceip, 0);
- if (!base)
+ if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
{
- DBG1(DBG_CFG, "virtual IP address invalid, discarded");
- return;
+ enumerator->destroy(enumerator);
+ return enumerator_create_filter(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)attr_filter, this->lock,
+ (void*)this->lock->unlock);
}
- bits = msg->add_conn.other.sourceip_mask;
}
- pool = mem_pool_create(msg->add_conn.name, base, bits);
- DESTROY_IF(base);
-
- this->lock->write_lock(this->lock);
- this->pools->insert_last(this->pools, pool);
+ enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
+ return enumerator_create_empty();
}
-METHOD(stroke_attribute_t, del_pool, void,
- private_stroke_attribute_t *this, stroke_msg_t *msg)
+METHOD(stroke_attribute_t, add_pool, void,
+ private_stroke_attribute_t *this, mem_pool_t *pool)
{
enumerator_t *enumerator;
- mem_pool_t *pool;
+ mem_pool_t *current;
+ host_t *base;
+ int size;
+
+ base = pool->get_base(pool);
+ size = pool->get_size(pool);
this->lock->write_lock(this->lock);
+
enumerator = this->pools->create_enumerator(this->pools);
- while (enumerator->enumerate(enumerator, &pool))
+ while (enumerator->enumerate(enumerator, &current))
{
- if (streq(msg->del_conn.name, pool->get_name(pool)))
+ if (base && current->get_base(current) &&
+ base->ip_equals(base, current->get_base(current)) &&
+ size == current->get_size(current))
{
- this->pools->remove_at(this->pools, enumerator);
pool->destroy(pool);
+ pool = NULL;
+ DBG1(DBG_CFG, "reusing virtual IP address pool %H/%d", base, size);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (pool)
+ {
+ if (base)
+ {
+ DBG1(DBG_CFG, "adding virtual IP address pool %H/%d", base, size);
+ }
+ this->pools->insert_last(this->pools, pool);
+ }
+
+ this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_attribute_t, add_dns, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.other.dns)
+ {
+ enumerator_t *enumerator;
+ attributes_t *attr = NULL;
+ host_t *host;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ host = host_create_from_string(token, 0);
+ if (host)
+ {
+ if (!attr)
+ {
+ INIT(attr,
+ .name = strdup(msg->add_conn.name),
+ .dns = linked_list_create(),
+ );
+ }
+ attr->dns->insert_last(attr->dns, host);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (attr)
+ {
+ this->lock->write_lock(this->lock);
+ this->attrs->insert_last(this->attrs, attr);
+ this->lock->unlock(this->lock);
+ }
+ }
+}
+
+METHOD(stroke_attribute_t, del_dns, void,
+ private_stroke_attribute_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ this->lock->write_lock(this->lock);
+
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(msg->del_conn.name, attr->name))
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
break;
}
}
enumerator->destroy(enumerator);
+
this->lock->unlock(this->lock);
}
@@ -158,6 +290,11 @@ static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
void *d3, u_int *offline)
{
mem_pool_t *pool = *poolp;
+
+ if (pool->get_size(pool) == 0)
+ {
+ return FALSE;
+ }
*name = pool->get_name(pool);
*size = pool->get_size(pool);
*online = pool->get_online(pool);
@@ -166,7 +303,7 @@ static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
}
METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
- private_stroke_attribute_t *this)
+ private_stroke_attribute_t *this)
{
this->lock->read_lock(this->lock);
return enumerator_create_filter(this->pools->create_enumerator(this->pools),
@@ -175,7 +312,7 @@ METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
}
METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
- private_stroke_attribute_t *this, char *name)
+ private_stroke_attribute_t *this, char *name)
{
mem_pool_t *pool;
this->lock->read_lock(this->lock);
@@ -190,10 +327,11 @@ METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
}
METHOD(stroke_attribute_t, destroy, void,
- private_stroke_attribute_t *this)
+ private_stroke_attribute_t *this)
{
this->lock->destroy(this->lock);
this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
free(this);
}
@@ -209,15 +347,17 @@ stroke_attribute_t *stroke_attribute_create()
.provider = {
.acquire_address = _acquire_address,
.release_address = _release_address,
- .create_attribute_enumerator = enumerator_create_empty,
+ .create_attribute_enumerator = _create_attribute_enumerator,
},
.add_pool = _add_pool,
- .del_pool = _del_pool,
+ .add_dns = _add_dns,
+ .del_dns = _del_dns,
.create_pool_enumerator = _create_pool_enumerator,
.create_lease_enumerator = _create_lease_enumerator,
.destroy = _destroy,
},
.pools = linked_list_create(),
+ .attrs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.h b/src/libcharon/plugins/stroke/stroke_attribute.h
index 249a9899b..f1b9d135b 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.h
+++ b/src/libcharon/plugins/stroke/stroke_attribute.h
@@ -23,6 +23,7 @@
#include <stroke_msg.h>
#include <attributes/attribute_provider.h>
+#include <attributes/mem_pool.h>
typedef struct stroke_attribute_t stroke_attribute_t;
@@ -37,18 +38,28 @@ struct stroke_attribute_t {
attribute_provider_t provider;
/**
- * Add a virtual IP address pool.
+ * Add a memory pool to this virtual IP backend.
*
- * @param msg stroke message
+ * The pool gets owned by the provider, or destroyed if such a pool
+ * is already registered.
+ *
+ * @param pool virtual IP pool to add
+ */
+ void (*add_pool)(stroke_attribute_t *this, mem_pool_t *pool);
+
+ /**
+ * Add connection specific DNS servers.
+ *
+ * @param msg stroke add message
*/
- void (*add_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+ void (*add_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
- * Remove a virtual IP address pool.
+ * Remove connection specific DNS servers.
*
- * @param msg stroke message
+ * @param msg stroke del message
*/
- void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg);
+ void (*del_dns)(stroke_attribute_t *this, stroke_msg_t *msg);
/**
* Create an enumerator over installed pools.
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 9dcb9ba0c..e3c78f750 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -52,6 +52,11 @@ struct private_stroke_config_t {
* credentials
*/
stroke_cred_t *cred;
+
+ /**
+ * Virtual IP pool / DNS backend
+ */
+ stroke_attribute_t *attributes;
};
METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
@@ -618,7 +623,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
identification_t *peer_id = NULL;
peer_cfg_t *mediated_by = NULL;
- host_t *vip = NULL;
unique_policy_t unique;
u_int32_t rekey = 0, reauth = 0, over, jitter;
peer_cfg_t *peer_cfg;
@@ -677,49 +681,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
{
rekey = msg->add_conn.rekey.ike_lifetime - over;
}
- if (msg->add_conn.me.sourceip_mask)
- {
- if (msg->add_conn.me.sourceip)
- {
- vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
- }
- if (!vip)
- { /* if it is set to something like %poolname, request an address */
- if (msg->add_conn.me.subnets)
- { /* use the same family as in local subnet, if any */
- if (strchr(msg->add_conn.me.subnets, '.'))
- {
- vip = host_create_any(AF_INET);
- }
- else
- {
- vip = host_create_any(AF_INET6);
- }
- }
- else if (msg->add_conn.other.subnets)
- { /* use the same family as in remote subnet, if any */
- if (strchr(msg->add_conn.other.subnets, '.'))
- {
- vip = host_create_any(AF_INET);
- }
- else
- {
- vip = host_create_any(AF_INET6);
- }
- }
- else
- {
- if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
- {
- vip = host_create_any(AF_INET6);
- }
- else
- {
- vip = host_create_any(AF_INET);
- }
- }
- }
- }
switch (msg->add_conn.unique)
{
case 1: /* yes */
@@ -747,10 +708,126 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
msg->add_conn.mobike, msg->add_conn.aggressive,
msg->add_conn.dpd.delay, msg->add_conn.dpd.timeout,
- vip, msg->add_conn.other.sourceip_mask ?
- msg->add_conn.name : msg->add_conn.other.sourceip,
msg->add_conn.ikeme.mediation, mediated_by, peer_id);
+ if (msg->add_conn.other.sourceip)
+ {
+ enumerator_t *enumerator;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.other.sourceip,
+ ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
+ streq(token, "%config") || streq(token, "%cfg") ||
+ streq(token, "%config4") || streq(token, "%config6"))
+ {
+ /* empty pool, uses connection name */
+ this->attributes->add_pool(this->attributes,
+ mem_pool_create(msg->add_conn.name, NULL, 0));
+ peer_cfg->add_pool(peer_cfg, msg->add_conn.name);
+ }
+ else if (*token == '%')
+ {
+ /* external named pool */
+ peer_cfg->add_pool(peer_cfg, token + 1);
+ }
+ else
+ {
+ /* in-memory pool, named using CIDR notation */
+ host_t *base;
+ int bits;
+
+ base = host_create_from_subnet(token, &bits);
+ if (base)
+ {
+ this->attributes->add_pool(this->attributes,
+ mem_pool_create(token, base, bits));
+ peer_cfg->add_pool(peer_cfg, token);
+ base->destroy(base);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "IP pool %s invalid, ignored", token);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (msg->add_conn.me.sourceip)
+ {
+ enumerator_t *enumerator;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.me.sourceip, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ host_t *vip = NULL;
+
+ if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
+ streq(token, "%config") || streq(token, "%cfg"))
+ { /* try to deduce an address family */
+ if (msg->add_conn.me.subnets)
+ { /* use the same family as in local subnet, if any */
+ if (strchr(msg->add_conn.me.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else if (msg->add_conn.other.subnets)
+ { /* use the same family as in remote subnet, if any */
+ if (strchr(msg->add_conn.other.subnets, '.'))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ }
+ else
+ {
+ if (strchr(ike_cfg->get_my_addr(ike_cfg, NULL), ':'))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_any(AF_INET);
+ }
+ }
+ }
+ else if (streq(token, "%config4"))
+ {
+ vip = host_create_any(AF_INET);
+ }
+ else if (streq(token, "%config6"))
+ {
+ vip = host_create_any(AF_INET6);
+ }
+ else
+ {
+ vip = host_create_from_string(token, 0);
+ if (vip)
+ {
+ DBG1(DBG_CFG, "ignored invalid subnet token: %s", token);
+ }
+ }
+
+ if (vip)
+ {
+ peer_cfg->add_virtual_ip(peer_cfg, vip);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
/* build leftauth= */
auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
if (auth_cfg)
@@ -1209,7 +1286,8 @@ METHOD(stroke_config_t, destroy, void,
/*
* see header file
*/
-stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
+ stroke_attribute_t *attributes)
{
private_stroke_config_t *this;
@@ -1229,6 +1307,7 @@ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred)
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
.ca = ca,
.cred = cred,
+ .attributes = attributes,
);
return &this->public;
diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h
index 450d517f3..894e03ce4 100644
--- a/src/libcharon/plugins/stroke/stroke_config.h
+++ b/src/libcharon/plugins/stroke/stroke_config.h
@@ -26,6 +26,7 @@
#include <stroke_msg.h>
#include "stroke_ca.h"
#include "stroke_cred.h"
+#include "stroke_attribute.h"
typedef struct stroke_config_t stroke_config_t;
@@ -71,6 +72,7 @@ struct stroke_config_t {
/**
* Create a stroke_config instance.
*/
-stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred);
+stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
+ stroke_attribute_t *attributes);
#endif /** STROKE_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 163a2a750..233d4088f 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -407,10 +407,10 @@ METHOD(stroke_control_t, rekey, void,
METHOD(stroke_control_t, terminate_srcip, void,
private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
- enumerator_t *enumerator;
+ enumerator_t *enumerator, *vips;
ike_sa_t *ike_sa;
host_t *start = NULL, *end = NULL, *vip;
- chunk_t chunk_start, chunk_end = chunk_empty, chunk_vip;
+ chunk_t chunk_start, chunk_end = chunk_empty, chunk;
if (msg->terminate_srcip.start)
{
@@ -438,33 +438,40 @@ METHOD(stroke_control_t, terminate_srcip, void,
charon->controller, TRUE);
while (enumerator->enumerate(enumerator, &ike_sa))
{
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (!vip)
- {
- continue;
- }
- if (!end)
+ bool match = FALSE;
+
+ vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
+ while (vips->enumerate(vips, &vip))
{
- if (!vip->ip_equals(vip, start))
+ if (!end)
{
- continue;
+ if (vip->ip_equals(vip, start))
+ {
+ match = TRUE;
+ break;
+ }
}
- }
- else
- {
- chunk_vip = vip->get_address(vip);
- if (chunk_vip.len != chunk_start.len ||
- chunk_vip.len != chunk_end.len ||
- memcmp(chunk_vip.ptr, chunk_start.ptr, chunk_vip.len) < 0 ||
- memcmp(chunk_vip.ptr, chunk_end.ptr, chunk_vip.len) > 0)
+ else
{
- continue;
+ chunk = vip->get_address(vip);
+ if (chunk.len == chunk_start.len &&
+ chunk.len == chunk_end.len &&
+ memcmp(chunk.ptr, chunk_start.ptr, chunk.len) >= 0 &&
+ memcmp(chunk.ptr, chunk_end.ptr, chunk.len) <= 0)
+ {
+ match = TRUE;
+ break;
+ }
}
}
+ vips->destroy(vips);
- /* schedule delete asynchronously */
- lib->processor->queue_job(lib->processor, (job_t*)
+ if (match)
+ {
+ /* schedule delete asynchronously */
+ lib->processor->queue_job(lib->processor, (job_t*)
delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+ }
}
enumerator->destroy(enumerator);
start->destroy(start);
diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c
new file mode 100644
index 000000000..523151efb
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_handler.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "stroke_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_stroke_handler_t private_stroke_handler_t;
+
+/**
+ * Private data of an stroke_handler_t object.
+ */
+struct private_stroke_handler_t {
+
+ /**
+ * Public stroke_handler_t interface.
+ */
+ stroke_handler_t public;
+
+ /**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+ /** name of the connection */
+ char *name;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+ configuration_attribute_type_t *type,
+ void *dummy, chunk_t *data)
+{
+ host_t *host = *in;
+
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ *type = INTERNAL_IP4_DNS;
+ break;
+ case AF_INET6:
+ *type = INTERNAL_IP6_DNS;
+ break;
+ default:
+ return FALSE;
+ }
+ if (host->is_anyaddr(host))
+ {
+ *data = chunk_empty;
+ }
+ else
+ {
+ *data = host->get_address(host);
+ }
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+ private_stroke_handler_t *this, identification_t *server,
+ linked_list_t *vips)
+{
+ ike_sa_t *ike_sa;
+ peer_cfg_t *peer_cfg;
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
+ {
+ enumerator->destroy(enumerator);
+ return enumerator_create_filter(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)attr_filter, this->lock,
+ (void*)this->lock->unlock);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+ return enumerator_create_empty();
+}
+
+METHOD(stroke_handler_t, add_attributes, void,
+ private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+ if (msg->add_conn.me.dns)
+ {
+ enumerator_t *enumerator;
+ attributes_t *attr = NULL;
+ host_t *host;
+ char *token;
+
+ enumerator = enumerator_create_token(msg->add_conn.me.dns, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token, "%config") || streq(token, "%config4"))
+ {
+ host = host_create_any(AF_INET);
+ }
+ else if (streq(token, "%config6"))
+ {
+ host = host_create_any(AF_INET6);
+ }
+ else
+ {
+ host = host_create_from_string(token, 0);
+ }
+ if (host)
+ {
+ if (!attr)
+ {
+ INIT(attr,
+ .name = strdup(msg->add_conn.name),
+ .dns = linked_list_create(),
+ );
+ }
+ attr->dns->insert_last(attr->dns, host);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (attr)
+ {
+ this->lock->write_lock(this->lock);
+ this->attrs->insert_last(this->attrs, attr);
+ this->lock->unlock(this->lock);
+ }
+ }
+}
+
+METHOD(stroke_handler_t, del_attributes, void,
+ private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+ enumerator_t *enumerator;
+ attributes_t *attr;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (streq(msg->del_conn.name, attr->name))
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_handler_t, destroy, void,
+ private_stroke_handler_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+stroke_handler_t *stroke_handler_create()
+{
+ private_stroke_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = (void*)return_false,
+ .release = (void*)return_false,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ },
+ .add_attributes = _add_attributes,
+ .del_attributes = _del_attributes,
+ .destroy = _destroy,
+ },
+ .attrs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/stroke/stroke_handler.h b/src/libcharon/plugins/stroke/stroke_handler.h
new file mode 100644
index 000000000..ab76f80b0
--- /dev/null
+++ b/src/libcharon/plugins/stroke/stroke_handler.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup stroke_handler stroke_handler
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_HANDLER_H_
+#define STROKE_HANDLER_H_
+
+#include <stroke_msg.h>
+#include <attributes/attribute_handler.h>
+
+typedef struct stroke_handler_t stroke_handler_t;
+
+/**
+ * Handler requesting DNS attributes as defined with leftdns option.
+ */
+struct stroke_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Add connection specific configuration attributes.
+ *
+ * @param msg stroke message
+ */
+ void (*add_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+ /**
+ * Remove connection specific configuration attributes.
+ *
+ * @param msg stroke message
+ */
+ void (*del_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+ /**
+ * Destroy a stroke_handler_t.
+ */
+ void (*destroy)(stroke_handler_t *this);
+};
+
+/**
+ * Create a stroke_handler instance.
+ */
+stroke_handler_t *stroke_handler_create();
+
+#endif /** STROKE_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 6bf65cc7e..241f0fbf6 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -37,6 +37,7 @@
#include "stroke_cred.h"
#include "stroke_ca.h"
#include "stroke_attribute.h"
+#include "stroke_handler.h"
#include "stroke_list.h"
/**
@@ -99,6 +100,11 @@ struct private_stroke_socket_t {
stroke_attribute_t *attribute;
/**
+ * attribute handler (requests only)
+ */
+ stroke_handler_t *handler;
+
+ /**
* controller to control daemon
*/
stroke_control_t *control;
@@ -171,6 +177,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
pop_string(msg, &end->address);
pop_string(msg, &end->subnets);
pop_string(msg, &end->sourceip);
+ pop_string(msg, &end->dns);
pop_string(msg, &end->auth);
pop_string(msg, &end->auth2);
pop_string(msg, &end->id);
@@ -188,6 +195,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
DBG2(DBG_CFG, " %s=%s", label, end->address);
DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
+ DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
DBG2(DBG_CFG, " %sid=%s", label, end->id);
@@ -235,7 +243,8 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
this->config->add(this->config, msg);
- this->attribute->add_pool(this->attribute, msg);
+ this->attribute->add_dns(this->attribute, msg);
+ this->handler->add_attributes(this->handler, msg);
}
/**
@@ -247,7 +256,8 @@ static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
this->config->del(this->config, msg);
- this->attribute->del_pool(this->attribute, msg);
+ this->attribute->del_dns(this->attribute, msg);
+ this->handler->del_attributes(this->handler, msg);
}
/**
@@ -787,10 +797,12 @@ METHOD(stroke_socket_t, destroy, void,
lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->backends->remove_backend(charon->backends, &this->config->backend);
hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
this->cred->destroy(this->cred);
this->ca->destroy(this->ca);
this->config->destroy(this->config);
this->attribute->destroy(this->attribute);
+ this->handler->destroy(this->handler);
this->control->destroy(this->control);
this->list->destroy(this->list);
free(this);
@@ -817,8 +829,9 @@ stroke_socket_t *stroke_socket_create()
this->cred = stroke_cred_create();
this->attribute = stroke_attribute_create();
+ this->handler = stroke_handler_create();
this->ca = stroke_ca_create(this->cred);
- this->config = stroke_config_create(this->ca, this->cred);
+ this->config = stroke_config_create(this->ca, this->cred, this->attribute);
this->control = stroke_control_create();
this->list = stroke_list_create(this->attribute);
@@ -833,6 +846,7 @@ stroke_socket_t *stroke_socket_create()
lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
+ hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
lib->processor->queue_job(lib->processor,
(job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index 5b698b8b2..1201f568e 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -178,7 +178,6 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
1800, 900, /* jitter, overtime */
TRUE, FALSE, /* mobike, aggressive */
60, 0, /* DPD delay, timeout */
- NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */
auth = auth_cfg_create();
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
index 312c8d7e8..30683d83e 100644
--- a/src/libcharon/plugins/updown/Makefile.am
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -12,6 +12,7 @@ endif
libstrongswan_updown_la_SOURCES = \
updown_plugin.h updown_plugin.c \
+ updown_handler.h updown_handler.c \
updown_listener.h updown_listener.c
libstrongswan_updown_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/updown/updown_handler.c b/src/libcharon/plugins/updown/updown_handler.c
new file mode 100644
index 000000000..b2ac02e85
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_handler.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "updown_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_updown_handler_t private_updown_handler_t;
+
+/**
+ * Private data of an updown_handler_t object.
+ */
+struct private_updown_handler_t {
+
+ /**
+ * Public updown_handler_t interface.
+ */
+ updown_handler_t public;
+
+ /**
+ * List of connection specific attributes, as attributes_t
+ */
+ linked_list_t *attrs;
+
+ /**
+ * rwlock to lock access to pools
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to an IKE_SA
+ */
+typedef struct {
+ /** unique IKE_SA identifier */
+ u_int id;
+ /** list of DNS attributes, as host_t */
+ linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+ this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+ free(this);
+}
+
+METHOD(attribute_handler_t, handle, bool,
+ private_updown_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attributes_t *current, *attr = NULL;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ host_t *host;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ host = host_create_from_chunk(AF_INET, data, 0);
+ break;
+ case INTERNAL_IP6_DNS:
+ host = host_create_from_chunk(AF_INET6, data, 0);
+ break;
+ default:
+ return FALSE;
+ }
+ if (!host)
+ {
+ return FALSE;
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->id == ike_sa->get_unique_id(ike_sa))
+ {
+ attr = current;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!attr)
+ {
+ INIT(attr,
+ .id = ike_sa->get_unique_id(ike_sa),
+ .dns = linked_list_create(),
+ );
+ this->attrs->insert_last(this->attrs, attr);
+ }
+ attr->dns->insert_last(attr->dns, host);
+ this->lock->unlock(this->lock);
+
+ return TRUE;
+}
+
+METHOD(attribute_handler_t, release, void,
+ private_updown_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data)
+{
+ attributes_t *attr;
+ enumerator_t *enumerator, *servers;
+ ike_sa_t *ike_sa;
+ host_t *host;
+ bool found = FALSE;
+ int family;
+
+ switch (type)
+ {
+ case INTERNAL_IP4_DNS:
+ family = AF_INET;
+ break;
+ case INTERNAL_IP6_DNS:
+ family = AF_INET6;
+ break;
+ default:
+ return;
+ }
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ this->lock->write_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->id == ike_sa->get_unique_id(ike_sa))
+ {
+ servers = attr->dns->create_enumerator(attr->dns);
+ while (servers->enumerate(servers, &host))
+ {
+ if (host->get_family(host) == family &&
+ chunk_equals(data, host->get_address(host)))
+ {
+ attr->dns->remove_at(attr->dns, servers);
+ host->destroy(host);
+ found = TRUE;
+ break;
+ }
+ }
+ servers->destroy(servers);
+ if (attr->dns->get_count(attr->dns) == 0)
+ {
+ this->attrs->remove_at(this->attrs, enumerator);
+ attributes_destroy(attr);
+ break;
+ }
+ }
+ if (found)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+}
+
+METHOD(updown_handler_t, create_dns_enumerator, enumerator_t*,
+ private_updown_handler_t *this, u_int id)
+{
+ attributes_t *attr;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (!ike_sa)
+ {
+ return FALSE;
+ }
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->attrs->create_enumerator(this->attrs);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ if (attr->id == ike_sa->get_unique_id(ike_sa))
+ {
+ enumerator->destroy(enumerator);
+ return enumerator_create_cleaner(
+ attr->dns->create_enumerator(attr->dns),
+ (void*)this->lock->unlock, this->lock);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return enumerator_create_empty();
+}
+
+
+METHOD(updown_handler_t, destroy, void,
+ private_updown_handler_t *this)
+{
+ this->lock->destroy(this->lock);
+ this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+ free(this);
+}
+
+/**
+ * See header
+ */
+updown_handler_t *updown_handler_create()
+{
+ private_updown_handler_t *this;
+
+ INIT(this,
+ .public = {
+ .handler = {
+ .handle = _handle,
+ .release = _release,
+ .create_attribute_enumerator = enumerator_create_empty,
+ },
+ .create_dns_enumerator = _create_dns_enumerator,
+ .destroy = _destroy,
+ },
+ .attrs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/updown/updown_handler.h b/src/libcharon/plugins/updown/updown_handler.h
new file mode 100644
index 000000000..d4de880b8
--- /dev/null
+++ b/src/libcharon/plugins/updown/updown_handler.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup updown_handler updown_handler
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_HANDLER_H_
+#define UPDOWN_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct updown_handler_t updown_handler_t;
+
+/**
+ * Handler storing configuration attributes to pass to updown script.
+ */
+struct updown_handler_t {
+
+ /**
+ * Implements the attribute_handler_t interface
+ */
+ attribute_handler_t handler;
+
+ /**
+ * Create an enumerator over received DNS servers.
+ *
+ * @param id unique IKE_SA identifier to get attributes for
+ * @return enumerator over host_t*
+ */
+ enumerator_t* (*create_dns_enumerator)(updown_handler_t *this, u_int id);
+
+ /**
+ * Destroy a updown_handler_t.
+ */
+ void (*destroy)(updown_handler_t *this);
+};
+
+/**
+ * Create a updown_handler instance.
+ */
+updown_handler_t *updown_handler_create();
+
+#endif /** UPDOWN_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 2bd757ec7..2f9f2ef91 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -38,6 +38,11 @@ struct private_updown_listener_t {
* List of cached interface names
*/
linked_list_t *iface_cache;
+
+ /**
+ * DNS attribute handler
+ */
+ updown_handler_t *handler;
};
typedef struct cache_entry_t cache_entry_t;
@@ -90,6 +95,85 @@ static char* uncache_iface(private_updown_listener_t *this, u_int32_t reqid)
return iface;
}
+/**
+ * Create variables for handled DNS attributes
+ */
+static char *make_dns_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+ char total[512] = "", current[64];
+
+ if (!this->handler)
+ {
+ return strdup("");
+ }
+
+ enumerator = this->handler->create_dns_enumerator(this->handler,
+ ike_sa->get_unique_id(ike_sa));
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ snprintf(current, sizeof(current),
+ "PLUTO_DNS4_%d='%H' ", ++v4, host);
+ break;
+ case AF_INET6:
+ snprintf(current, sizeof(current),
+ "PLUTO_DNS6_%d='%H' ", ++v6, host);
+ break;
+ default:
+ continue;
+ }
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ enumerator->destroy(enumerator);
+
+ return strdup(total);
+}
+
+/**
+ * Create variables for local virtual IPs
+ */
+static char *make_vip_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+ char total[512] = "", current[64];
+ bool first = TRUE;
+
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ while (enumerator->enumerate(enumerator, &host))
+ {
+ if (first)
+ { /* legacy variable for first VIP */
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP='%H' ", host);
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP4_%d='%H' ", ++v4, host);
+ break;
+ case AF_INET6:
+ snprintf(current, sizeof(current),
+ "PLUTO_MY_SOURCEIP6_%d='%H' ", ++v6, host);
+ break;
+ default:
+ continue;
+ }
+ strncat(total, current, sizeof(total) - strlen(total) - 1);
+ }
+ enumerator->destroy(enumerator);
+
+ return strdup(total);
+}
+
METHOD(listener_t, child_updown, bool,
private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
bool up)
@@ -97,11 +181,10 @@ METHOD(listener_t, child_updown, bool,
traffic_selector_t *my_ts, *other_ts;
enumerator_t *enumerator;
child_cfg_t *config;
- host_t *vip, *me, *other;
+ host_t *me, *other;
char *script;
config = child_sa->get_config(child_sa);
- vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
script = config->get_updown(config);
me = ike_sa->get_my_host(ike_sa);
other = ike_sa->get_other_host(ike_sa);
@@ -117,7 +200,7 @@ METHOD(listener_t, child_updown, bool,
char command[1024];
host_t *my_client, *other_client;
u_int8_t my_client_mask, other_client_mask;
- char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc;
+ char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc, *dns;
mark_t mark;
bool is_host, is_ipv6;
FILE *shell;
@@ -125,20 +208,7 @@ METHOD(listener_t, child_updown, bool,
my_ts->to_subnet(my_ts, &my_client, &my_client_mask);
other_ts->to_subnet(other_ts, &other_client, &other_client_mask);
- if (vip)
- {
- if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0)
- {
- virtual_ip = NULL;
- }
- }
- else
- {
- if (asprintf(&virtual_ip, "") < 0)
- {
- virtual_ip = NULL;
- }
- }
+ virtual_ip = make_vip_vars(this, ike_sa);
/* check for the presence of an inbound mark */
mark = config->get_mark(config, TRUE);
@@ -209,6 +279,8 @@ METHOD(listener_t, child_updown, bool,
iface = uncache_iface(this, child_sa->get_reqid(child_sa));
}
+ dns = make_dns_vars(this, ike_sa);
+
/* determine IPv4/IPv6 and client/host situation */
is_host = my_ts->is_host(my_ts, me);
is_ipv6 = is_host ? (me->get_family(me) == AF_INET6) :
@@ -239,6 +311,7 @@ METHOD(listener_t, child_updown, bool,
"%s"
"%s"
"%s"
+ "%s"
"%s",
up ? "up" : "down",
is_host ? "-host" : "-client",
@@ -259,6 +332,7 @@ METHOD(listener_t, child_updown, bool,
mark_out,
udp_enc,
config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
+ dns,
script);
my_client->destroy(my_client);
other_client->destroy(other_client);
@@ -266,6 +340,7 @@ METHOD(listener_t, child_updown, bool,
free(mark_in);
free(mark_out);
free(udp_enc);
+ free(dns);
free(iface);
DBG3(DBG_CHD, "running updown script: %s", command);
@@ -315,7 +390,7 @@ METHOD(updown_listener_t, destroy, void,
/**
* See header
*/
-updown_listener_t *updown_listener_create()
+updown_listener_t *updown_listener_create(updown_handler_t *handler)
{
private_updown_listener_t *this;
@@ -327,6 +402,7 @@ updown_listener_t *updown_listener_create()
.destroy = _destroy,
},
.iface_cache = linked_list_create(),
+ .handler = handler,
);
return &this->public;
diff --git a/src/libcharon/plugins/updown/updown_listener.h b/src/libcharon/plugins/updown/updown_listener.h
index 5b866c4e5..2d9b56ade 100644
--- a/src/libcharon/plugins/updown/updown_listener.h
+++ b/src/libcharon/plugins/updown/updown_listener.h
@@ -23,6 +23,8 @@
#include <bus/bus.h>
+#include "updown_handler.h"
+
typedef struct updown_listener_t updown_listener_t;
/**
@@ -44,6 +46,6 @@ struct updown_listener_t {
/**
* Create a updown_listener instance.
*/
-updown_listener_t *updown_listener_create();
+updown_listener_t *updown_listener_create(updown_handler_t *handler);
#endif /** UPDOWN_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c
index 2ce2d3257..e1f0d1380 100644
--- a/src/libcharon/plugins/updown/updown_plugin.c
+++ b/src/libcharon/plugins/updown/updown_plugin.c
@@ -15,8 +15,10 @@
#include "updown_plugin.h"
#include "updown_listener.h"
+#include "updown_handler.h"
#include <daemon.h>
+#include <hydra.h>
typedef struct private_updown_plugin_t private_updown_plugin_t;
@@ -34,6 +36,11 @@ struct private_updown_plugin_t {
* Listener interface, listens to CHILD_SA state changes
*/
updown_listener_t *listener;
+
+ /**
+ * Attribute handler, to pass DNS servers to updown
+ */
+ updown_handler_t *handler;
};
METHOD(plugin_t, get_name, char*,
@@ -47,6 +54,12 @@ METHOD(plugin_t, destroy, void,
{
charon->bus->remove_listener(charon->bus, &this->listener->listener);
this->listener->destroy(this->listener);
+ if (this->handler)
+ {
+ hydra->attributes->remove_handler(hydra->attributes,
+ &this->handler->handler);
+ this->handler->destroy(this->handler);
+ }
free(this);
}
@@ -65,9 +78,16 @@ plugin_t *updown_plugin_create()
.destroy = _destroy,
},
},
- .listener = updown_listener_create(),
);
+ if (lib->settings->get_bool(lib->settings,
+ "charon.plugins.updown.dns_handler", FALSE))
+ {
+ this->handler = updown_handler_create();
+ hydra->attributes->add_handler(hydra->attributes,
+ &this->handler->handler);
+ }
+ this->listener = updown_listener_create(this->handler);
charon->bus->add_listener(charon->bus, &this->listener->listener);
return &this->public.plugin;