static packet_t *clone(private_packet_t *this)
{
private_packet_t *other = (private_packet_t*)packet_create();
-
+
if (this->destination != NULL)
{
other->destination = this->destination->clone(this->destination);
}
- else
- {
- other->destination = NULL;
- }
-
if (this->source != NULL)
{
other->source = this->source->clone(this->source);
}
- else
- {
- other->source = NULL;
- }
-
- /* only clone existing chunks :-) */
if (this->data.ptr != NULL)
{
other->data.ptr = clalloc(this->data.ptr,this->data.len);
other->data.len = this->data.len;
}
- else
- {
- other->data = CHUNK_INITIALIZER;
- }
return &(other->public);
}
-
/*
* Documented in header
*/
typedef struct event_t event_t;
/**
- * @brief Represents an event as it is stored in the event queue.
- *
- * A event consists of a event time and an assigned job object.
- *
+ * Event containing a job and a schedule time
*/
-struct event_t{
+struct event_t {
/**
* Time to fire the event.
*/
* Every event has its assigned job.
*/
job_t * job;
-
- /**
- * @brief Destroys a event_t object.
- *
- * @param event_t calling object
- */
- void (*destroy) (event_t *event);
};
-
-/**
- * implements event_t.destroy
- */
-static void event_destroy(event_t *event)
-{
- free(event);
-}
-
-/**
- * @brief Creates a event for a specific time
- *
- * @param time absolute time to fire the event
- * @param job job to add to job-queue at specific time
- *
- * @returns created event_t object
- */
-static event_t *event_create(timeval_t time, job_t *job)
-{
- event_t *this = malloc_thing(event_t);
-
- this->destroy = event_destroy;
- this->time = time;
- this->job = job;
-
- return this;
-}
-
typedef struct private_event_queue_t private_event_queue_t;
/**
* Private Variables and Functions of event_queue_t class.
- *
*/
struct private_event_queue_t {
/**
pthread_mutex_lock(&(this->mutex));
- while (1)
+ while (TRUE)
{
while(this->list->get_count(this->list) == 0)
{
pthread_cleanup_pop(0);
}
- this->list->get_first(this->list,(void **) &next_event);
+ this->list->get_first(this->list, (void **)&next_event);
gettimeofday(¤t_time, NULL);
long difference = time_difference(¤t_time,&(next_event->time));
else
{
/* event available */
- this->list->remove_first(this->list,(void **) &next_event);
-
+ this->list->remove_first(this->list, (void **)&next_event);
job = next_event->job;
-
- next_event->destroy(next_event);
+ free(next_event);
break;
}
}
*/
static void add_absolute(private_event_queue_t *this, job_t *job, timeval_t time)
{
- event_t *event = event_create(time,job);
+ event_t *event;
event_t *current_event;
status_t status;
+
+ /* create event */
+ event = malloc_thing(event_t);
+ event->time = time;
+ event->job = job;
pthread_mutex_lock(&(this->mutex));
*/
static void event_queue_destroy(private_event_queue_t *this)
{
- while (this->list->get_count(this->list) > 0)
+ event_t *event;
+ while (this->list->remove_last(this->list, (void**)&event) == SUCCESS)
{
- event_t *event;
-
- if (this->list->remove_first(this->list,(void *) &event) != SUCCESS)
- {
- this->list->destroy(this->list);
- break;
- }
event->job->destroy(event->job);
- event->destroy(event);
+ free(event);
}
this->list->destroy(this->list);
-
pthread_mutex_destroy(&(this->mutex));
-
pthread_cond_destroy(&(this->condvar));
-
free(this);
}
/* add mutex unlock handler for cancellation, enable cancellation */
pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex));
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-
+
pthread_cond_wait( &(this->condvar), &(this->mutex));
-
+
/* reset cancellation, remove mutex-unlock handler (without executing) */
pthread_setcancelstate(oldstate, NULL);
pthread_cleanup_pop(0);
}
- this->list->remove_first(this->list,(void **) &job);
+ this->list->remove_first(this->list, (void **)&job);
pthread_mutex_unlock(&(this->mutex));
return job;
}
*/
static void job_queue_destroy (private_job_queue_t *this)
{
- while (this->list->get_count(this->list) > 0)
+ job_t *job;
+ while (this->list->remove_last(this->list, (void**)&job) == SUCCESS)
{
- job_t *job;
- if (this->list->remove_first(this->list,(void *) &job) != SUCCESS)
- {
- this->list->destroy(this->list);
- break;
- }
job->destroy(job);
}
this->list->destroy(this->list);
-
pthread_mutex_destroy(&(this->mutex));
-
pthread_cond_destroy(&(this->condvar));
-
free(this);
}
static int get_count(private_send_queue_t *this)
{
int count;
- pthread_mutex_lock(&(this->mutex));
+ pthread_mutex_lock(&this->mutex);
count = this->list->get_count(this->list);
- pthread_mutex_unlock(&(this->mutex));
+ pthread_mutex_unlock(&this->mutex);
return count;
}
{
int oldstate;
packet_t *packet;
- pthread_mutex_lock(&(this->mutex));
- /* go to wait while no packets available */
+ pthread_mutex_lock(&this->mutex);
+
+ /* go to wait while no packets available */
while(this->list->get_count(this->list) == 0)
{
/* add mutex unlock handler for cancellation, enable cancellation */
- pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex));
+ pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&this->mutex);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
- pthread_cond_wait( &(this->condvar), &(this->mutex));
-
+ pthread_cond_wait(&this->condvar, &this->mutex);
+
/* reset cancellation, remove mutex-unlock handler (without executing) */
pthread_setcancelstate(oldstate, NULL);
pthread_cleanup_pop(0);
}
- this->list->remove_first(this->list,(void **)&packet);
- pthread_mutex_unlock(&(this->mutex));
+ this->list->remove_first(this->list, (void**)&packet);
+ pthread_mutex_unlock(&this->mutex);
return packet;
}
src->get_address(src), src->get_port(src),
dst->get_address(dst), dst->get_port(dst));
- pthread_mutex_lock(&(this->mutex));
- this->list->insert_last(this->list,packet);
- pthread_cond_signal( &(this->condvar));
- pthread_mutex_unlock(&(this->mutex));
+ pthread_mutex_lock(&this->mutex);
+ this->list->insert_last(this->list, packet);
+ pthread_cond_signal(&this->condvar);
+ pthread_mutex_unlock(&this->mutex);
}
/**
*/
static void destroy (private_send_queue_t *this)
{
-
- /* destroy all packets in list before destroying list */
- while (this->list->get_count(this->list) > 0)
+ packet_t *packet;
+ while (this->list->remove_last(this->list, (void**)&packet) == SUCCESS)
{
- packet_t *packet;
- if (this->list->remove_first(this->list,(void *) &packet) != SUCCESS)
- {
- this->list->destroy(this->list);
- break;
- }
packet->destroy(packet);
}
this->list->destroy(this->list);
-
pthread_mutex_destroy(&(this->mutex));
-
pthread_cond_destroy(&(this->condvar));
-
free(this);
}
this->public.destroy = (void(*)(send_queue_t*)) destroy;
this->list = linked_list_create();
- pthread_mutex_init(&(this->mutex), NULL);
- pthread_cond_init(&(this->condvar), NULL);
+ pthread_mutex_init(&this->mutex, NULL);
+ pthread_cond_init(&this->condvar, NULL);
this->logger = logger_manager->get_logger(logger_manager, SOCKET);
-
+
return (&this->public);
}
u_int32_t hard_lifetime;
/**
- * has this CHILD_SA been rekeyed?
+ * transaction which is rekeying this CHILD_SA
*/
- bool rekeyed;
+ void *rekeying_transaction;
+
+ /**
+ * has this child SA been rekeyed/is rekeying?
+ */
+ bool is_rekeying;
/**
* Specifies if NAT traversal is used
prf_plus, natt, mine);
this->install_time = time(NULL);
-
+
return status;
}
}
/**
- * Implementation of child_sa_t.set_rekeyed.
+ * Implementation of child_sa_t.set_rekeying_transaction.
+ */
+static void set_rekeying_transaction(private_child_sa_t *this, void *transaction)
+{
+ this->rekeying_transaction = transaction;
+ this->is_rekeying = TRUE;
+}
+
+/**
+ * Implementation of child_sa_t.get_rekeying_transaction.
*/
-static void set_rekeyed(private_child_sa_t *this)
+static void* get_rekeying_transaction(private_child_sa_t *this)
{
- this->rekeyed = TRUE;
+ return this->rekeying_transaction;
+}
+
+/**
+ * Implementation of child_sa_t.is_rekeying.
+ */
+static bool is_rekeying(private_child_sa_t *this)
+{
+ return this->is_rekeying;
}
/**
if (mine)
{
- src = this->me.addr;
- dst = this->other.addr;
- new_src = new_me;
- new_dst = new_other;
- src_changes = my_changes;
- dst_changes = other_changes;
- spi = this->me.spi;
- }
- else
- {
src = this->other.addr;
dst = this->me.addr;
new_src = new_other;
dst_changes = my_changes;
spi = this->other.spi;
}
+ else
+ {
+ src = this->me.addr;
+ dst = this->other.addr;
+ new_src = new_me;
+ new_dst = new_other;
+ src_changes = my_changes;
+ dst_changes = other_changes;
+ spi = this->me.spi;
+ }
this->logger->log(this->logger, CONTROL|LEVEL1,
"updating %s SA 0x%x, from %s:%d..%s:%d to %s:%d..%s:%d",
static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other,
int my_changes, int other_changes)
{
- if (!my_changes || !other_changes)
+ if (!my_changes && !other_changes)
{
return SUCCESS;
}
/* delete all policies in the kernel */
while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS)
{
- if (!this->rekeyed)
+ if (!this->is_rekeying)
{
/* let rekeyed policies, as they are used by another child_sa */
charon->kernel_interface->del_policy(charon->kernel_interface,
free(policy);
}
this->policies->destroy(this->policies);
-
+
+ this->me.addr->destroy(this->me.addr);
+ this->other.addr->destroy(this->other.addr);
free(this);
}
this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,int,int))update_hosts;
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
- this->public.set_rekeyed = (void (*)(child_sa_t*))set_rekeyed;
+ this->public.set_rekeying_transaction = (void (*)(child_sa_t*,void*))set_rekeying_transaction;
+ this->public.get_rekeying_transaction = (void* (*)(child_sa_t*))get_rekeying_transaction;
+ this->public.is_rekeying = (bool (*)(child_sa_t*))is_rekeying;
this->public.log_status = (void (*)(child_sa_t*, logger_t*, char*))log_status;
this->public.destroy = (void(*)(child_sa_t*))destroy;
/* private data */
this->logger = logger_manager->get_logger(logger_manager, CHILD_SA);
- this->me.addr = me;
- this->other.addr = other;
+ this->me.addr = me->clone(me);
+ this->other.addr = other->clone(other);
this->me.spi = 0;
this->other.spi = 0;
this->alloc_ah_spi = 0;
this->reqid = rekey ? rekey : ++reqid;
this->policies = linked_list_create();
this->protocol = PROTO_NONE;
- this->rekeyed = FALSE;
+ this->rekeying_transaction = NULL;
+ this->is_rekeying = FALSE;
return &this->public;
}
typedef struct child_sa_t child_sa_t;
/**
- * @brief Represents multiple IPsec SAs between two hosts.
+ * @brief Represents an IPsec SAs between two hosts.
*
* A child_sa_t contains two SAs. SAs for both
* directions are managed in one child_sa_t object. Both
status_t (*get_use_time) (child_sa_t *this, bool inbound, time_t *use_time);
/**
- * @brief Mark this child_sa as rekeyed.
+ * @brief Set the transaction which rekeys this CHILD_SA.
*
- * Since an SA which rekeys a old SA shares the same policy,
- * we must mark a child_sa as rekeyed. A so marked SA does
- * not remove its policy, as the new SA uses it.
+ * Since either end may initiate CHILD_SA rekeying, we must detect
+ * such situations to handle them cleanly. A rekeying transaction
+ * registers itself to the CHILD_SA, and checks later if another
+ * transaction is in progress of a rekey.
*
* @param this calling object
*/
- void (*set_rekeyed) (child_sa_t *this);
+ void (*set_rekeying_transaction) (child_sa_t *this, void *transaction);
+
+ /**
+ * @brief Get the transaction which rekeys this CHILD_SA.
+ *
+ * See set_rekeying_transactoin
+ *
+ * @param this calling object
+ */
+ void* (*get_rekeying_transaction) (child_sa_t *this);
+
+ /**
+ * @brief Is the CHILD SA rekeying/in progress of rekeying?
+ *
+ * This is a readonly parameter. It is set whenever the
+ * set_rekeying_transaction() method is called.
+ *
+ * @param this calling object
+ */
+ bool (*is_rekeying) (child_sa_t *this);
/**
* @brief Log the status of a child_sa to a logger.
#include <encoding/payloads/sa_payload.h>
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/ts_payload.h>
-#include <sa/child_sa.h>
#include <sa/transactions/delete_child_sa.h>
#include <utils/randomizer.h>
child_sa_t *rekeyed_sa;
/**
+ * Have we lost the simultaneous rekeying nonce compare?
+ */
+ bool lost;
+
+ /**
* source of randomness
*/
randomizer_t *randomizer;
}
/**
- * Implementation of transaction_t.rekeys_child.
+ * Implementation of create_child_sa_t.rekeys_child.
*/
static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
{
}
/**
+ * Implementation of create_child_sa_t.cancel.
+ */
+static void cancel(private_create_child_sa_t *this)
+{
+ this->rekeyed_sa = NULL;
+ this->lost = TRUE;
+}
+
+/**
* Implementation of transaction_t.get_request.
*/
static status_t get_request(private_create_child_sa_t *this, message_t **result)
message_t *request;
host_t *me, *other;
+ /* check if we are not already rekeying */
+ if (this->rekeyed_sa &&
+ this->rekeyed_sa->is_rekeying(this->rekeyed_sa))
+ {
+ this->logger->log(this->logger, ERROR,
+ "rekeying a CHILD_SA which is already rekeying, aborted");
+ return FAILED;
+ }
+
/* check if we already have built a message (retransmission) */
if (this->message)
{
notify->set_spi(notify, this->rekeyed_sa->get_spi(this->rekeyed_sa, TRUE));
request->add_payload(request, (payload_t*)notify);
- /* and mark sa with rekeying-in-progress */
- this->rekeyed_sa->set_rekeyed(this->rekeyed_sa);
+ /* register us as rekeying to detect multiple rekeying */
+ this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, &this->public);
}
return SUCCESS;
ts_response = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
response->add_payload(response, (payload_t*)ts_response);
}
- /* CHILD_SA successfully created. Now we must check if it rekeys an old one,
- * and if so, mark the old as rekeyed. It will get deleted from the other
- * peer. */
+ /* CHILD_SA successfully created. We set us as the rekeying transaction of
+ * this SA. If we already initiated rekeying of the same SA, we will detect
+ * this later in the conclude() call. */
if (this->rekeyed_sa)
{
- this->rekeyed_sa->set_rekeyed(this->rekeyed_sa);
+ if (this->rekeyed_sa->is_rekeying(this->rekeyed_sa))
+ {
+ /* rekeying already in progress, register us, too */
+ this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, &this->public);
+ }
+ else
+ {
+ /* no rekeying in progress. mark SA as rekeyed, but not conflicted */
+ this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, NULL);
+ }
}
return SUCCESS;
}
ts_payload_t *tsi_payload = NULL;
ts_payload_t *tsr_payload = NULL;
status_t status;
+ child_sa_t *new_child = NULL;
+ delete_child_sa_t *delete_child_sa;
/* check message type */
if (response->get_exchange_type(response) != CREATE_CHILD_SA)
"CHILD_SA creation failed");
return FAILED;
}
+ new_child = this->child_sa;
if (install_child_sa(this, TRUE) != SUCCESS)
{
this->logger->log(this->logger, ERROR,
return FAILED;
}
}
- /* CHILD_SA successfully created. If we have rekeyed an old one, delete it */
+ /* CHILD_SA successfully created. If the other peer initiated rekeying
+ * in the meantime, we detect this by comparing the rekeying_transaction
+ * of the SA. If it changed, we are not alone. Then we must compare the nonces.
+ * If no simultaneous rekeying is going on, we just initiate the delete of
+ * the superseded SA. */
if (this->rekeyed_sa)
{
- delete_child_sa_t *delete_child_sa;
+ private_create_child_sa_t *other;
+
+ other = (private_create_child_sa_t*)
+ this->rekeyed_sa->get_rekeying_transaction(this->rekeyed_sa);
- delete_child_sa = delete_child_sa_create(this->ike_sa,
- this->message_id + 1);
- delete_child_sa->set_child_sa(delete_child_sa, this->rekeyed_sa);
+ /* we are not rekeying anymore, unregister us */
+ this->rekeyed_sa->set_rekeying_transaction(this->rekeyed_sa, NULL);
+
+ if (other != this)
+ { /* simlutaneous rekeying is going on, not so good */
+ chunk_t this_lowest, other_lowest;
+
+ /* check if this has a lower nonce the other */
+ if (memcmp(this->nonce_i.ptr, this->nonce_r.ptr,
+ min(this->nonce_i.len, this->nonce_r.len)) < 0)
+ {
+ this_lowest = this->nonce_i;
+ }
+ else
+ {
+ this_lowest = this->nonce_r;
+ }
+ if (memcmp(other->nonce_i.ptr, other->nonce_r.ptr,
+ min(other->nonce_i.len, other->nonce_r.len)) < 0)
+ {
+ other_lowest = other->nonce_i;
+ }
+ else
+ {
+ other_lowest = other->nonce_r;
+ }
+ if (memcmp(this_lowest.ptr, other_lowest.ptr,
+ min(this_lowest.len, other_lowest.len)) < 0)
+ {
+ this->logger->log(this->logger, ERROR,
+ "detected simultaneous CHILD_SA rekeying, but ours is preferred");
+ }
+ else
+ {
+
+ this->logger->log(this->logger, ERROR,
+ "detected simultaneous CHILD_SA rekeying, deleting ours");
+ this->lost = TRUE;
+ }
+ }
+ /* delete the old SA if we have won the rekeying nonce compare*/
+ if (!this->lost)
+ {
+ other->rekeyed_sa->set_rekeying_transaction(other->rekeyed_sa, NULL);
+ delete_child_sa = delete_child_sa_create(this->ike_sa, this->message_id + 1);
+ delete_child_sa->set_child_sa(delete_child_sa, this->rekeyed_sa);
+ *next = (transaction_t*)delete_child_sa;
+ }
+ }
+ if (this->lost)
+ {
+ /* we have lost simlutaneous rekeying, delete the CHILD_SA we just have created */
+ delete_child_sa = delete_child_sa_create(this->ike_sa, this->message_id + 1);
+ new_child->set_rekeying_transaction(new_child, NULL);
+ delete_child_sa->set_child_sa(delete_child_sa, new_child);
*next = (transaction_t*)delete_child_sa;
}
return SUCCESS;
/* public functions */
this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
+ this->public.cancel = (void(*)(create_child_sa_t*))cancel;
/* private data */
this->ike_sa = ike_sa;
this->nonce_r = CHUNK_INITIALIZER;
this->child_sa = NULL;
this->rekeyed_sa = NULL;
+ this->lost = FALSE;
this->proposal = NULL;
this->tsi = NULL;
this->tsr = NULL;
* for more details.
*/
-
-#ifndef CREATE_CHILD_SA_
-#define CREATE_CHILD_SA_
+#ifndef CREATE_CHILD_SA_H_
+#define CREATE_CHILD_SA_H_
#include <sa/ike_sa.h>
#include <sa/child_sa.h>
* Rekeying of an CHILD_SA works the same way as creating a new one,
* but includes an additional REKEY_SA notify and deletes the old
* one (in a separate transaction).
+ *
+ * ¦__________ _________¦
+ * ¦ Cyq \/ Czq ¦
+ * ¦__________/\_________¦
+ * detect ¦__________ _________¦ detect
+ * ¦ Czp \/ Czp ¦
+ * compare nonces, won ¦__________/\_________¦ compare nonces, lost
+ * ¦ ¦
+ * delete old ¦__________ ¦
+ * ¦ Dxq \__________¦
+ * ¦ __________¦
+ * ¦__________/ Dxp ¦
+ * ¦ __________¦ delete created
+ * ¦__________/ Dzq ¦
+ * ¦__________ ¦
+ * ¦ Dzp \__________¦
+ *
*
* @b Constructors:
* - create_child_sa_create()
* @param child_sa CHILD_SA to rekey
*/
void (*rekeys_child) (create_child_sa_t* this, child_sa_t *child_sa);
+
+ /**
+ * @brief Cancel a rekeying request.
+ *
+ * Cancelling a rekeying request will set a flag in the transaction. When
+ * the response for the transaction is received, the created CHILD_SA
+ * gets deleted afterwards.
+ *
+ * @param this calling object
+ * @param child_sa CHILD_SA to rekey
+ */
+ void (*cancel) (create_child_sa_t* this);
};
/**
*/
create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa, u_int32_t message_id);
-#endif /* CREATE_CHILD_SA_ */
+#endif /* CREATE_CHILD_SA_H_ */
#include <daemon.h>
#include <encoding/payloads/delete_payload.h>
+#include <sa/transactions/create_child_sa.h>
typedef struct private_delete_child_sa_t private_delete_child_sa_t;
protocol_id_t protocol;
u_int32_t spi;
iterator_t *iterator;
- delete_payload_t *delete_response;
+ delete_payload_t *delete_response = NULL;
/* get requested CHILD */
protocol = delete_request->get_protocol_id(delete_request);
if (child_sa != NULL)
{
+ create_child_sa_t *rekey;
+
this->logger->log(this->logger, CONTROL,
- "received DELETE for %s CHILD_SA with SPI 0x%x, deleting",
+ "received DELETE for %s CHILD_SA with SPI 0x%x, deleting",
mapping_find(protocol_id_m, protocol), ntohl(spi));
+
+ rekey = child_sa->get_rekeying_transaction(child_sa);
+ if (rekey)
+ {
+ /* we have received a delete for an SA which we are still rekeying.
+ * this means we have lost the nonce comparison, and the rekeying
+ * will fail. We set a flag in the transaction for this special case.
+ */
+ this->logger->log(this->logger, CONTROL,
+ "DELETE received while rekeying, rekeying cancelled");
+ rekey->cancel(rekey);
+ }
/* delete it, with inbound spi */
spi = child_sa->get_spi(child_sa, TRUE);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
#ifndef TRANSACTION_H_
#define TRANSACTION_H_
+
+typedef struct transaction_t transaction_t;
+
#include <types.h>
#include <encoding/message.h>
#include <sa/ike_sa.h>
-typedef struct transaction_t transaction_t;
/**
* @brief This interface represents a transaction an established IKE_SA can do.
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/udp.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
}
struct xfrm_encap_tmpl* encap = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
- /* UDP_ENCAP_ESPINUDP, see /usr/src/linux/include/linux/udp.h
- * we could probably use 3 here (as pluto does) although the
- * result is eventually the same. */
- encap->encap_type = 2;
+ encap->encap_type = UDP_ENCAP_ESPINUDP;
encap->encap_sport = ntohs(natt->sport);
encap->encap_dport = ntohs(natt->dport);
memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
this->logger->log(this->logger, CONTROL|LEVEL2, "getting SA");
struct nlmsghdr *hdr = (struct nlmsghdr*)request;
- hdr->nlmsg_flags = NLM_F_REQUEST ;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
- hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
struct xfrm_usersa_id *sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
sa_id->daddr = dst->get_xfrm_addr(dst);
/* public functions */
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,bool))add_sa;
- this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,protocol_id_t,u_int32_t))add_policy;
this->public.update_sa_hosts = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,int,int,u_int32_t,protocol_id_t))update_sa_hosts;
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*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,protocol_id_t,u_int32_t))add_policy;
this->public.query_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,time_t*))query_policy;
this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy;
-
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
/* private members */
* Public part of a receiver_t object.
*/
receiver_t public;
-
- /**
- * @brief Thread function started at creation of the receiver object.
- *
- * @param this calling object
- */
- void (*receive_packets) (private_receiver_t *this);
/**
* Assigned thread.
private_receiver_t *this = malloc_thing(private_receiver_t);
this->public.destroy = (void(*)(receiver_t*)) destroy;
- this->receive_packets = receive_packets;
this->logger = logger_manager->get_logger(logger_manager, RECEIVER);
- if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->receive_packets, this) != 0)
+ if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))receive_packets, this) != 0)
{
this->logger->log(this->logger, ERROR, "Receiver thread could not be started");
free(this);
* Public part of a scheduler_t object.
*/
scheduler_t public;
-
- /**
- * @brief Get events from the event queue and add them to to job queue.
- *
- * Thread function started at creation of the scheduler object.
- *
- * @param this calling object
- */
- void (*get_events) (private_scheduler_t *this);
/**
* Assigned thread.
this->logger->log(this->logger, CONTROL, "scheduler thread running, thread_ID: %06u", (int)pthread_self());
- for (;;)
+ while (TRUE)
{
this->logger->log(this->logger, CONTROL|LEVEL2, "Waiting for next event...");
/* get a job, this block until one is available */
private_scheduler_t *this = malloc_thing(private_scheduler_t);
this->public.destroy = (void(*)(scheduler_t*)) destroy;
- this->get_events = get_events;
this->logger = logger_manager->get_logger(logger_manager, SCHEDULER);
- if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->get_events, this) != 0)
+ if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))get_events, this) != 0)
{
/* thread could not be created */
this->logger->log(this->logger, ERROR, "Scheduler thread could not be created!");
pthread_t assigned_thread;
/**
- * @brief The thread function, sends out packets.
- *
- * @param this calling object
- */
- void (*send_packets) (private_sender_t * this);
-
- /**
* A logger for this sender_t object.
*/
logger_t *logger;
*/
static void send_packets(private_sender_t * this)
{
- packet_t * current_packet;
+ packet_t *current_packet;
status_t status;
/* cancellation disabled by default */
this->logger->log(this->logger, CONTROL, "sender thread running, thread_ID: %06u", (int)pthread_self());
- while (1)
+ while (TRUE)
{
current_packet = charon->send_queue->get(charon->send_queue);
this->logger->log(this->logger, CONTROL|LEVEL1, "Got a packet, sending it");
- status = charon->socket->send(charon->socket,current_packet);
+ status = charon->socket->send(charon->socket, current_packet);
if (status != SUCCESS)
{
this->logger->log(this->logger, ERROR, "Sending failed, socket returned %s",
{
this->logger->log(this->logger, CONTROL | LEVEL1, "Going to terminate sender thread");
pthread_cancel(this->assigned_thread);
-
+
pthread_join(this->assigned_thread, NULL);
this->logger->log(this->logger, CONTROL | LEVEL1, "Sender thread terminated");
-
+
free(this);
}
{
private_sender_t *this = malloc_thing(private_sender_t);
- this->send_packets = send_packets;
this->public.destroy = (void(*)(sender_t*)) destroy;
this->logger = logger_manager->get_logger(logger_manager, SENDER);
- if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->send_packets, this) != 0)
+ if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))send_packets, this) != 0)
{
this->logger->log(this->logger, ERROR, "Sender thread could not be created");
free(this);
/**
* @file thread_pool.c
- *
+ *
* @brief Implementation of thread_pool_t.
- *
+ *
*/
/*
/**
* Logger of the thread pool.
*/
- logger_t *pool_logger;
-
- /**
- * Logger of the worker threads.
- */
- logger_t *worker_logger;
+ logger_t *logger;
} ;
/**
/* cancellation disabled by default */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- this->worker_logger->log(this->worker_logger, CONTROL, "worker thread running, thread_ID: %06u", (int)pthread_self());
+ this->logger->log(this->logger, CONTROL,
+ "worker thread running, thread_ID: %06u",
+ (int)pthread_self());
while (TRUE)
{
int current;
/* flag thread for termination */
for (current = 0; current < this->pool_size; current++) {
- this->pool_logger->log(this->pool_logger, CONTROL, "cancelling worker thread #%d", current+1);
+ this->logger->log(this->logger, CONTROL,
+ "cancelling worker thread #%d", current+1);
pthread_cancel(this->threads[current]);
}
for (current = 0; current < this->pool_size; current++) {
if (pthread_join(this->threads[current], NULL) == 0)
{
- this->pool_logger->log(this->pool_logger, CONTROL, "worker thread #%d terminated", current+1);
+ this->logger->log(this->logger, CONTROL,
+ "worker thread #%d terminated", current+1);
}
else
{
- this->pool_logger->log(this->pool_logger, ERROR, "could not terminate worker thread #%d", current+1);
+ this->logger->log(this->logger, ERROR,
+ "could not terminate worker thread #%d", current+1);
}
}
/* initialize member */
this->pool_size = pool_size;
this->threads = malloc(sizeof(pthread_t) * pool_size);
- this->pool_logger = logger_manager->get_logger(logger_manager, THREAD_POOL);
- this->worker_logger = logger_manager->get_logger(logger_manager, WORKER);
+ this->logger = logger_manager->get_logger(logger_manager, THREAD_POOL);
/* try to create as many threads as possible, up to pool_size */
for (current = 0; current < pool_size; current++)
{
- if (pthread_create(&(this->threads[current]), NULL, (void*(*)(void*))process_jobs, this) == 0)
+ if (pthread_create(&(this->threads[current]), NULL,
+ (void*(*)(void*))process_jobs, this) == 0)
{
- this->pool_logger->log(this->pool_logger, CONTROL, "created worker thread #%d", current+1);
+ this->logger->log(this->logger, CONTROL,
+ "created worker thread #%d", current+1);
}
else
{
/* creation failed, is it the first one? */
if (current == 0)
{
- this->pool_logger->log(this->pool_logger, ERROR, "Could not create any thread");
+ this->logger->log(this->logger, ERROR, "Could not create any thread");
free(this->threads);
free(this);
return NULL;
}
/* not all threads could be created, but at least one :-/ */
- this->pool_logger->log(this->pool_logger, ERROR, "Could only create %d from requested %d threads!", current, pool_size);
+ this->logger->log(this->logger, ERROR,
+ "Could only create %d from requested %d threads!",
+ current, pool_size);
this->pool_size = current;
return (thread_pool_t*)this;
}
- }
+ }
return (thread_pool_t*)this;
}