add priority management for kernel policy
let ROUTED policies installed, until manuall removed introduced new naming scheme to allow proper shutdown of IKE/CHILD_SAs ike_sa_manager cleanups
This commit is contained in:
@@ -52,7 +52,7 @@ enum dpd_action_t {
|
|||||||
/**
|
/**
|
||||||
* String mappings for dpd_action_t
|
* String mappings for dpd_action_t
|
||||||
*/
|
*/
|
||||||
mapping_t dpd_action_m[];
|
extern mapping_t dpd_action_m[];
|
||||||
|
|
||||||
|
|
||||||
typedef struct policy_t policy_t;
|
typedef struct policy_t policy_t;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "traffic_selector.h"
|
#include "traffic_selector.h"
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,9 @@ static status_t execute(private_incoming_packet_job_t *this)
|
|||||||
ike_sa_id->get_responder_spi(ike_sa_id));
|
ike_sa_id->get_responder_spi(ike_sa_id));
|
||||||
if (message->get_request(message))
|
if (message->get_request(message))
|
||||||
{
|
{
|
||||||
send_notify_response(this, message, INVALID_IKE_SPI);
|
/* TODO: send notify if we have NULL crypters,
|
||||||
|
* see todo in send_notify_response
|
||||||
|
send_notify_response(this, message, INVALID_IKE_SPI); */
|
||||||
}
|
}
|
||||||
ike_sa_id->destroy(ike_sa_id);
|
ike_sa_id->destroy(ike_sa_id);
|
||||||
message->destroy(message);
|
message->destroy(message);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "child_sa.h"
|
#include "child_sa.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
@@ -182,8 +183,14 @@ static char *get_name(private_child_sa_t *this)
|
|||||||
*/
|
*/
|
||||||
static void set_name(private_child_sa_t *this, char* name)
|
static void set_name(private_child_sa_t *this, char* name)
|
||||||
{
|
{
|
||||||
free(this->name);
|
char buffer[64];
|
||||||
this->name = strdup(name);
|
|
||||||
|
if (snprintf(buffer, sizeof(buffer), "%s[%d]",
|
||||||
|
name, this->reqid - REQID_START) > 0)
|
||||||
|
{
|
||||||
|
free(this->name);
|
||||||
|
this->name = strdup(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -468,6 +475,8 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
|
|||||||
{
|
{
|
||||||
iterator_t *my_iter, *other_iter;
|
iterator_t *my_iter, *other_iter;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
|
/* use low prio for ROUTED policies */
|
||||||
|
bool high_prio = (this->state != CHILD_CREATED);
|
||||||
|
|
||||||
/* iterate over both lists */
|
/* iterate over both lists */
|
||||||
my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
|
my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
|
||||||
@@ -503,15 +512,15 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
|
|||||||
/* install 3 policies: out, in and forward */
|
/* install 3 policies: out, in and forward */
|
||||||
status = charon->kernel_interface->add_policy(charon->kernel_interface,
|
status = charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||||
this->me.addr, this->other.addr, my_ts, other_ts,
|
this->me.addr, this->other.addr, my_ts, other_ts,
|
||||||
POLICY_OUT, this->protocol, this->reqid, FALSE);
|
POLICY_OUT, this->protocol, this->reqid, high_prio, FALSE);
|
||||||
|
|
||||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||||
this->other.addr, this->me.addr, other_ts, my_ts,
|
this->other.addr, this->me.addr, other_ts, my_ts,
|
||||||
POLICY_IN, this->protocol, this->reqid, FALSE);
|
POLICY_IN, this->protocol, this->reqid, high_prio, FALSE);
|
||||||
|
|
||||||
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
|
||||||
this->other.addr, this->me.addr, other_ts, my_ts,
|
this->other.addr, this->me.addr, other_ts, my_ts,
|
||||||
POLICY_FWD, this->protocol, this->reqid, FALSE);
|
POLICY_FWD, this->protocol, this->reqid, high_prio, FALSE);
|
||||||
|
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -805,6 +814,7 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
|
|||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
sa_policy_t *policy;
|
sa_policy_t *policy;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
/* we always use high priorities, as hosts getting updated are INSTALLED */
|
||||||
|
|
||||||
iterator = this->policies->create_iterator(this->policies, TRUE);
|
iterator = this->policies->create_iterator(this->policies, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&policy))
|
while (iterator->iterate(iterator, (void**)&policy))
|
||||||
@@ -813,19 +823,19 @@ static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, ho
|
|||||||
charon->kernel_interface,
|
charon->kernel_interface,
|
||||||
new_me, new_other,
|
new_me, new_other,
|
||||||
policy->my_ts, policy->other_ts,
|
policy->my_ts, policy->other_ts,
|
||||||
POLICY_OUT, this->protocol, this->reqid, TRUE);
|
POLICY_OUT, this->protocol, this->reqid, TRUE, TRUE);
|
||||||
|
|
||||||
status |= charon->kernel_interface->add_policy(
|
status |= charon->kernel_interface->add_policy(
|
||||||
charon->kernel_interface,
|
charon->kernel_interface,
|
||||||
new_other, new_me,
|
new_other, new_me,
|
||||||
policy->other_ts, policy->my_ts,
|
policy->other_ts, policy->my_ts,
|
||||||
POLICY_IN, this->protocol, this->reqid, TRUE);
|
POLICY_IN, this->protocol, this->reqid, TRUE, TRUE);
|
||||||
|
|
||||||
status |= charon->kernel_interface->add_policy(
|
status |= charon->kernel_interface->add_policy(
|
||||||
charon->kernel_interface,
|
charon->kernel_interface,
|
||||||
new_other, new_me,
|
new_other, new_me,
|
||||||
policy->other_ts, policy->my_ts,
|
policy->other_ts, policy->my_ts,
|
||||||
POLICY_FWD, this->protocol, this->reqid, TRUE);
|
POLICY_FWD, this->protocol, this->reqid, TRUE, TRUE);
|
||||||
|
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
|
|||||||
+20
-19
@@ -920,8 +920,6 @@ static status_t initiate(private_ike_sa_t *this,
|
|||||||
|
|
||||||
this->logger->log(this->logger, CONTROL,
|
this->logger->log(this->logger, CONTROL,
|
||||||
"initiating IKE_SA");
|
"initiating IKE_SA");
|
||||||
|
|
||||||
set_name(this, connection->get_name(connection));
|
|
||||||
DESTROY_IF(this->my_host);
|
DESTROY_IF(this->my_host);
|
||||||
this->my_host = connection->get_my_host(connection);
|
this->my_host = connection->get_my_host(connection);
|
||||||
this->my_host = this->my_host->clone(this->my_host);
|
this->my_host = this->my_host->clone(this->my_host);
|
||||||
@@ -1130,27 +1128,30 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
|
|||||||
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
|
||||||
while (iterator->iterate(iterator, (void**)&child_sa))
|
while (iterator->iterate(iterator, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
linked_list_t *my_ts_conf, *other_ts_conf;
|
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
|
||||||
|
|
||||||
my_ts = child_sa->get_my_traffic_selectors(child_sa);
|
|
||||||
other_ts = child_sa->get_other_traffic_selectors(child_sa);
|
|
||||||
|
|
||||||
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
|
|
||||||
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
|
|
||||||
|
|
||||||
if (ts_list_equals(my_ts, my_ts_conf) &&
|
|
||||||
ts_list_equals(other_ts, other_ts_conf))
|
|
||||||
{
|
{
|
||||||
|
linked_list_t *my_ts_conf, *other_ts_conf;
|
||||||
|
|
||||||
|
my_ts = child_sa->get_my_traffic_selectors(child_sa);
|
||||||
|
other_ts = child_sa->get_other_traffic_selectors(child_sa);
|
||||||
|
|
||||||
|
my_ts_conf = policy->get_my_traffic_selectors(policy, this->my_host);
|
||||||
|
other_ts_conf = policy->get_other_traffic_selectors(policy, this->other_host);
|
||||||
|
|
||||||
|
if (ts_list_equals(my_ts, my_ts_conf) &&
|
||||||
|
ts_list_equals(other_ts, other_ts_conf))
|
||||||
|
{
|
||||||
|
ts_list_destroy(my_ts_conf);
|
||||||
|
ts_list_destroy(other_ts_conf);
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
this->logger->log(this->logger, CONTROL,
|
||||||
|
"a CHILD_SA with such a policy already routed");
|
||||||
|
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
ts_list_destroy(my_ts_conf);
|
ts_list_destroy(my_ts_conf);
|
||||||
ts_list_destroy(other_ts_conf);
|
ts_list_destroy(other_ts_conf);
|
||||||
iterator->destroy(iterator);
|
|
||||||
this->logger->log(this->logger, CONTROL,
|
|
||||||
"a CHILD_SA with such a policy already routed");
|
|
||||||
|
|
||||||
return FAILED;
|
|
||||||
}
|
}
|
||||||
ts_list_destroy(my_ts_conf);
|
|
||||||
ts_list_destroy(other_ts_conf);
|
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
|
|||||||
+147
-126
@@ -134,58 +134,7 @@ struct private_ike_sa_manager_t {
|
|||||||
* Public interface of ike_sa_manager_t.
|
* Public interface of ike_sa_manager_t.
|
||||||
*/
|
*/
|
||||||
ike_sa_manager_t public;
|
ike_sa_manager_t public;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get next spi.
|
|
||||||
*
|
|
||||||
* We give out SPIs from a pseudo random source
|
|
||||||
*
|
|
||||||
* @param this the ike_sa_manager
|
|
||||||
* @return the next spi
|
|
||||||
*/
|
|
||||||
u_int64_t (*get_next_spi) (private_ike_sa_manager_t *this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Find the ike_sa_entry_t object in the list by SPIs.
|
|
||||||
*
|
|
||||||
* This function simply iterates over the linked list. A hash-table
|
|
||||||
* would be more efficient when storing a lot of IKE_SAs...
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
* @param ike_sa_id id of the ike_sa, containing SPIs
|
|
||||||
* @param[out] entry pointer to set to the found entry
|
|
||||||
* @return
|
|
||||||
* - SUCCESS when found,
|
|
||||||
* - NOT_FOUND when no such ike_sa_id in list
|
|
||||||
*/
|
|
||||||
status_t (*get_entry_by_id) (private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Find the ike_sa_entry_t in the list by pointer to SA.
|
|
||||||
*
|
|
||||||
* This function simply iterates over the linked list. A hash-table
|
|
||||||
* would be more efficient when storing a lot of IKE_SAs...
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
* @param ike_sa pointer to the ike_sa
|
|
||||||
* @param[out] entry pointer to set to the found entry
|
|
||||||
* @return
|
|
||||||
* - SUCCESS when found,
|
|
||||||
* - NOT_FOUND when no such ike_sa_id in list
|
|
||||||
*/
|
|
||||||
status_t (*get_entry_by_sa) (private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete an entry from the linked list.
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
* @param entry entry to delete
|
|
||||||
* @return
|
|
||||||
* - SUCCESS when found,
|
|
||||||
* - NOT_FOUND when no such ike_sa_id in list
|
|
||||||
*/
|
|
||||||
status_t (*delete_entry) (private_ike_sa_manager_t *this, ike_sa_entry_t *entry);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock for exclusivly accessing the manager.
|
* Lock for exclusivly accessing the manager.
|
||||||
*/
|
*/
|
||||||
@@ -321,6 +270,17 @@ static status_t delete_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *ent
|
|||||||
iterator->current(iterator, (void**)¤t);
|
iterator->current(iterator, (void**)¤t);
|
||||||
if (current == entry)
|
if (current == entry)
|
||||||
{
|
{
|
||||||
|
/* mark it, so now new threads can get this entry */
|
||||||
|
entry->driveout_new_threads = TRUE;
|
||||||
|
/* wait until all workers have done their work */
|
||||||
|
while (entry->waiting_threads)
|
||||||
|
{
|
||||||
|
/* wake up all */
|
||||||
|
pthread_cond_broadcast(&(entry->condvar));
|
||||||
|
/* they will wake us again when their work is done */
|
||||||
|
pthread_cond_wait(&(entry->condvar), &(this->mutex));
|
||||||
|
}
|
||||||
|
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL2,
|
this->logger->log(this->logger, CONTROL|LEVEL2,
|
||||||
"found entry by pointer. Going to delete it");
|
"found entry by pointer. Going to delete it");
|
||||||
iterator->remove(iterator);
|
iterator->remove(iterator);
|
||||||
@@ -440,7 +400,7 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this,
|
|||||||
ike_sa_entry_t *new_ike_sa_entry;
|
ike_sa_entry_t *new_ike_sa_entry;
|
||||||
ike_sa_id_t *new_ike_sa_id;
|
ike_sa_id_t *new_ike_sa_id;
|
||||||
|
|
||||||
initiator_spi = this->get_next_spi(this);
|
initiator_spi = get_next_spi(this);
|
||||||
new_ike_sa_id = ike_sa_id_create(0, 0, TRUE);
|
new_ike_sa_id = ike_sa_id_create(0, 0, TRUE);
|
||||||
new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi);
|
new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi);
|
||||||
|
|
||||||
@@ -501,7 +461,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
|
|||||||
*/
|
*/
|
||||||
ike_sa_entry_t *entry;
|
ike_sa_entry_t *entry;
|
||||||
/* look for the entry */
|
/* look for the entry */
|
||||||
if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
||||||
{
|
{
|
||||||
if (wait_for_entry(this, entry))
|
if (wait_for_entry(this, entry))
|
||||||
{
|
{
|
||||||
@@ -537,7 +497,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
|
|||||||
ike_sa_entry_t *new_ike_sa_entry;
|
ike_sa_entry_t *new_ike_sa_entry;
|
||||||
|
|
||||||
/* set SPIs, we are the responder */
|
/* set SPIs, we are the responder */
|
||||||
responder_spi = this->get_next_spi(this);
|
responder_spi = get_next_spi(this);
|
||||||
|
|
||||||
/* we also set arguments spi, so its still valid */
|
/* we also set arguments spi, so its still valid */
|
||||||
ike_sa_id->set_responder_spi(ike_sa_id, responder_spi);
|
ike_sa_id->set_responder_spi(ike_sa_id, responder_spi);
|
||||||
@@ -558,7 +518,7 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
|
|||||||
/* checkout of a new and unused IKE_SA, used for rekeying */
|
/* checkout of a new and unused IKE_SA, used for rekeying */
|
||||||
ike_sa_entry_t *new_ike_sa_entry;
|
ike_sa_entry_t *new_ike_sa_entry;
|
||||||
|
|
||||||
ike_sa_id->set_initiator_spi(ike_sa_id, this->get_next_spi(this));
|
ike_sa_id->set_initiator_spi(ike_sa_id, get_next_spi(this));
|
||||||
/* create entry */
|
/* create entry */
|
||||||
new_ike_sa_entry = ike_sa_entry_create(ike_sa_id);
|
new_ike_sa_entry = ike_sa_entry_create(ike_sa_id);
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL2,
|
this->logger->log(this->logger, CONTROL|LEVEL2,
|
||||||
@@ -621,7 +581,7 @@ static ike_sa_t* checkout_by_child(private_ike_sa_manager_t *this,
|
|||||||
/**
|
/**
|
||||||
* Implementation of ike_sa_manager_t.get_ike_sa_list.
|
* Implementation of ike_sa_manager_t.get_ike_sa_list.
|
||||||
*/
|
*/
|
||||||
linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this)
|
static linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this)
|
||||||
{
|
{
|
||||||
linked_list_t *list;
|
linked_list_t *list;
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
@@ -642,32 +602,6 @@ linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of ike_sa_manager_t.get_ike_sa_list_by_name.
|
|
||||||
*/
|
|
||||||
linked_list_t *get_ike_sa_list_by_name(private_ike_sa_manager_t* this, const char *name)
|
|
||||||
{
|
|
||||||
linked_list_t *list;
|
|
||||||
iterator_t *iterator;
|
|
||||||
ike_sa_entry_t *entry;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
|
||||||
|
|
||||||
list = linked_list_create();
|
|
||||||
iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
|
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
|
||||||
if (strcmp(name, entry->ike_sa->get_name(entry->ike_sa)) == 0)
|
|
||||||
{
|
|
||||||
list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ike_sa_manager_t.log_status.
|
* Implementation of ike_sa_manager_t.log_status.
|
||||||
*/
|
*/
|
||||||
@@ -724,7 +658,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
|
|||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
|
||||||
/* look for the entry */
|
/* look for the entry */
|
||||||
if (this->get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
|
if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
|
||||||
{
|
{
|
||||||
/* ike_sa_id must be updated */
|
/* ike_sa_id must be updated */
|
||||||
entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
|
entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
|
||||||
@@ -772,23 +706,13 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
|
|||||||
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
|
||||||
if (this->get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
|
if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
|
||||||
{
|
{
|
||||||
/* mark it, so now new threads can acquire this SA */
|
/* drive out waiting threads, as we are in hurry */
|
||||||
entry->driveout_new_threads = TRUE;
|
|
||||||
/* additionaly, drive out waiting threads */
|
|
||||||
entry->driveout_waiting_threads = TRUE;
|
entry->driveout_waiting_threads = TRUE;
|
||||||
|
|
||||||
/* wait until all workers have done their work */
|
delete_entry(this, entry);
|
||||||
while (entry->waiting_threads)
|
|
||||||
{
|
|
||||||
/* let the other threads leave the manager */
|
|
||||||
pthread_cond_broadcast(&(entry->condvar));
|
|
||||||
/* and the nice thing, they will wake us again when their work is done */
|
|
||||||
pthread_cond_wait(&(entry->condvar), &(this->mutex));
|
|
||||||
}
|
|
||||||
/* ok, we are alone now, no threads waiting in the entry's condvar */
|
|
||||||
this->delete_entry(this, entry);
|
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL1,
|
this->logger->log(this->logger, CONTROL|LEVEL1,
|
||||||
"check-in and destroy of IKE_SA successful");
|
"check-in and destroy of IKE_SA successful");
|
||||||
retval = SUCCESS;
|
retval = SUCCESS;
|
||||||
@@ -825,7 +749,7 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
|
|||||||
|
|
||||||
pthread_mutex_lock(&(this->mutex));
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
|
||||||
if (this->get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
|
||||||
{
|
{
|
||||||
/* we try a delete. If it succeeds, our job is done here. The
|
/* we try a delete. If it succeeds, our job is done here. The
|
||||||
* other peer will reply, and the IKE SA gets the finally deleted...
|
* other peer will reply, and the IKE SA gets the finally deleted...
|
||||||
@@ -837,25 +761,10 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
|
|||||||
}
|
}
|
||||||
/* but if the IKE SA is not in a state where the deletion is
|
/* but if the IKE SA is not in a state where the deletion is
|
||||||
* negotiated with the other peer, we can destroy the IKE SA on our own.
|
* negotiated with the other peer, we can destroy the IKE SA on our own.
|
||||||
* For this, we must be sure that really NO other threads are
|
|
||||||
* waiting for this SA...
|
|
||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* mark it, so now new threads can acquire this SA */
|
|
||||||
entry->driveout_new_threads = TRUE;
|
|
||||||
/* wait until all workers have done their work */
|
|
||||||
while (entry->waiting_threads)
|
|
||||||
{
|
|
||||||
/* wake up all */
|
|
||||||
pthread_cond_broadcast(&(entry->condvar));
|
|
||||||
/* and the nice thing, they will wake us again when their work
|
|
||||||
* is done */
|
|
||||||
pthread_cond_wait(&(entry->condvar), &(this->mutex));
|
|
||||||
}
|
|
||||||
/* ok, we are alone now, no threads waiting in the entry's condvar */
|
|
||||||
this->delete_entry(this, entry);
|
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL1, "destroyed IKE_SA");
|
|
||||||
}
|
}
|
||||||
retval = SUCCESS;
|
retval = SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -870,6 +779,125 @@ static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_sa_manager_t.delete_by_name.
|
||||||
|
*/
|
||||||
|
static status_t delete_by_name(private_ike_sa_manager_t *this, char *name)
|
||||||
|
{
|
||||||
|
iterator_t *iterator;
|
||||||
|
iterator_t *child_iter;
|
||||||
|
ike_sa_entry_t *entry;
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(this->mutex));
|
||||||
|
|
||||||
|
iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
|
||||||
|
while (iterator->iterate(iterator, (void**)&entry))
|
||||||
|
{
|
||||||
|
if (wait_for_entry(this, entry))
|
||||||
|
{
|
||||||
|
/* delete ike_sa if:
|
||||||
|
* name{x} matches completely
|
||||||
|
* name{} matches by name
|
||||||
|
* name matches by name
|
||||||
|
*/
|
||||||
|
bool del = FALSE;
|
||||||
|
char *ike_name;
|
||||||
|
char *child_name;
|
||||||
|
child_sa_t *child_sa;
|
||||||
|
|
||||||
|
ike_name = entry->ike_sa->get_name(entry->ike_sa);
|
||||||
|
/* check if "name{x}" matches completely */
|
||||||
|
if (strcmp(name, ike_name) == 0)
|
||||||
|
{
|
||||||
|
del = TRUE;
|
||||||
|
}
|
||||||
|
/* check if name is in form of "name{}" and matches to ike_name */
|
||||||
|
else if (name_len > 1 &&
|
||||||
|
name[name_len - 2] == '{' && name[name_len - 1] == '}' &&
|
||||||
|
strlen(ike_name) > name_len &&
|
||||||
|
ike_name[name_len - 2] == '{' &&
|
||||||
|
strncmp(name, ike_name, name_len - 2) == 0)
|
||||||
|
{
|
||||||
|
del = TRUE;
|
||||||
|
}
|
||||||
|
/* finally, check if name is "name" and matches ike_name */
|
||||||
|
else if (name_len == strchr(ike_name, '{') - ike_name &&
|
||||||
|
strncmp(name, ike_name, name_len) == 0)
|
||||||
|
{
|
||||||
|
del = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (del)
|
||||||
|
{
|
||||||
|
if (entry->ike_sa->delete(entry->ike_sa) == DESTROY_ME)
|
||||||
|
{
|
||||||
|
delete_entry(this, entry);
|
||||||
|
iterator->reset(iterator);
|
||||||
|
}
|
||||||
|
/* no need to check children, as we delete all */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* and now the same game for all children. delete child_sa if:
|
||||||
|
* name[x] matches completely
|
||||||
|
* name[] matches by name
|
||||||
|
* name matches by name
|
||||||
|
*/
|
||||||
|
child_iter = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
|
||||||
|
while (child_iter->iterate(child_iter, (void**)&child_sa))
|
||||||
|
{
|
||||||
|
/* skip ROUTED children, they have their "unroute" command */
|
||||||
|
if (child_sa->get_state(child_sa) == CHILD_ROUTED)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
child_name = child_sa->get_name(child_sa);
|
||||||
|
del = FALSE;
|
||||||
|
/* check if "name[x]" matches completely */
|
||||||
|
if (strcmp(name, child_name) == 0)
|
||||||
|
{
|
||||||
|
del = TRUE;
|
||||||
|
}
|
||||||
|
/* check if name is in form of "name[]" and matches to child_name */
|
||||||
|
else if (name_len > 1 &&
|
||||||
|
name[name_len - 2] == '[' && name[name_len - 1] == ']' &&
|
||||||
|
strlen(child_name) > name_len &&
|
||||||
|
child_name[name_len - 2] == '[' &&
|
||||||
|
strncmp(name, child_name, name_len - 2) == 0)
|
||||||
|
{
|
||||||
|
del = TRUE;
|
||||||
|
}
|
||||||
|
/* finally, check if name is "name" and matches child_name */
|
||||||
|
else if (name_len == strchr(child_name, '[') - child_name &&
|
||||||
|
strncmp(name, child_name, name_len) == 0)
|
||||||
|
{
|
||||||
|
del = TRUE;
|
||||||
|
}
|
||||||
|
if (del)
|
||||||
|
{
|
||||||
|
if (entry->ike_sa->delete_child_sa(entry->ike_sa,
|
||||||
|
child_sa->get_protocol(child_sa),
|
||||||
|
child_sa->get_spi(child_sa, TRUE)) == DESTROY_ME)
|
||||||
|
{
|
||||||
|
/* when a fatal error occurs, we are responsible to
|
||||||
|
* remove the IKE_SA */
|
||||||
|
delete_entry(this, entry);
|
||||||
|
iterator->reset(iterator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child_iter->destroy(child_iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
pthread_mutex_unlock(&(this->mutex));
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ike_sa_manager_t.destroy.
|
* Implementation of ike_sa_manager_t.destroy.
|
||||||
*/
|
*/
|
||||||
@@ -921,10 +949,9 @@ static void destroy(private_ike_sa_manager_t *this)
|
|||||||
|
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL2, "destroy all entries");
|
this->logger->log(this->logger, CONTROL|LEVEL2, "destroy all entries");
|
||||||
/* Step 4: destroy all entries */
|
/* Step 4: destroy all entries */
|
||||||
while (list->get_count(list) > 0)
|
while (list->remove_last(list, (void**)&entry) == SUCCESS)
|
||||||
{
|
{
|
||||||
list->get_first(list, (void**)&entry);
|
entry->destroy(entry);
|
||||||
this->delete_entry(this, entry);
|
|
||||||
}
|
}
|
||||||
list->destroy(list);
|
list->destroy(list);
|
||||||
pthread_mutex_unlock(&(this->mutex));
|
pthread_mutex_unlock(&(this->mutex));
|
||||||
@@ -947,18 +974,12 @@ ike_sa_manager_t *ike_sa_manager_create()
|
|||||||
this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
|
this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
|
||||||
this->public.checkout_by_child = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t))checkout_by_child;
|
this->public.checkout_by_child = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t))checkout_by_child;
|
||||||
this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
|
this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
|
||||||
this->public.get_ike_sa_list_by_name = (linked_list_t*(*)(ike_sa_manager_t*,const char*))get_ike_sa_list_by_name;
|
|
||||||
this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status;
|
this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status;
|
||||||
this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
|
this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
|
||||||
this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete_;
|
this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete_;
|
||||||
|
this->public.delete_by_name = (status_t(*)(ike_sa_manager_t*,char*))delete_by_name;
|
||||||
this->public.checkin_and_destroy = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
|
this->public.checkin_and_destroy = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
|
||||||
|
|
||||||
/* initialize private functions */
|
|
||||||
this->get_next_spi = get_next_spi;
|
|
||||||
this->get_entry_by_sa = get_entry_by_sa;
|
|
||||||
this->get_entry_by_id = get_entry_by_id;
|
|
||||||
this->delete_entry = delete_entry;
|
|
||||||
|
|
||||||
/* initialize private variables */
|
/* initialize private variables */
|
||||||
this->logger = logger_manager->get_logger(logger_manager, IKE_SA_MANAGER);
|
this->logger = logger_manager->get_logger(logger_manager, IKE_SA_MANAGER);
|
||||||
|
|
||||||
|
|||||||
@@ -116,15 +116,6 @@ struct ike_sa_manager_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *(*get_ike_sa_list) (ike_sa_manager_t* this);
|
linked_list_t *(*get_ike_sa_list) (ike_sa_manager_t* this);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get a list of all IKE_SA SAs currently set up specified
|
|
||||||
* by the connections name.
|
|
||||||
*
|
|
||||||
* @param this the manager object
|
|
||||||
* @return a list with ike_sa_id_t s
|
|
||||||
*/
|
|
||||||
linked_list_t *(*get_ike_sa_list_by_name) (ike_sa_manager_t* this, const char *name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log the status of the IKE_SA's in the manager.
|
* @brief Log the status of the IKE_SA's in the manager.
|
||||||
*
|
*
|
||||||
@@ -171,6 +162,29 @@ struct ike_sa_manager_t {
|
|||||||
*/
|
*/
|
||||||
status_t (*delete) (ike_sa_manager_t* this, ike_sa_id_t *ike_sa_id);
|
status_t (*delete) (ike_sa_manager_t* this, ike_sa_id_t *ike_sa_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete a SA identified by its name, which was not checked out.
|
||||||
|
*
|
||||||
|
* Using delete_by_name allows the delete of IKE_SAs and CHILD_SAs.
|
||||||
|
* The supplied name may have one of the following format:
|
||||||
|
*
|
||||||
|
* name{x} => delete IKE_SA with "name" and unique id "x"
|
||||||
|
* name{} => delete all IKE_SAs with "name"
|
||||||
|
* name[x] => delete CHILD_SA with "name" and unique id "x"
|
||||||
|
* name[] => delete all CHILD_SAs with "name"
|
||||||
|
* name => delete all CHILD_SAs or IKE_SAs with "name"
|
||||||
|
*
|
||||||
|
* @warning do not use this when the SA is already checked out, this will
|
||||||
|
* deadlock!
|
||||||
|
*
|
||||||
|
* @param this the manager object
|
||||||
|
* @param name name in one of the format described above
|
||||||
|
* @returns
|
||||||
|
* - SUCCESS if found
|
||||||
|
* - NOT_FOUND when no such SA is available
|
||||||
|
*/
|
||||||
|
status_t (*delete_by_name) (ike_sa_manager_t* this, char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy a checked out SA.
|
* @brief Destroy a checked out SA.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ struct private_ike_sa_init_t {
|
|||||||
*/
|
*/
|
||||||
u_int32_t reqid;
|
u_int32_t reqid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique ID for to enumerate all IKE_SAs in its name
|
||||||
|
*/
|
||||||
|
u_int32_t unique_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Randomizer to generate nonces
|
* Randomizer to generate nonces
|
||||||
*/
|
*/
|
||||||
@@ -281,6 +286,7 @@ static status_t get_request(private_ike_sa_init_t *this, message_t **result)
|
|||||||
message_t *request;
|
message_t *request;
|
||||||
host_t *me, *other;
|
host_t *me, *other;
|
||||||
identification_t *my_id, *other_id;
|
identification_t *my_id, *other_id;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
/* check if we already have built a message (retransmission) */
|
/* check if we already have built a message (retransmission) */
|
||||||
if (this->message)
|
if (this->message)
|
||||||
@@ -298,6 +304,12 @@ static status_t get_request(private_ike_sa_init_t *this, message_t **result)
|
|||||||
other_id = this->policy->get_other_id(this->policy);
|
other_id = this->policy->get_other_id(this->policy);
|
||||||
this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
|
this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
|
||||||
this->ike_sa->set_other_id(this->ike_sa, other_id->clone(other_id));
|
this->ike_sa->set_other_id(this->ike_sa, other_id->clone(other_id));
|
||||||
|
if (snprintf(name, sizeof(name), "%s{%d}",
|
||||||
|
this->connection->get_name(this->connection),
|
||||||
|
this->unique_id) > 0)
|
||||||
|
{
|
||||||
|
this->ike_sa->set_name(this->ike_sa, name);
|
||||||
|
}
|
||||||
|
|
||||||
/* build the request */
|
/* build the request */
|
||||||
request = message_create();
|
request = message_create();
|
||||||
@@ -516,6 +528,7 @@ static status_t get_response(private_ike_sa_init_t *this,
|
|||||||
nonce_payload_t *nonce_request = NULL;
|
nonce_payload_t *nonce_request = NULL;
|
||||||
ike_sa_id_t *ike_sa_id;
|
ike_sa_id_t *ike_sa_id;
|
||||||
u_int32_t timeout;
|
u_int32_t timeout;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
/* check if we already have built a response (retransmission) */
|
/* check if we already have built a response (retransmission) */
|
||||||
if (this->message)
|
if (this->message)
|
||||||
@@ -561,8 +574,13 @@ static status_t get_response(private_ike_sa_init_t *this,
|
|||||||
me->get_string(me), other->get_string(other));
|
me->get_string(me), other->get_string(other));
|
||||||
return DESTROY_ME;
|
return DESTROY_ME;
|
||||||
}
|
}
|
||||||
this->ike_sa->set_name(this->ike_sa,
|
|
||||||
this->connection->get_name(this->connection));
|
if (snprintf(name, sizeof(name), "%s{%d}",
|
||||||
|
this->connection->get_name(this->connection),
|
||||||
|
this->unique_id) > 0)
|
||||||
|
{
|
||||||
|
this->ike_sa->set_name(this->ike_sa, name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Precompute NAT-D hashes for incoming NAT notify comparison */
|
/* Precompute NAT-D hashes for incoming NAT notify comparison */
|
||||||
ike_sa_id = request->get_ike_sa_id(request);
|
ike_sa_id = request->get_ike_sa_id(request);
|
||||||
@@ -1077,6 +1095,7 @@ static void destroy(private_ike_sa_init_t *this)
|
|||||||
*/
|
*/
|
||||||
ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
|
ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
|
||||||
{
|
{
|
||||||
|
static u_int unique_id = 0;
|
||||||
private_ike_sa_init_t *this = malloc_thing(private_ike_sa_init_t);
|
private_ike_sa_init_t *this = malloc_thing(private_ike_sa_init_t);
|
||||||
|
|
||||||
/* transaction interface functions */
|
/* transaction interface functions */
|
||||||
@@ -1103,6 +1122,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
|
|||||||
this->connection = NULL;
|
this->connection = NULL;
|
||||||
this->policy = NULL;
|
this->policy = NULL;
|
||||||
this->proposal = NULL;
|
this->proposal = NULL;
|
||||||
|
this->unique_id = ++unique_id;
|
||||||
this->reqid = 0;
|
this->reqid = 0;
|
||||||
this->randomizer = randomizer_create();
|
this->randomizer = randomizer_create();
|
||||||
this->nat_hasher = hasher_create(HASH_SHA1);
|
this->nat_hasher = hasher_create(HASH_SHA1);
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ static status_t switchto_new_sa(private_rekey_ike_sa_t* this, bool initiator)
|
|||||||
other_id = this->ike_sa->get_other_id(this->ike_sa);
|
other_id = this->ike_sa->get_other_id(this->ike_sa);
|
||||||
my_host = this->ike_sa->get_my_host(this->ike_sa);
|
my_host = this->ike_sa->get_my_host(this->ike_sa);
|
||||||
other_host = this->ike_sa->get_other_host(this->ike_sa);
|
other_host = this->ike_sa->get_other_host(this->ike_sa);
|
||||||
name = this->connection->get_name(this->connection);
|
name = this->ike_sa->get_name(this->ike_sa);
|
||||||
|
|
||||||
this->new_sa->set_my_id(this->new_sa, my_id->clone(my_id));
|
this->new_sa->set_my_id(this->new_sa, my_id->clone(my_id));
|
||||||
this->new_sa->set_other_id(this->new_sa, other_id->clone(other_id));
|
this->new_sa->set_other_id(this->new_sa, other_id->clone(other_id));
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
#define KERNEL_AH 51
|
#define KERNEL_AH 51
|
||||||
|
|
||||||
/** default priority of installed policies */
|
/** default priority of installed policies */
|
||||||
#define SPD_PRIORITY 1024
|
#define PRIO_LOW 3000
|
||||||
|
#define PRIO_HIGH 2000
|
||||||
|
|
||||||
#define BUFFER_SIZE 1024
|
#define BUFFER_SIZE 1024
|
||||||
|
|
||||||
@@ -979,7 +980,7 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
traffic_selector_t *src_ts,
|
traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts,
|
traffic_selector_t *dst_ts,
|
||||||
policy_dir_t direction, protocol_id_t protocol,
|
policy_dir_t direction, protocol_id_t protocol,
|
||||||
u_int32_t reqid, bool update)
|
u_int32_t reqid, bool high_prio, bool update)
|
||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
kernel_policy_t *current, *policy;
|
kernel_policy_t *current, *policy;
|
||||||
@@ -1011,6 +1012,14 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
current->refcount++;
|
current->refcount++;
|
||||||
this->logger->log(this->logger, CONTROL|LEVEL1,
|
this->logger->log(this->logger, CONTROL|LEVEL1,
|
||||||
"policy already exists, increasing refcount");
|
"policy already exists, increasing refcount");
|
||||||
|
if (!high_prio)
|
||||||
|
{
|
||||||
|
/* if added policy is for a ROUTED child_sa, do not
|
||||||
|
* overwrite existing INSTALLED policy */
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
pthread_mutex_unlock(&this->pol_mutex);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
policy = current;
|
policy = current;
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
@@ -1035,7 +1044,11 @@ static status_t add_policy(private_kernel_interface_t *this,
|
|||||||
policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
|
policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
|
||||||
policy_info->sel = policy->sel;
|
policy_info->sel = policy->sel;
|
||||||
policy_info->dir = policy->direction;
|
policy_info->dir = policy->direction;
|
||||||
policy_info->priority = SPD_PRIORITY;
|
/* calculate priority based on source selector size, small size = high prio */
|
||||||
|
policy_info->priority = high_prio ? PRIO_HIGH : PRIO_LOW;
|
||||||
|
policy_info->priority -= policy->sel.prefixlen_s * 10;
|
||||||
|
policy_info->priority -= policy->sel.proto ? 2 : 0;
|
||||||
|
policy_info->priority -= policy->sel.sport_mask ? 1 : 0;
|
||||||
policy_info->action = XFRM_POLICY_ALLOW;
|
policy_info->action = XFRM_POLICY_ALLOW;
|
||||||
policy_info->share = XFRM_SHARE_ANY;
|
policy_info->share = XFRM_SHARE_ANY;
|
||||||
pthread_mutex_unlock(&this->pol_mutex);
|
pthread_mutex_unlock(&this->pol_mutex);
|
||||||
@@ -1272,7 +1285,7 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa;
|
this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa;
|
||||||
this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
|
this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
|
||||||
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
|
||||||
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool))add_policy;
|
this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,bool))add_policy;
|
||||||
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
|
this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
|
||||||
this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
|
this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
|
||||||
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ struct kernel_interface_t {
|
|||||||
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
|
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
|
||||||
* @param protocol protocol to use to protect traffic (AH/ESP)
|
* @param protocol protocol to use to protect traffic (AH/ESP)
|
||||||
* @param reqid uniqe ID of an SA to use to enforce policy
|
* @param reqid uniqe ID of an SA to use to enforce policy
|
||||||
|
* @param high_prio if TRUE, uses a higher priority than any with FALSE
|
||||||
* @param update update an existing policy, if TRUE
|
* @param update update an existing policy, if TRUE
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS
|
* - SUCCESS
|
||||||
@@ -217,7 +218,7 @@ struct kernel_interface_t {
|
|||||||
traffic_selector_t *src_ts,
|
traffic_selector_t *src_ts,
|
||||||
traffic_selector_t *dst_ts,
|
traffic_selector_t *dst_ts,
|
||||||
policy_dir_t direction, protocol_id_t protocol,
|
policy_dir_t direction, protocol_id_t protocol,
|
||||||
u_int32_t reqid, bool update);
|
u_int32_t reqid, bool high_prio, bool update);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Query the use time of a policy.
|
* @brief Query the use time of a policy.
|
||||||
|
|||||||
@@ -601,58 +601,10 @@ static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
|
|||||||
*/
|
*/
|
||||||
static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
|
static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
|
||||||
{
|
{
|
||||||
linked_list_t *ike_sas;
|
|
||||||
iterator_t *iterator;
|
|
||||||
int instances = 0;
|
|
||||||
connection_t *conn;
|
|
||||||
|
|
||||||
pop_string(msg, &(msg->terminate.name));
|
pop_string(msg, &(msg->terminate.name));
|
||||||
this->logger->log(this->logger, CONTROL, "received stroke: terminate \"%s\"", msg->terminate.name);
|
this->logger->log(this->logger, CONTROL, "received stroke: terminate \"%s\"", msg->terminate.name);
|
||||||
|
|
||||||
/* we have to do tricky tricks to give the most comprehensive output to the user.
|
charon->ike_sa_manager->delete_by_name(charon->ike_sa_manager, msg->terminate.name);
|
||||||
* There are different cases:
|
|
||||||
* 1. Connection is available, but IKEv1:
|
|
||||||
* => just ignore it, let pluto print it
|
|
||||||
* 2. Connection is not available, but instances of a deleted connection template:
|
|
||||||
* => terminate them, and print their termination
|
|
||||||
* 3. Connection is not available, and and no instances are there:
|
|
||||||
* => show error about bad connection name
|
|
||||||
* 4. An IKEv2 connection is available, and may contain instances:
|
|
||||||
* => terminate and print, simple
|
|
||||||
*/
|
|
||||||
conn = charon->connections->get_connection_by_name(charon->connections, msg->terminate.name);
|
|
||||||
if (conn == NULL || conn->is_ikev2(conn))
|
|
||||||
{
|
|
||||||
ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager, msg->terminate.name);
|
|
||||||
|
|
||||||
iterator = ike_sas->create_iterator(ike_sas, TRUE);
|
|
||||||
while (iterator->has_next(iterator))
|
|
||||||
{
|
|
||||||
ike_sa_id_t *ike_sa_id;
|
|
||||||
iterator->current(iterator, (void**)&ike_sa_id);
|
|
||||||
charon->ike_sa_manager->delete(charon->ike_sa_manager, ike_sa_id);
|
|
||||||
ike_sa_id->destroy(ike_sa_id);
|
|
||||||
instances++;
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
ike_sas->destroy(ike_sas);
|
|
||||||
if (conn == NULL && instances == 0)
|
|
||||||
{
|
|
||||||
this->stroke_logger->log(this->stroke_logger, CONTROL,
|
|
||||||
"no connection named \"%s\"",
|
|
||||||
msg->terminate.name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->stroke_logger->log(this->stroke_logger, CONTROL,
|
|
||||||
"terminated %d instances of \"%s\"",
|
|
||||||
instances, msg->terminate.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (conn)
|
|
||||||
{
|
|
||||||
conn->destroy(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user