summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/farp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins/farp')
-rw-r--r--src/libcharon/plugins/farp/Makefile.in7
-rw-r--r--src/libcharon/plugins/farp/farp_listener.c147
-rw-r--r--src/libcharon/plugins/farp/farp_listener.h9
-rw-r--r--src/libcharon/plugins/farp/farp_spoofer.c20
4 files changed, 100 insertions, 83 deletions
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index 4ba29472d..cfb51933c 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -192,6 +192,9 @@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+axis2c_CFLAGS = @axis2c_CFLAGS@
+axis2c_LIBS = @axis2c_LIBS@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@@ -200,6 +203,7 @@ build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
c_plugins = @c_plugins@
+clearsilver_LIBS = @clearsilver_LIBS@
datadir = @datadir@
datarootdir = @datarootdir@
dbusservicedir = @dbusservicedir@
@@ -216,11 +220,13 @@ host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
+imcvdir = @imcvdir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
libcharon_plugins = @libcharon_plugins@
libdir = @libdir@
@@ -264,6 +270,7 @@ sharedstatedir = @sharedstatedir@
soup_CFLAGS = @soup_CFLAGS@
soup_LIBS = @soup_LIBS@
srcdir = @srcdir@
+starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
diff --git a/src/libcharon/plugins/farp/farp_listener.c b/src/libcharon/plugins/farp/farp_listener.c
index 8eed49778..d1df4cc27 100644
--- a/src/libcharon/plugins/farp/farp_listener.c
+++ b/src/libcharon/plugins/farp/farp_listener.c
@@ -15,7 +15,7 @@
#include "farp_listener.h"
-#include <utils/hashtable.h>
+#include <utils/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_farp_listener_t private_farp_listener_t;
@@ -31,9 +31,9 @@ struct private_farp_listener_t {
farp_listener_t public;
/**
- * Hashtable with active virtual IPs
+ * List with entry_t
*/
- hashtable_t *ips;
+ linked_list_t *entries;
/**
* RWlock for IP list
@@ -42,88 +42,99 @@ struct private_farp_listener_t {
};
/**
- * Hashtable hash function
+ * Traffic selector cache entry
*/
-static u_int hash(host_t *key)
+typedef struct {
+ /** list of local selectors */
+ linked_list_t *local;
+ /** list of remote selectors */
+ linked_list_t *remote;
+ /** reqid of CHILD_SA */
+ u_int32_t reqid;
+} entry_t;
+
+METHOD(listener_t, child_updown, bool,
+ private_farp_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ bool up)
{
- return chunk_hash(key->get_address(key));
-}
-
-/**
- * Hashtable equals function
- */
-static bool equals(host_t *a, host_t *b)
-{
- return a->ip_equals(a, b);
-}
+ enumerator_t *enumerator;
+ entry_t *entry;
-METHOD(listener_t, ike_updown, bool,
- private_farp_listener_t *this, ike_sa_t *ike_sa, bool up)
-{
- if (!up)
+ if (up)
{
- host_t *ip;
-
- ip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (ip)
- {
- this->lock->write_lock(this->lock);
- ip = this->ips->remove(this->ips, ip);
- this->lock->unlock(this->lock);
- DESTROY_IF(ip);
- }
+ INIT(entry,
+ .local = child_sa->get_traffic_selectors(child_sa, TRUE),
+ .remote = child_sa->get_traffic_selectors(child_sa, FALSE),
+ .reqid = child_sa->get_reqid(child_sa),
+ );
+ entry->local = entry->local->clone_offset(entry->local,
+ offsetof(traffic_selector_t, clone));
+ entry->remote = entry->remote->clone_offset(entry->remote,
+ offsetof(traffic_selector_t, clone));
+
+ this->lock->write_lock(this->lock);
+ this->entries->insert_last(this->entries, entry);
+ this->lock->unlock(this->lock);
}
- return TRUE;
-}
-
-METHOD(listener_t, message_hook, bool,
- private_farp_listener_t *this, ike_sa_t *ike_sa,
- message_t *message, bool incoming)
-{
- if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
- message->get_exchange_type(message) == IKE_AUTH &&
- !message->get_request(message))
+ else
{
- host_t *ip;
-
- ip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (ip)
+ this->lock->write_lock(this->lock);
+ enumerator = this->entries->create_enumerator(this->entries);
+ while (enumerator->enumerate(enumerator, &entry))
{
- ip = ip->clone(ip);
- this->lock->write_lock(this->lock);
- ip = this->ips->put(this->ips, ip, ip);
- this->lock->unlock(this->lock);
- DESTROY_IF(ip);
+ if (entry->reqid == child_sa->get_reqid(child_sa))
+ {
+ this->entries->remove_at(this->entries, enumerator);
+ entry->local->destroy_offset(entry->local,
+ offsetof(traffic_selector_t, destroy));
+ entry->remote->destroy_offset(entry->remote,
+ offsetof(traffic_selector_t, destroy));
+ free(entry);
+ }
}
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
}
return TRUE;
}
-METHOD(farp_listener_t, is_active, bool,
- private_farp_listener_t *this, host_t *ip)
+METHOD(farp_listener_t, has_tunnel, bool,
+ private_farp_listener_t *this, host_t *local, host_t *remote)
{
- bool active;
+ enumerator_t *entries, *locals, *remotes;
+ traffic_selector_t *ts;
+ bool found = FALSE;
+ entry_t *entry;
this->lock->read_lock(this->lock);
- active = this->ips->get(this->ips, ip) != NULL;
+ entries = this->entries->create_enumerator(this->entries);
+ while (!found && entries->enumerate(entries, &entry))
+ {
+ remotes = entry->remote->create_enumerator(entry->remote);
+ while (!found && remotes->enumerate(remotes, &ts))
+ {
+ if (ts->includes(ts, remote))
+ {
+ locals = entry->local->create_enumerator(entry->local);
+ while (!found && locals->enumerate(locals, &ts))
+ {
+ found = ts->includes(ts, local);
+ }
+ locals->destroy(locals);
+ }
+ }
+ remotes->destroy(remotes);
+ }
+ entries->destroy(entries);
this->lock->unlock(this->lock);
- return active;
+
+ return found;
}
METHOD(farp_listener_t, destroy, void,
private_farp_listener_t *this)
{
- enumerator_t *enumerator;
- host_t *key, *value;
-
- enumerator = this->ips->create_enumerator(this->ips);
- while (enumerator->enumerate(enumerator, &key, &value))
- {
- value->destroy(value);
- }
- enumerator->destroy(enumerator);
- this->ips->destroy(this->ips);
-
+ this->entries->destroy(this->entries);
this->lock->destroy(this->lock);
free(this);
}
@@ -138,14 +149,12 @@ farp_listener_t *farp_listener_create()
INIT(this,
.public = {
.listener = {
- .ike_updown = _ike_updown,
- .message = _message_hook,
+ .child_updown = _child_updown,
},
- .is_active = _is_active,
+ .has_tunnel = _has_tunnel,
.destroy = _destroy,
},
- .ips = hashtable_create((hashtable_hash_t)hash,
- (hashtable_equals_t)equals, 8),
+ .entries = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
diff --git a/src/libcharon/plugins/farp/farp_listener.h b/src/libcharon/plugins/farp/farp_listener.h
index bd96d7a1c..3155f60e2 100644
--- a/src/libcharon/plugins/farp/farp_listener.h
+++ b/src/libcharon/plugins/farp/farp_listener.h
@@ -37,12 +37,13 @@ struct farp_listener_t {
listener_t listener;
/**
- * Check if a given IP is currently used as virtual IP by a peer.
+ * Check if we have a tunnel between two IP addresses.
*
- * @param ip IP to check
- * @return TRUE if IP is an active virtual IP
+ * @param local local IP
+ * @param remote remote IP
+ * @return TRUE if a tunnel is active
*/
- bool (*is_active)(farp_listener_t *this, host_t *ip);
+ bool (*has_tunnel)(farp_listener_t *this, host_t *local, host_t *remote);
/**
* Destroy a farp_listener_t.
diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c
index a904a6538..587a3a74e 100644
--- a/src/libcharon/plugins/farp/farp_spoofer.c
+++ b/src/libcharon/plugins/farp/farp_spoofer.c
@@ -108,7 +108,7 @@ static job_requeue_t receive_arp(private_farp_spoofer_t *this)
arp_t arp;
int oldstate;
ssize_t len;
- host_t *ip;
+ host_t *local, *remote;
oldstate = thread_cancelability(TRUE);
len = recvfrom(this->skt, &arp, sizeof(arp), 0,
@@ -117,16 +117,16 @@ static job_requeue_t receive_arp(private_farp_spoofer_t *this)
if (len == sizeof(arp))
{
- ip = host_create_from_chunk(AF_INET,
+ local = host_create_from_chunk(AF_INET,
+ chunk_create((char*)&arp.sender_ip, 4), 0);
+ remote = host_create_from_chunk(AF_INET,
chunk_create((char*)&arp.target_ip, 4), 0);
- if (ip)
+ if (this->listener->has_tunnel(this->listener, local, remote))
{
- if (this->listener->is_active(this->listener, ip))
- {
- send_arp(this, &arp, &addr);
- }
- ip->destroy(ip);
+ send_arp(this, &arp, &addr);
}
+ local->destroy(local);
+ remote->destroy(remote);
}
return JOB_REQUEUE_DIRECT;
@@ -189,8 +189,8 @@ farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener)
return NULL;
}
- this->job = callback_job_create((callback_job_cb_t)receive_arp,
- this, NULL, NULL);
+ this->job = callback_job_create_with_prio((callback_job_cb_t)receive_arp,
+ this, NULL, NULL, JOB_PRIO_CRITICAL);
lib->processor->queue_job(lib->processor, (job_t*)this->job);
return &this->public;