diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
commit | b34738ed08c2227300d554b139e2495ca5da97d6 (patch) | |
tree | 62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libcharon/plugins/farp | |
parent | 0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff) | |
download | vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip |
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libcharon/plugins/farp')
-rw-r--r-- | src/libcharon/plugins/farp/Makefile.in | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/farp/farp_listener.c | 147 | ||||
-rw-r--r-- | src/libcharon/plugins/farp/farp_listener.h | 9 | ||||
-rw-r--r-- | src/libcharon/plugins/farp/farp_spoofer.c | 20 |
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; |