attr: Only enumerate attributes matching the IKE version of the current IKE_SA
authorTobias Brunner <tobias@strongswan.org>
Thu, 11 Feb 2016 14:47:32 +0000 (15:47 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 10 Mar 2016 10:57:39 +0000 (11:57 +0100)
Numerically configured attributes are currently sent for both versions.

src/libcharon/plugins/attr/attr_provider.c

index 6b6f7b5..1de571c 100644 (file)
@@ -54,6 +54,8 @@ struct attribute_entry_t {
        configuration_attribute_type_t type;
        /** attribute value */
        chunk_t value;
+       /** associated IKE version */
+       ike_version_t ike;
 };
 
 /**
@@ -66,26 +68,51 @@ static void attribute_destroy(attribute_entry_t *this)
 }
 
 /**
+ * Data for attribute enumerator
+ */
+typedef struct {
+       rwlock_t *lock;
+       ike_version_t ike;
+} enumerator_data_t;
+
+/**
  * convert enumerator value from attribute_entry
  */
-static bool attr_enum_filter(void *null, attribute_entry_t **in,
+static bool attr_enum_filter(enumerator_data_t *data, attribute_entry_t **in,
                        configuration_attribute_type_t *type, void* none, chunk_t *value)
 {
-       *type = (*in)->type;
-       *value = (*in)->value;
-       return TRUE;
+       if ((*in)->ike == IKE_ANY || (*in)->ike == data->ike)
+       {
+               *type = (*in)->type;
+               *value = (*in)->value;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+CALLBACK(attr_enum_destroy, void,
+       enumerator_data_t *data)
+{
+       data->lock->unlock(data->lock);
+       free(data);
 }
 
 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
        private_attr_provider_t *this, linked_list_t *pools,
        ike_sa_t *ike_sa, linked_list_t *vips)
 {
+       enumerator_data_t *data;
+
        if (vips->get_count(vips))
        {
+               INIT(data,
+                       .lock = this->lock,
+                       .ike = ike_sa->get_version(ike_sa),
+               );
                this->lock->read_lock(this->lock);
                return enumerator_create_filter(
                                this->attributes->create_enumerator(this->attributes),
-                               (void*)attr_enum_filter, this->lock, (void*)this->lock->unlock);
+                               (void*)attr_enum_filter, data, attr_enum_destroy);
        }
        return enumerator_create_empty();
 }
@@ -116,8 +143,6 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
                host = host_create_from_string(str, 0);
                if (host)
                {
-                       entry = malloc_thing(attribute_entry_t);
-
                        if (host->get_family(host) == AF_INET6)
                        {
                                switch (type)
@@ -132,8 +157,11 @@ static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
                                                break;
                                }
                        }
-                       entry->type = type;
-                       entry->value = chunk_clone(host->get_address(host));
+                       INIT(entry,
+                               .type = type,
+                               .value = chunk_clone(host->get_address(host)),
+                               .ike = IKE_ANY,
+                       );
                        host->destroy(host);
                        DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B",
                                 configuration_attribute_type_names, entry->type, &entry->value);
@@ -149,19 +177,20 @@ typedef struct {
        char *name;
        configuration_attribute_type_t v4;
        configuration_attribute_type_t v6;
+       ike_version_t ike;
 } attribute_type_key_t;
 
 static attribute_type_key_t keys[] = {
-       {"address",                     INTERNAL_IP4_ADDRESS,   INTERNAL_IP6_ADDRESS},
-       {"dns",                         INTERNAL_IP4_DNS,               INTERNAL_IP6_DNS},
-       {"nbns",                        INTERNAL_IP4_NBNS,              INTERNAL_IP6_NBNS},
-       {"dhcp",                        INTERNAL_IP4_DHCP,              INTERNAL_IP6_DHCP},
-       {"netmask",                     INTERNAL_IP4_NETMASK,   INTERNAL_IP6_NETMASK},
-       {"server",                      INTERNAL_IP4_SERVER,    INTERNAL_IP6_SERVER},
-       {"subnet",                      INTERNAL_IP4_SUBNET,    INTERNAL_IP6_SUBNET},
-       {"p-cscf",                      P_CSCF_IP4_ADDRESS,             P_CSCF_IP6_ADDRESS},
-       {"split-include",       UNITY_SPLIT_INCLUDE,    UNITY_SPLIT_INCLUDE},
-       {"split-exclude",       UNITY_LOCAL_LAN,                UNITY_LOCAL_LAN},
+       {"address",                     INTERNAL_IP4_ADDRESS,   INTERNAL_IP6_ADDRESS,   IKE_ANY},
+       {"dns",                         INTERNAL_IP4_DNS,               INTERNAL_IP6_DNS,               IKE_ANY},
+       {"nbns",                        INTERNAL_IP4_NBNS,              INTERNAL_IP6_NBNS,              IKE_ANY},
+       {"dhcp",                        INTERNAL_IP4_DHCP,              INTERNAL_IP6_DHCP,              IKE_ANY},
+       {"netmask",                     INTERNAL_IP4_NETMASK,   INTERNAL_IP6_NETMASK,   IKE_ANY},
+       {"server",                      INTERNAL_IP4_SERVER,    INTERNAL_IP6_SERVER,    IKE_ANY},
+       {"subnet",                      INTERNAL_IP4_SUBNET,    INTERNAL_IP6_SUBNET,    IKE_ANY},
+       {"p-cscf",                      P_CSCF_IP4_ADDRESS,             P_CSCF_IP6_ADDRESS,             IKEV2},
+       {"split-include",       UNITY_SPLIT_INCLUDE,    UNITY_SPLIT_INCLUDE,    IKEV1},
+       {"split-exclude",       UNITY_LOCAL_LAN,                UNITY_LOCAL_LAN,                IKEV1},
 };
 
 /**
@@ -276,6 +305,7 @@ static void load_entries(private_attr_provider_t *this)
                        INIT(entry,
                                .type = type,
                                .value = data,
+                               .ike = mapped ? mapped->ike : IKE_ANY,
                        );
                        DBG2(DBG_CFG, "loaded attribute %N: %#B",
                                 configuration_attribute_type_names, entry->type, &entry->value);