Merge branch 'attr-enum'
authorMartin Willi <martin@revosec.ch>
Tue, 17 Jun 2014 13:15:02 +0000 (15:15 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 17 Jun 2014 13:15:02 +0000 (15:15 +0200)
Introduces a handle_vips() hook very similar to assign_vips(), but for clients
handling virtual IPs and other configuration attributes. Non-handled attributes
are stored on the IKE_SA as well and can be enumerated.

src/libcharon/bus/bus.c
src/libcharon/bus/bus.h
src/libcharon/bus/listeners/listener.h
src/libcharon/sa/ike_sa.c
src/libcharon/sa/ike_sa.h
src/libcharon/sa/ikev1/tasks/mode_config.c
src/libcharon/sa/ikev2/tasks/ike_config.c

index bc080d1..d467c33 100644 (file)
@@ -879,6 +879,33 @@ METHOD(bus_t, assign_vips, void,
        this->mutex->unlock(this->mutex);
 }
 
+METHOD(bus_t, handle_vips, void,
+       private_bus_t *this, ike_sa_t *ike_sa, bool handle)
+{
+       enumerator_t *enumerator;
+       entry_t *entry;
+       bool keep;
+
+       this->mutex->lock(this->mutex);
+       enumerator = this->listeners->create_enumerator(this->listeners);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->calling || !entry->listener->handle_vips)
+               {
+                       continue;
+               }
+               entry->calling++;
+               keep = entry->listener->handle_vips(entry->listener, ike_sa, handle);
+               entry->calling--;
+               if (!keep)
+               {
+                       unregister_listener(this, entry, enumerator);
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->mutex->unlock(this->mutex);
+}
+
 /**
  * Credential manager hook function to forward bus alerts
  */
@@ -955,6 +982,7 @@ bus_t *bus_create()
                        .authorize = _authorize,
                        .narrow = _narrow,
                        .assign_vips = _assign_vips,
+                       .handle_vips = _handle_vips,
                        .destroy = _destroy,
                },
                .listeners = linked_list_create(),
index 4a0ac68..1d708c5 100644 (file)
@@ -412,6 +412,14 @@ struct bus_t {
        void (*assign_vips)(bus_t *this, ike_sa_t *ike_sa, bool assign);
 
        /**
+        * Virtual IP handler hook.
+        *
+        * @param ike_sa        IKE_SA the VIPs/attributes got handled on
+        * @param assign        TRUE after installing attributes, FALSE on release
+        */
+       void (*handle_vips)(bus_t *this, ike_sa_t *ike_sa, bool handle);
+
+       /**
         * Destroy the event bus.
         */
        void (*destroy) (bus_t *this);
index 57445df..abcc765 100644 (file)
@@ -192,10 +192,10 @@ struct listener_t {
                                narrow_hook_t type, linked_list_t *local, linked_list_t *remote);
 
        /**
-        * Virtual IP address assignment hook
+        * Virtual IP address assignment hook.
         *
-        * This hook gets invoked when a a Virtual IP address is assigned to an
-        * IKE_SA (assign = TRUE) and again when it is released (assign = FALSE)
+        * This hook gets invoked after virtual IPs have been assigned to a peer
+        * for a specific IKE_SA, and again before they get released.
         *
         * @param ike_sa        IKE_SA the VIPs are assigned to
         * @param assign        TRUE if assigned to IKE_SA, FALSE if released
@@ -203,6 +203,18 @@ struct listener_t {
         */
        bool (*assign_vips)(listener_t *this, ike_sa_t *ike_sa, bool assign);
 
+       /**
+        * Virtual IP and configuration attribute handler hook.
+        *
+        * This hook gets invoked after virtual IP and other configuration
+        * attributes just got installed or are about to get uninstalled on a peer
+        * receiving them.
+        *
+        * @param ike_sa        IKE_SA the VIPs/attributes are handled on
+        * @param handle        TRUE if handled by IKE_SA, FALSE on release
+        * @return                      TRUE to stay registered, FALSE to unregister
+        */
+       bool (*handle_vips)(listener_t *this, ike_sa_t *ike_sa, bool handle);
 };
 
 #endif /** LISTENER_H_ @}*/
index 7b38e02..c338cda 100644 (file)
@@ -2001,6 +2001,26 @@ METHOD(ike_sa_t, add_configuration_attribute, void,
        array_insert(this->attributes, ARRAY_TAIL, &entry);
 }
 
+/**
+ * Enumerator filter for attributes
+ */
+static bool filter_attribute(void *null, attribute_entry_t **in,
+                                                        configuration_attribute_type_t *type, void *in2,
+                                                        chunk_t *data, void *in3, bool *handled)
+{
+       *type = (*in)->type;
+       *data = (*in)->data;
+       *handled = (*in)->handler != NULL;
+       return TRUE;
+}
+
+METHOD(ike_sa_t, create_attribute_enumerator, enumerator_t*,
+       private_ike_sa_t *this)
+{
+       return enumerator_create_filter(array_create_enumerator(this->attributes),
+                                                                       (void*)filter_attribute, NULL, NULL);
+}
+
 METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
        private_ike_sa_t *this, task_queue_t queue)
 {
@@ -2148,10 +2168,14 @@ METHOD(ike_sa_t, destroy, void,
        }
 
        /* remove attributes first, as we pass the IKE_SA to the handler */
+       charon->bus->handle_vips(charon->bus, &this->public, FALSE);
        while (array_remove(this->attributes, ARRAY_TAIL, &entry))
        {
-               hydra->attributes->release(hydra->attributes, entry.handler,
-                                                                  this->other_id, entry.type, entry.data);
+               if (entry.handler)
+               {
+                       hydra->attributes->release(hydra->attributes, entry.handler,
+                                                                          this->other_id, entry.type, entry.data);
+               }
                free(entry.data.ptr);
        }
        /* uninstall CHILD_SAs before virtual IPs, otherwise we might kill
@@ -2314,6 +2338,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
                        .clear_virtual_ips = _clear_virtual_ips,
                        .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
                        .add_configuration_attribute = _add_configuration_attribute,
+                       .create_attribute_enumerator = _create_attribute_enumerator,
                        .set_kmaddress = _set_kmaddress,
                        .create_task_enumerator = _create_task_enumerator,
                        .flush_queue = _flush_queue,
index d162539..15fb474 100644 (file)
@@ -978,6 +978,9 @@ struct ike_sa_t {
         * registered at the IKE_SA. Attributes are inherit()ed and get released
         * when the IKE_SA is closed.
         *
+        * Unhandled attributes are passed as well, but with a NULL handler. They
+        * do not get released.
+        *
         * @param handler               handler installed the attribute, use for release()
         * @param type                  configuration attribute type
         * @param data                  associated attribute data
@@ -987,6 +990,17 @@ struct ike_sa_t {
                                                        configuration_attribute_type_t type, chunk_t data);
 
        /**
+        * Create an enumerator over received configuration attributes.
+        *
+        * The resulting enumerator is over the configuration_attribute_type_t type,
+        * a value chunk_t followed by a bool flag. The boolean flag indicates if
+        * the attribute has been handled by an attribute handler.
+        *
+        * @return                              enumerator over type, value and the "handled" flag.
+        */
+       enumerator_t* (*create_attribute_enumerator)(ike_sa_t *this);
+
+       /**
         * Set local and remote host addresses to be used for IKE.
         *
         * These addresses are communicated via the KMADDRESS field of a MIGRATE
index 55fb390..94026b9 100644 (file)
@@ -139,11 +139,8 @@ static void handle_attribute(private_mode_config_t *this,
        handler = hydra->attributes->handle(hydra->attributes,
                                                        this->ike_sa->get_other_id(this->ike_sa), handler,
                                                        ca->get_type(ca), ca->get_chunk(ca));
-       if (handler)
-       {
-               this->ike_sa->add_configuration_attribute(this->ike_sa,
-                               handler, ca->get_type(ca), ca->get_chunk(ca));
-       }
+       this->ike_sa->add_configuration_attribute(this->ike_sa,
+                                                       handler, ca->get_type(ca), ca->get_chunk(ca));
 }
 
 /**
@@ -396,6 +393,8 @@ static status_t build_set(private_mode_config_t *this, message_t *message)
        any4->destroy(any4);
        any6->destroy(any6);
 
+       charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
+
        /* query registered providers for additional attributes to include */
        pools = linked_list_create_from_enumerator(
                                                                        config->create_pool_enumerator(config));
@@ -442,6 +441,8 @@ static void install_vips(private_mode_config_t *this)
                }
        }
        enumerator->destroy(enumerator);
+
+       charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
 }
 
 METHOD(task_t, process_r, status_t,
@@ -505,6 +506,8 @@ static status_t build_reply(private_mode_config_t *this, message_t *message)
        }
        enumerator->destroy(enumerator);
 
+       charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
+
        /* query registered providers for additional attributes to include */
        enumerator = hydra->attributes->create_responder_enumerator(
                                                                                        hydra->attributes, pools, id, vips);
index 1a4c21b..da06e2a 100644 (file)
@@ -130,11 +130,8 @@ static void handle_attribute(private_ike_config_t *this,
        handler = hydra->attributes->handle(hydra->attributes,
                                                        this->ike_sa->get_other_id(this->ike_sa), handler,
                                                        ca->get_type(ca), ca->get_chunk(ca));
-       if (handler)
-       {
-               this->ike_sa->add_configuration_attribute(this->ike_sa,
-                               handler, ca->get_type(ca), ca->get_chunk(ca));
-       }
+       this->ike_sa->add_configuration_attribute(this->ike_sa,
+                                                       handler, ca->get_type(ca), ca->get_chunk(ca));
 }
 
 /**
@@ -449,6 +446,8 @@ METHOD(task_t, process_i, status_t,
                        }
                }
                enumerator->destroy(enumerator);
+
+               charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
                return SUCCESS;
        }
        return NEED_MORE;