]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Add a lookip function to register virtual IP notification listeners
authorMartin Willi <martin@revosec.ch>
Wed, 3 Oct 2012 15:42:19 +0000 (17:42 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 24 Oct 2012 09:43:34 +0000 (11:43 +0200)
src/libcharon/plugins/lookip/lookip_listener.c
src/libcharon/plugins/lookip/lookip_listener.h

index 77ad78ea75c37ee2d5c1d86de046a6e20d65594a..9be4e09eabb613ae3321afa01a8c0f805041dbfb 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <daemon.h>
 #include <utils/hashtable.h>
+#include <utils/linked_list.h>
 #include <threading/rwlock.h>
 
 typedef struct private_lookip_listener_t private_lookip_listener_t;
@@ -40,8 +41,23 @@ struct private_lookip_listener_t {
         * Hashtable with entries: host_t => entry_t
         */
        hashtable_t *entries;
+
+       /**
+        * List of registered listeners
+        */
+       linked_list_t *listeners;
 };
 
+/**
+ * Listener entry
+ */
+typedef struct {
+       /** callback function */
+       lookip_callback_t cb;
+       /** user data for callback */
+       void *user;
+} listener_entry_t;
+
 /**
  * Hashtable entry
  */
@@ -84,6 +100,34 @@ static bool equals(host_t *a, host_t *b)
        return a->ip_equals(a, b);
 }
 
+/**
+ * Compare callback that invokes up callback of all registered listeners
+ */
+static bool notify_up(listener_entry_t *listener, entry_t *entry)
+{
+       if (!listener->cb(listener->user, TRUE, entry->vip, entry->other,
+                                         entry->id, entry->name))
+       {
+               free(listener);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/**
+ * Compare callback that invokes down callback of all registered listeners
+ */
+static bool notify_down(listener_entry_t *listener, entry_t *entry)
+{
+       if (!listener->cb(listener->user, FALSE, entry->vip, entry->other,
+                                                entry->id, entry->name))
+       {
+               free(listener);
+               return TRUE;
+       }
+       return FALSE;
+}
+
 /**
  * Add a new entry to the hashtable
  */
@@ -107,6 +151,10 @@ static void add_entry(private_lookip_listener_t *this, ike_sa_t *ike_sa)
                        .name = strdup(ike_sa->get_name(ike_sa)),
                );
 
+               this->lock->read_lock(this->lock);
+               this->listeners->remove(this->listeners, entry, (void*)notify_up);
+               this->lock->unlock(this->lock);
+
                this->lock->write_lock(this->lock);
                entry = this->entries->put(this->entries, entry->vip, entry);
                this->lock->unlock(this->lock);
@@ -135,6 +183,10 @@ static void remove_entry(private_lookip_listener_t *this, ike_sa_t *ike_sa)
                this->lock->unlock(this->lock);
                if (entry)
                {
+                       this->lock->read_lock(this->lock);
+                       this->listeners->remove(this->listeners, entry, (void*)notify_down);
+                       this->lock->unlock(this->lock);
+
                        entry_destroy(entry);
                }
        }
@@ -184,7 +236,7 @@ METHOD(lookip_listener_t, lookup, void,
                entry = this->entries->get(this->entries, vip);
                if (entry)
                {
-                       cb(user, entry->vip, entry->other, entry->id, entry->name);
+                       cb(user, TRUE, entry->vip, entry->other, entry->id, entry->name);
                }
        }
        else
@@ -194,16 +246,32 @@ METHOD(lookip_listener_t, lookup, void,
                enumerator = this->entries->create_enumerator(this->entries);
                while (enumerator->enumerate(enumerator, &vip, &entry))
                {
-                       cb(user, entry->vip, entry->other, entry->id, entry->name);
+                       cb(user, TRUE, entry->vip, entry->other, entry->id, entry->name);
                }
                enumerator->destroy(enumerator);
        }
        this->lock->unlock(this->lock);
 }
 
+METHOD(lookip_listener_t, add_listener, void,
+       private_lookip_listener_t *this, lookip_callback_t cb, void *user)
+{
+       listener_entry_t *listener;
+
+       INIT(listener,
+               .cb = cb,
+               .user = user,
+       );
+
+       this->lock->write_lock(this->lock);
+       this->listeners->insert_last(this->listeners, listener);
+       this->lock->unlock(this->lock);
+}
+
 METHOD(lookip_listener_t, destroy, void,
        private_lookip_listener_t *this)
 {
+       this->listeners->destroy_function(this->listeners, free);
        this->entries->destroy(this->entries);
        this->lock->destroy(this->lock);
        free(this);
@@ -223,11 +291,13 @@ lookip_listener_t *lookip_listener_create()
                                .ike_updown = _ike_updown,
                        },
                        .lookup = _lookup,
+                       .add_listener = _add_listener,
                        .destroy = _destroy,
                },
                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                .entries = hashtable_create((hashtable_hash_t)hash,
                                                                        (hashtable_equals_t)equals, 32),
+               .listeners = linked_list_create(),
        );
 
        return &this->public;
index eeb955ec612699ac671f43328979332a74887812..63378fbb84071abe41f32996fc9e28ae055b7e67 100644 (file)
@@ -29,14 +29,15 @@ typedef struct lookip_listener_t lookip_listener_t;
  * Callback function to query virtual IP entries
  *
  * @param user         user supplied pointer
+ * @param up           TRUE if tunnels established, FALSE if closed
  * @param vip          virtual IP of remote peer
  * @param other                peer external IP
  * @param id           peer identity
  * @param name         associated connection name
  * @return                     TRUE to receive more results, FALSE to cancel
  */
-typedef bool (*lookip_callback_t)(void *user, host_t *vip, host_t *other,
-                                                                 identification_t *id, char *name);
+typedef bool (*lookip_callback_t)(void *user, bool up, host_t *vip,
+                                                       host_t *other, identification_t *id, char *name);
 
 /**
  * Listener collecting virtual IPs.
@@ -51,6 +52,9 @@ struct lookip_listener_t {
        /**
         * Perform a lookup for a given virtual IP, invoke callback for matches.
         *
+        * The "up" parameter is always TRUE when the callback is invoked using
+        * lookup().
+        *
         * @param vip           virtual IP to look up, NULL to get all entries
         * @param cb            callback function to invoke
         * @param user          user data to pass to callback function
@@ -58,6 +62,15 @@ struct lookip_listener_t {
        void (*lookup)(lookip_listener_t *this, host_t *vip,
                                   lookip_callback_t cb, void *user);
 
+       /**
+        * Register a listener function that gets notified about virtual IP changes.
+        *
+        * @param cb            callback function to invoke
+        * @param user          user data to pass to callback function
+        */
+       void (*add_listener)(lookip_listener_t *this,
+                                                lookip_callback_t cb, void *user);
+
        /**
         * Destroy a lookip_listener_t.
         */