changed log level
[strongswan.git] / src / charon / config / connections / local_connection_store.c
index 0ae18e0..88a83aa 100644 (file)
@@ -46,6 +46,11 @@ struct private_local_connection_store_t {
        linked_list_t *connections;
        
        /**
+        * Mutex to exclusivly access connection list
+        */
+       pthread_mutex_t mutex;
+       
+       /**
         * Assigned logger
         */
        logger_t *logger;
@@ -57,130 +62,143 @@ struct private_local_connection_store_t {
  */
 static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host)
 {
+       typedef enum {
+               PRIO_UNDEFINED=         0x00,
+               PRIO_ADDR_ANY=          0x01,
+               PRIO_ADDR_MATCH=        0x02
+       } prio_t;
+
+       prio_t best_prio = PRIO_UNDEFINED;
+
        iterator_t *iterator;
-       connection_t *current, *found = NULL;
+       connection_t *candidate;
+       connection_t *found = NULL;
        
-       this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s", 
+       this->logger->log(this->logger, CONTROL|LEVEL1, "looking for connection for host pair %s...%s",
                                          my_host->get_address(my_host), other_host->get_address(other_host));
        
+       pthread_mutex_lock(&(this->mutex));
        iterator = this->connections->create_iterator(this->connections, TRUE);
+       /* determine closest matching connection */
        while (iterator->has_next(iterator))
        {
-               host_t *config_my_host, *config_other_host;
+               host_t *candidate_my_host;
+               host_t *candidate_other_host;
                
-               iterator->current(iterator, (void**)&current);
+               iterator->current(iterator, (void**)&candidate);
 
-               config_my_host = current->get_my_host(current);
-               config_other_host = current->get_other_host(current);
+               candidate_my_host    = candidate->get_my_host(candidate);
+               candidate_other_host = candidate->get_other_host(candidate);
 
-               /* first check if ip is equal */
-               if(config_other_host->ip_equals(config_other_host, other_host))
+               /* my_host addresses must match*/
+               if (my_host->ip_equals(my_host, candidate_my_host))
                {
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s", 
-                                                         config_other_host->get_address(config_other_host));
-                       /* could be right one, check my_host for default route*/
-                       if (config_my_host->is_default_route(config_my_host))
-                       {
-                               found = current->clone(current);
-                               break;
-                       }
-                       /* check now if host informations are the same */
-                       else if (config_my_host->ip_equals(config_my_host,my_host))
+                       prio_t prio = PRIO_UNDEFINED;
+
+                       /* exact match of peer host address or wildcard address? */
+                       if (other_host->ip_equals(other_host, candidate_other_host))
                        {
-                               found = current->clone(current);
-                               break;
+                               prio |= PRIO_ADDR_MATCH;
                        }
-                       
-               }
-               /* Then check for wildcard hosts!
-               * TODO
-               * actually its only checked if other host with default route can be found! */
-               else if (config_other_host->is_default_route(config_other_host))
-               {
-                       /* could be right one, check my_host for default route*/
-                       if (config_my_host->is_default_route(config_my_host))
+                       else if (candidate_other_host->is_anyaddr(candidate_other_host))
                        {
-                               found = current->clone(current);
-                               break;
+                               prio |= PRIO_ADDR_ANY;
                        }
-                       /* check now if host informations are the same */
-                       else if (config_my_host->ip_equals(config_my_host,my_host))
+
+                       this->logger->log(this->logger, CONTROL|LEVEL2,
+                                                        "candidate connection \"%s\": %s...%s (prio=%d)",
+                                                         candidate->get_name(candidate),
+                                                         candidate_my_host->get_address(candidate_my_host),
+                                                         candidate_other_host->get_address(candidate_other_host),
+                                                         prio);
+
+                       if (prio > best_prio)
                        {
-                               found = current->clone(current);
-                               break;
-                       }
+                               found = candidate;
+                               best_prio = prio;
+                       }                       
                }
        }
        iterator->destroy(iterator);
        
-       /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */
        if (found)
        {
-               found->update_my_host(found, my_host->clone(my_host));
-               found->update_other_host(found, other_host->clone(other_host));
+               host_t *found_my_host    = found->get_my_host(found);
+               host_t *found_other_host = found->get_other_host(found);
+               
+               this->logger->log(this->logger, CONTROL,
+                                                "found matching connection \"%s\": %s...%s (prio=%d)",
+                                                 found->get_name(found),
+                                                 found_my_host->get_address(found_my_host),
+                                                 found_other_host->get_address(found_other_host),
+                                                 best_prio);
+
+               found = found->clone(found);
+               if (best_prio & PRIO_ADDR_ANY)
+               {
+                       /* replace %any by the peer's address */
+                       found->update_other_host(found, other_host->clone(other_host));
+               }
        }
-       
+       pthread_mutex_unlock(&(this->mutex));
        return found;
 }
 
 /**
- * Implementation of connection_store_t.get_connection_by_ids.
+ * Implementation of connection_store_t.get_connection_by_name.
  */
-static connection_t *get_connection_by_ids(private_local_connection_store_t *this, identification_t *my_id, identification_t *other_id)
+static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name)
 {
        iterator_t *iterator;
        connection_t *current, *found = NULL;
        
-       this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s", 
-                                         my_id->get_string(my_id), other_id->get_string(other_id));
-       
+       pthread_mutex_lock(&(this->mutex));
        iterator = this->connections->create_iterator(this->connections, TRUE);
        while (iterator->has_next(iterator))
        {
-               identification_t *config_my_id, *config_other_id;
-               
                iterator->current(iterator, (void**)&current);
-               
-               config_my_id = current->get_my_id(current);
-               config_other_id = current->get_other_id(current);
-               
-               /* first check if ids are equal 
-               * TODO: Add wildcard checks */
-               if (config_other_id->equals(config_other_id, other_id) &&
-                       config_my_id->equals(config_my_id, my_id))
+               if (strcmp(name, current->get_name(current)) == 0)
                {
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s", 
-                                                         config_other_id->get_string(config_other_id));
                        found = current->clone(current);
                        break;
                }
        }
        iterator->destroy(iterator);
+       pthread_mutex_unlock(&(this->mutex));
        
        return found;
 }
 
 /**
- * Implementation of connection_store_t.get_connection_by_name.
+ * Implementation of connection_store_t.delete_connection.
  */
-static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name)
+static status_t delete_connection(private_local_connection_store_t *this, char *name)
 {
        iterator_t *iterator;
-       connection_t *current, *found = NULL;
+       connection_t *current;
+       bool found = FALSE;
        
+       pthread_mutex_lock(&(this->mutex));
        iterator = this->connections->create_iterator(this->connections, TRUE);
        while (iterator->has_next(iterator))
        {
-               iterator->current(iterator, (void**)&current);
-               if (strcmp(name, current->get_name(current)) == 0)
+               iterator->current(iterator, (void **)&current);
+               if (strcmp(current->get_name(current), name) == 0)
                {
-                       found = current->clone(current);
+                       /* remove connection from list, and destroy it */
+                       iterator->remove(iterator);
+                       current->destroy(current);
+                       found = TRUE;
                        break;
                }
        }
        iterator->destroy(iterator);
-       
-       return found;
+       pthread_mutex_unlock(&(this->mutex));
+       if (found)
+       {
+               return SUCCESS;
+       }
+       return NOT_FOUND;
 }
 
 /**
@@ -188,22 +206,60 @@ static connection_t *get_connection_by_name(private_local_connection_store_t *th
  */
 static status_t add_connection(private_local_connection_store_t *this, connection_t *connection)
 {
+       pthread_mutex_lock(&(this->mutex));
        this->connections->insert_last(this->connections, connection);
+       pthread_mutex_unlock(&(this->mutex));
        return SUCCESS;
 }
 
 /**
+ * Implementation of connection_store_t.log_connections.
+ */
+void log_connections(private_local_connection_store_t *this, logger_t *logger, char *name)
+{
+       iterator_t *iterator;
+       connection_t *current, *found = NULL;
+       
+       if (logger == NULL)
+       {
+               logger = this->logger;
+       }
+       
+       logger->log(logger, CONTROL, "templates:");
+       
+       pthread_mutex_lock(&(this->mutex));
+       iterator = this->connections->create_iterator(this->connections, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               iterator->current(iterator, (void**)&current);
+               if (!name || strcmp(name, current->get_name(current)) == 0)
+               {
+                       host_t *my_host, *other_host;
+                       my_host = current->get_my_host(current);
+                       other_host = current->get_other_host(current);
+                       logger->log(logger, CONTROL, "  \"%s\": %s...%s",
+                                               current->get_name(current),
+                                               my_host->get_address(my_host), other_host->get_address(other_host));
+               }
+       }
+       iterator->destroy(iterator);
+       pthread_mutex_unlock(&(this->mutex));
+}
+
+/**
  * Implementation of connection_store_t.destroy.
  */
 static void destroy (private_local_connection_store_t *this)
 {
        connection_t *connection;
        
+       pthread_mutex_lock(&(this->mutex));
        while (this->connections->remove_last(this->connections, (void**)&connection) == SUCCESS)
        {
                connection->destroy(connection);
        }
        this->connections->destroy(this->connections);
+       pthread_mutex_unlock(&(this->mutex));
        free(this);
 }
 
@@ -215,14 +271,16 @@ local_connection_store_t * local_connection_store_create(void)
        private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t);
 
        this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts;
-       this->public.connection_store.get_connection_by_ids = (connection_t*(*)(connection_store_t*,identification_t*,identification_t*))get_connection_by_ids;
        this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name;
+       this->public.connection_store.delete_connection = (status_t(*)(connection_store_t*,char*))delete_connection;
        this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection;
+       this->public.connection_store.log_connections = (void(*)(connection_store_t*,logger_t*,char*))log_connections;
        this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy;
        
        /* private variables */
        this->connections = linked_list_create();
        this->logger = logger_manager->get_logger(logger_manager, CONFIG);
+       pthread_mutex_init(&(this->mutex), NULL);
 
        return (&this->public);
 }