summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins')
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_server.c5
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c3
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c3
-rw-r--r--src/libcharon/plugins/eap_md5/eap_md5.c3
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c7
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c390
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_peer.c3
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_server.c3
-rw-r--r--src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c3
-rw-r--r--src/libcharon/plugins/ha/ha_cache.c12
-rw-r--r--src/libcharon/plugins/ha/ha_cache.h3
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.c128
-rw-r--r--src/libcharon/plugins/vici/libvici.h29
-rw-r--r--src/libcharon/plugins/vici/python/Makefile.am12
-rw-r--r--src/libcharon/plugins/vici/python/Makefile.in17
-rw-r--r--src/libcharon/plugins/vici/ruby/Makefile.am4
-rw-r--r--src/libcharon/plugins/vici/ruby/Makefile.in14
-rw-r--r--src/libcharon/plugins/vici/vici_config.c37
-rw-r--r--src/libcharon/plugins/vici/vici_dispatcher.c41
-rw-r--r--src/libcharon/plugins/vici/vici_dispatcher.h33
-rw-r--r--src/libcharon/plugins/vici/vici_plugin.c24
-rw-r--r--src/libcharon/plugins/vici/vici_query.c85
-rw-r--r--src/libcharon/plugins/vici/vici_query.h28
-rw-r--r--src/libcharon/plugins/vici/vici_socket.c46
-rw-r--r--src/libcharon/plugins/xauth_generic/xauth_generic.c2
25 files changed, 764 insertions, 171 deletions
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c
index eba7af874..04bfc170b 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_server.c
+++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c
@@ -425,7 +425,7 @@ static status_t process_challenge(private_eap_aka_server_t *this,
enumerator->destroy(enumerator);
/* compare received RES against stored XRES */
- if (!chunk_equals(res, this->xres))
+ if (!chunk_equals_const(res, this->xres))
{
DBG1(DBG_IKE, "received RES does not match XRES");
return FAILED;
@@ -486,7 +486,7 @@ static status_t process_reauthentication(private_eap_aka_server_t *this,
this->crypto->clear_keys(this->crypto);
return challenge(this, out);
}
- if (!chunk_equals(counter, this->counter))
+ if (!chunk_equals_const(counter, this->counter))
{
DBG1(DBG_IKE, "received counter does not match");
return FAILED;
@@ -730,4 +730,3 @@ eap_aka_server_t *eap_aka_server_create(identification_t *server,
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
index a71dae78a..e38ee5b70 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
@@ -87,7 +87,7 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
{
return FAILED;
}
- if (!memeq(mac, xmac, AKA_MAC_LEN))
+ if (!memeq_const(mac, xmac, AKA_MAC_LEN))
{
DBG1(DBG_IKE, "received MAC does not match XMAC");
DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
@@ -184,4 +184,3 @@ eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
index 0be122158..f272e1ec8 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
@@ -158,7 +158,7 @@ METHOD(simaka_provider_t, resync, bool,
{
return FALSE;
}
- if (!memeq(macs, xmacs, AKA_MAC_LEN))
+ if (!memeq_const(macs, xmacs, AKA_MAC_LEN))
{
DBG1(DBG_IKE, "received MACS does not match XMACS");
DBG3(DBG_IKE, "MACS %b XMACS %b",
@@ -205,4 +205,3 @@ eap_aka_3gpp2_provider_t *eap_aka_3gpp2_provider_create(
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c
index b2640d104..d314e7a9e 100644
--- a/src/libcharon/plugins/eap_md5/eap_md5.c
+++ b/src/libcharon/plugins/eap_md5/eap_md5.c
@@ -193,7 +193,7 @@ METHOD(eap_method_t, process_server, status_t,
}
response = chunk_create(data.ptr + 6, data.ptr[5]);
if (response.len < expected.len ||
- !memeq(response.ptr, expected.ptr, expected.len))
+ !memeq_const(response.ptr, expected.ptr, expected.len))
{
chunk_free(&expected);
DBG1(DBG_IKE, "EAP-MD5 verification failed");
@@ -299,4 +299,3 @@ eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
index 511506869..f7f39f984 100644
--- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
@@ -812,7 +812,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
goto error;
}
- if (!chunk_equals(this->auth_response, auth_string))
+ if (!chunk_equals_const(this->auth_response, auth_string))
{
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
goto error;
@@ -1087,8 +1087,8 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
userid->destroy(userid);
chunk_clear(&nt_hash);
- if (memeq(res->response.nt_response, this->nt_response.ptr,
- this->nt_response.len))
+ if (memeq_const(res->response.nt_response, this->nt_response.ptr,
+ this->nt_response.len))
{
chunk_t hex;
char msg[AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE)];
@@ -1267,4 +1267,3 @@ eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identificatio
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index ac4ecfc86..cef19305c 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2012 Martin Willi
* Copyright (C) 2012 revosec AG
*
@@ -21,6 +24,7 @@
#include <radius_message.h>
#include <radius_client.h>
#include <daemon.h>
+#include <collections/array.h>
#include <collections/hashtable.h>
#include <threading/mutex.h>
#include <processing/jobs/callback_job.h>
@@ -93,6 +97,62 @@ typedef enum {
} radius_acct_terminate_cause_t;
/**
+ * Usage stats for bytes and packets
+ */
+typedef struct {
+ struct {
+ u_int64_t sent;
+ u_int64_t received;
+ } bytes, packets;
+} usage_t;
+
+/**
+ * Add usage stats (modifies a)
+ */
+static inline void add_usage(usage_t *a, usage_t b)
+{
+ a->bytes.sent += b.bytes.sent;
+ a->bytes.received += b.bytes.received;
+ a->packets.sent += b.packets.sent;
+ a->packets.received += b.packets.received;
+}
+
+/**
+ * Subtract usage stats (modifies a)
+ */
+static inline void sub_usage(usage_t *a, usage_t b)
+{
+ a->bytes.sent -= b.bytes.sent;
+ a->bytes.received -= b.bytes.received;
+ a->packets.sent -= b.packets.sent;
+ a->packets.received -= b.packets.received;
+}
+
+/**
+ * Usage stats for a cached/migrated SAs
+ */
+typedef struct {
+ /** unique CHILD_SA identifier */
+ u_int32_t id;
+ /** usage stats for this SA */
+ usage_t usage;
+} sa_entry_t;
+
+/**
+ * Clone an sa_entry_t
+ */
+static sa_entry_t *clone_sa(sa_entry_t *sa)
+{
+ sa_entry_t *this;
+
+ INIT(this,
+ .id = sa->id,
+ .usage = sa->usage,
+ );
+ return this;
+}
+
+/**
* Hashtable entry with usage stats
*/
typedef struct {
@@ -100,11 +160,12 @@ typedef struct {
ike_sa_id_t *id;
/** RADIUS accounting session ID */
char sid[24];
- /** number of sent/received octets/packets */
- struct {
- u_int64_t sent;
- u_int64_t received;
- } bytes, packets;
+ /** number of sent/received octets/packets for expired SAs */
+ usage_t usage;
+ /** list of cached SAs, sa_entry_t (sorted by their unique ID) */
+ array_t *cached;
+ /** list of migrated SAs, sa_entry_t (sorted by their unique ID) */
+ array_t *migrated;
/** session creation time */
time_t created;
/** terminate cause */
@@ -123,6 +184,8 @@ typedef struct {
*/
static void destroy_entry(entry_t *this)
{
+ array_destroy_function(this->cached, (void*)free, NULL);
+ array_destroy_function(this->migrated, (void*)free, NULL);
this->id->destroy(this->id);
free(this);
}
@@ -155,30 +218,157 @@ static bool equals(ike_sa_id_t *a, ike_sa_id_t *b)
}
/**
+ * Sort cached SAs
+ */
+static int sa_sort(const void *a, const void *b, void *user)
+{
+ const sa_entry_t *ra = a, *rb = b;
+ return ra->id - rb->id;
+}
+
+/**
+ * Find a cached SA
+ */
+static int sa_find(const void *a, const void *b)
+{
+ return sa_sort(a, b, NULL);
+}
+
+/**
+ * Update or create usage counters of a cached SA
+ */
+static void update_sa(entry_t *entry, u_int32_t id, usage_t usage)
+{
+ sa_entry_t *sa, lookup;
+
+ lookup.id = id;
+ if (array_bsearch(entry->cached, &lookup, sa_find, &sa) == -1)
+ {
+ INIT(sa,
+ .id = id,
+ );
+ array_insert_create(&entry->cached, ARRAY_TAIL, sa);
+ array_sort(entry->cached, sa_sort, NULL);
+ }
+ sa->usage = usage;
+}
+
+/**
* Update usage counter when a CHILD_SA rekeys/goes down
*/
static void update_usage(private_eap_radius_accounting_t *this,
ike_sa_t *ike_sa, child_sa_t *child_sa)
{
- u_int64_t bytes_in, bytes_out, packets_in, packets_out;
+ usage_t usage;
entry_t *entry;
- child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, &packets_out);
- child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, &packets_in);
+ child_sa->get_usestats(child_sa, TRUE, NULL, &usage.bytes.received,
+ &usage.packets.received);
+ child_sa->get_usestats(child_sa, FALSE, NULL, &usage.bytes.sent,
+ &usage.packets.sent);
this->mutex->lock(this->mutex);
entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
if (entry)
{
- entry->bytes.sent += bytes_out;
- entry->bytes.received += bytes_in;
- entry->packets.sent += packets_out;
- entry->packets.received += packets_in;
+ update_sa(entry, child_sa->get_unique_id(child_sa), usage);
}
this->mutex->unlock(this->mutex);
}
/**
+ * Collect usage stats for all CHILD_SAs of the given IKE_SA, optionally returns
+ * the total number of bytes and packets
+ */
+static array_t *collect_stats(ike_sa_t *ike_sa, usage_t *total)
+{
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ array_t *stats;
+ sa_entry_t *sa;
+ usage_t usage;
+
+ if (total)
+ {
+ *total = (usage_t){};
+ }
+
+ stats = array_create(0, 0);
+ enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ INIT(sa,
+ .id = child_sa->get_unique_id(child_sa),
+ );
+ array_insert(stats, ARRAY_TAIL, sa);
+ array_sort(stats, sa_sort, NULL);
+
+ child_sa->get_usestats(child_sa, TRUE, NULL, &usage.bytes.received,
+ &usage.packets.received);
+ child_sa->get_usestats(child_sa, FALSE, NULL, &usage.bytes.sent,
+ &usage.packets.sent);
+ sa->usage = usage;
+ if (total)
+ {
+ add_usage(total, usage);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return stats;
+}
+
+/**
+ * Cleanup cached SAs
+ */
+static void cleanup_sas(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
+ entry_t *entry)
+{
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ sa_entry_t *sa, *found;
+ array_t *sas;
+
+ sas = array_create(0, 0);
+ enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ INIT(sa,
+ .id = child_sa->get_unique_id(child_sa),
+ );
+ array_insert(sas, ARRAY_TAIL, sa);
+ array_sort(sas, sa_sort, NULL);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = array_create_enumerator(entry->cached);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ if (array_bsearch(sas, sa, sa_find, &found) == -1)
+ {
+ /* SA is gone, add its latest stats to the total for this IKE_SA
+ * and remove the cache entry */
+ add_usage(&entry->usage, sa->usage);
+ array_remove_at(entry->cached, enumerator);
+ free(sa);
+ }
+ }
+ enumerator->destroy(enumerator);
+ enumerator = array_create_enumerator(entry->migrated);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ if (array_bsearch(sas, sa, sa_find, &found) == -1)
+ {
+ /* SA is gone, subtract stats from the total for this IKE_SA */
+ sub_usage(&entry->usage, sa->usage);
+ array_remove_at(entry->migrated, enumerator);
+ free(sa);
+ }
+ }
+ enumerator->destroy(enumerator);
+ array_destroy_function(sas, (void*)free, NULL);
+}
+
+/**
* Send a RADIUS message, wait for response
*/
static bool send_message(private_eap_radius_accounting_t *this,
@@ -273,17 +463,15 @@ static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
* Get an existing or create a new entry from the locked session table
*/
static entry_t* get_or_create_entry(private_eap_radius_accounting_t *this,
- ike_sa_t *ike_sa)
+ ike_sa_id_t *id, u_int32_t unique)
{
- ike_sa_id_t *id;
entry_t *entry;
time_t now;
- entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
+ entry = this->sessions->get(this->sessions, id);
if (!entry)
{
now = time_monotonic(NULL);
- id = ike_sa->get_id(ike_sa);
INIT(entry,
.id = id->clone(id),
@@ -294,8 +482,7 @@ static entry_t* get_or_create_entry(private_eap_radius_accounting_t *this,
/* default terminate cause, if none other catched */
.cause = ACCT_CAUSE_USER_REQUEST,
);
- snprintf(entry->sid, sizeof(entry->sid), "%u-%u",
- this->prefix, ike_sa->get_unique_id(ike_sa));
+ snprintf(entry->sid, sizeof(entry->sid), "%u-%u", this->prefix, unique);
this->sessions->put(this->sessions, entry->id, entry);
}
return entry;
@@ -330,31 +517,21 @@ void destroy_interim_data(interim_data_t *this)
static job_requeue_t send_interim(interim_data_t *data)
{
private_eap_radius_accounting_t *this = data->this;
- u_int64_t bytes_in = 0, bytes_out = 0, packets_in = 0, packets_out = 0;
- u_int64_t bytes, packets;
+ usage_t usage;
radius_message_t *message = NULL;
enumerator_t *enumerator;
- child_sa_t *child_sa;
ike_sa_t *ike_sa;
entry_t *entry;
u_int32_t value;
+ array_t *stats;
+ sa_entry_t *sa, *found;
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, data->id);
if (!ike_sa)
{
return JOB_REQUEUE_NONE;
}
- enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
- while (enumerator->enumerate(enumerator, &child_sa))
- {
- child_sa->get_usestats(child_sa, FALSE, NULL, &bytes, &packets);
- bytes_out += bytes;
- packets_out += packets;
- child_sa->get_usestats(child_sa, TRUE, NULL, &bytes, &packets);
- bytes_in += bytes;
- packets_in += packets;
- }
- enumerator->destroy(enumerator);
+ stats = collect_stats(ike_sa, &usage);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
/* avoid any races by returning IKE_SA before acquiring lock */
@@ -365,10 +542,45 @@ static job_requeue_t send_interim(interim_data_t *data)
{
entry->interim.last = time_monotonic(NULL);
- bytes_in += entry->bytes.received;
- bytes_out += entry->bytes.sent;
- packets_in += entry->packets.received;
- packets_out += entry->packets.sent;
+ enumerator = array_create_enumerator(entry->cached);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ if (array_bsearch(stats, sa, sa_find, &found) != -1)
+ {
+ /* SA is still around, update stats (e.g. for IKEv1 where
+ * SA might get used even after rekeying) */
+ sa->usage = found->usage;
+ }
+ else
+ {
+ /* SA is gone, add its last stats to the total for this IKE_SA
+ * and remove the cache entry */
+ add_usage(&entry->usage, sa->usage);
+ array_remove_at(entry->cached, enumerator);
+ free(sa);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = array_create_enumerator(entry->migrated);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ if (array_bsearch(stats, sa, sa_find, &found) != -1)
+ {
+ /* SA is still around, but we have to compensate */
+ sub_usage(&usage, sa->usage);
+ }
+ else
+ {
+ /* SA is gone, subtract stats from the total for this IKE_SA */
+ sub_usage(&entry->usage, sa->usage);
+ array_remove_at(entry->migrated, enumerator);
+ free(sa);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ add_usage(&usage, entry->usage);
message = radius_message_create(RMC_ACCOUNTING_REQUEST);
value = htonl(ACCT_STATUS_INTERIM_UPDATE);
@@ -377,26 +589,26 @@ static job_requeue_t send_interim(interim_data_t *data)
chunk_create(entry->sid, strlen(entry->sid)));
add_ike_sa_parameters(this, message, ike_sa);
- value = htonl(bytes_out);
+ value = htonl(usage.bytes.sent);
message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
- value = htonl(bytes_out >> 32);
+ value = htonl(usage.bytes.sent >> 32);
if (value)
{
message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
chunk_from_thing(value));
}
- value = htonl(packets_out);
+ value = htonl(usage.packets.sent);
message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
- value = htonl(bytes_in);
+ value = htonl(usage.bytes.received);
message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
- value = htonl(bytes_in >> 32);
+ value = htonl(usage.bytes.received >> 32);
if (value)
{
message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
chunk_from_thing(value));
}
- value = htonl(packets_in);
+ value = htonl(usage.packets.received);
message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
value = htonl(entry->interim.last - entry->created);
@@ -405,6 +617,7 @@ static job_requeue_t send_interim(interim_data_t *data)
schedule_interim(this, entry);
}
this->mutex->unlock(this->mutex);
+ array_destroy_function(stats, (void*)free, NULL);
if (message)
{
@@ -479,7 +692,8 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
this->mutex->lock(this->mutex);
- entry = get_or_create_entry(this, ike_sa);
+ entry = get_or_create_entry(this, ike_sa->get_id(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
entry->start_sent = TRUE;
message = radius_message_create(RMC_ACCOUNTING_REQUEST);
@@ -515,7 +729,9 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
{
radius_message_t *message;
+ enumerator_t *enumerator;
entry_t *entry;
+ sa_entry_t *sa;
u_int32_t value;
this->mutex->lock(this->mutex);
@@ -528,6 +744,20 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
destroy_entry(entry);
return;
}
+ enumerator = array_create_enumerator(entry->cached);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ add_usage(&entry->usage, sa->usage);
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = array_create_enumerator(entry->migrated);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ sub_usage(&entry->usage, sa->usage);
+ }
+ enumerator->destroy(enumerator);
+
message = radius_message_create(RMC_ACCOUNTING_REQUEST);
value = htonl(ACCT_STATUS_STOP);
message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
@@ -535,26 +765,26 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
chunk_create(entry->sid, strlen(entry->sid)));
add_ike_sa_parameters(this, message, ike_sa);
- value = htonl(entry->bytes.sent);
+ value = htonl(entry->usage.bytes.sent);
message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
- value = htonl(entry->bytes.sent >> 32);
+ value = htonl(entry->usage.bytes.sent >> 32);
if (value)
{
message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
chunk_from_thing(value));
}
- value = htonl(entry->packets.sent);
+ value = htonl(entry->usage.packets.sent);
message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
- value = htonl(entry->bytes.received);
+ value = htonl(entry->usage.bytes.received);
message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
- value = htonl(entry->bytes.received >> 32);
+ value = htonl(entry->usage.bytes.received >> 32);
if (value)
{
message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
chunk_from_thing(value));
}
- value = htonl(entry->packets.received);
+ value = htonl(entry->usage.packets.received);
message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
value = htonl(time_monotonic(NULL) - entry->created);
@@ -660,6 +890,8 @@ METHOD(listener_t, ike_rekey, bool,
/* fire new interim update job, old gets invalid */
schedule_interim(this, entry);
+ cleanup_sas(this, new, entry);
+
entry = this->sessions->put(this->sessions, entry->id, entry);
if (entry)
{
@@ -675,8 +907,64 @@ METHOD(listener_t, child_rekey, bool,
private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
child_sa_t *old, child_sa_t *new)
{
+ entry_t *entry;
+
update_usage(this, ike_sa, old);
+ this->mutex->lock(this->mutex);
+ entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
+ if (entry)
+ {
+ cleanup_sas(this, ike_sa, entry);
+ }
+ this->mutex->unlock(this->mutex);
+ return TRUE;
+}
+
+METHOD(listener_t, children_migrate, bool,
+ private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, ike_sa_id_t *new,
+ u_int32_t unique)
+{
+ enumerator_t *enumerator;
+ sa_entry_t *sa, *sa_new, *cached;
+ entry_t *entry_old, *entry_new;
+ array_t *stats;
+ if (!new)
+ {
+ return TRUE;
+ }
+ stats = collect_stats(ike_sa, NULL);
+ this->mutex->lock(this->mutex);
+ entry_old = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
+ if (entry_old)
+ {
+ entry_new = get_or_create_entry(this, new, unique);
+ enumerator = array_create_enumerator(stats);
+ while (enumerator->enumerate(enumerator, &sa))
+ {
+ /* if the SA was already rekeyed/cached we cache it too on the new
+ * SA to track it properly until it's finally gone */
+ if (array_bsearch(entry_old->cached, sa, sa_find, &cached) != -1)
+ {
+ sa_new = clone_sa(sa);
+ array_insert_create(&entry_new->cached, ARRAY_TAIL, sa_new);
+ array_sort(entry_new->cached, sa_sort, NULL);
+ }
+ /* if the SA was used, we store it to compensate on the new SA */
+ if (sa->usage.bytes.sent || sa->usage.bytes.received ||
+ sa->usage.packets.sent || sa->usage.packets.received)
+ {
+ sa_new = clone_sa(sa);
+ array_insert_create(&entry_new->migrated, ARRAY_TAIL, sa_new);
+ array_sort(entry_new->migrated, sa_sort, NULL);
+ /* store/update latest stats on old SA to report in Stop */
+ update_sa(entry_old, sa->id, sa->usage);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->mutex->unlock(this->mutex);
+ array_destroy_function(stats, (void*)free, NULL);
return TRUE;
}
@@ -717,6 +1005,7 @@ eap_radius_accounting_t *eap_radius_accounting_create()
.message = _message_hook,
.child_updown = _child_updown,
.child_rekey = _child_rekey,
+ .children_migrate = _children_migrate,
},
.destroy = _destroy,
},
@@ -759,7 +1048,8 @@ void eap_radius_accounting_start_interim(ike_sa_t *ike_sa, u_int32_t interval)
DBG1(DBG_CFG, "scheduling RADIUS Interim-Updates every %us", interval);
singleton->mutex->lock(singleton->mutex);
- entry = get_or_create_entry(singleton, ike_sa);
+ entry = get_or_create_entry(singleton, ike_sa->get_id(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
entry->interim.interval = interval;
singleton->mutex->unlock(singleton->mutex);
}
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
index ff96e9279..2637b4314 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
@@ -310,7 +310,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
/* excepting two or three RAND, each 16 bytes. We require two valid
* and different RANDs */
if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
- memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
+ memeq_const(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
{
DBG1(DBG_IKE, "no valid AT_RAND received");
if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
@@ -734,4 +734,3 @@ eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c
index f22266bda..5aa54db3e 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_server.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c
@@ -262,7 +262,7 @@ static status_t process_reauthentication(private_eap_sim_server_t *this,
this->crypto->clear_keys(this->crypto);
return initiate(this, out);
}
- if (!chunk_equals(counter, this->counter))
+ if (!chunk_equals_const(counter, this->counter))
{
DBG1(DBG_IKE, "received counter does not match");
return FAILED;
@@ -644,4 +644,3 @@ eap_sim_server_t *eap_sim_server_create(identification_t *server,
return &this->public;
}
-
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
index bd47e5085..0a6aec083 100644
--- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
@@ -52,7 +52,7 @@ METHOD(simaka_card_t, get_triplet, bool,
c_rand, SIM_RAND_LEN, c_sres, SIM_SRES_LEN, c_kc, SIM_KC_LEN);
if (id->matches(id, cand))
{
- if (memeq(c_rand, rand, SIM_RAND_LEN))
+ if (memeq_const(c_rand, rand, SIM_RAND_LEN))
{
DBG2(DBG_CFG, " => triplet matches");
memcpy(sres, c_sres, SIM_SRES_LEN);
@@ -105,4 +105,3 @@ eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c
index 6c1b3471d..0650f7fd9 100644
--- a/src/libcharon/plugins/ha/ha_cache.c
+++ b/src/libcharon/plugins/ha/ha_cache.c
@@ -43,6 +43,11 @@ struct private_ha_cache_t {
ha_socket_t *socket;
/**
+ * Tunnel securing sync messages
+ */
+ ha_tunnel_t *tunnel;
+
+ /**
* Total number of segments
*/
u_int count;
@@ -259,6 +264,10 @@ static void rekey_segment(private_ha_cache_t *this, u_int segment)
charon->ike_sa_manager, TRUE);
while (enumerator->enumerate(enumerator, &ike_sa))
{
+ if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+ {
+ continue;
+ }
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
this->kernel->get_segment(this->kernel,
ike_sa->get_other_host(ike_sa)) == segment)
@@ -365,7 +374,7 @@ METHOD(ha_cache_t, destroy, void,
* See header
*/
ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
- bool sync, u_int count)
+ ha_tunnel_t *tunnel, bool sync, u_int count)
{
private_ha_cache_t *this;
@@ -379,6 +388,7 @@ ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
.count = count,
.kernel = kernel,
.socket = socket,
+ .tunnel = tunnel,
.cache = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 8),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
);
diff --git a/src/libcharon/plugins/ha/ha_cache.h b/src/libcharon/plugins/ha/ha_cache.h
index 5e3936a20..8cfcbb24c 100644
--- a/src/libcharon/plugins/ha/ha_cache.h
+++ b/src/libcharon/plugins/ha/ha_cache.h
@@ -69,10 +69,11 @@ struct ha_cache_t {
*
* @param kernel kernel helper
* @param socket socket to send resync messages
+ * @param tunnel HA tunnel
* @param resync request a resync during startup?
* @param count total number of segments
*/
ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
- bool resync, u_int count);
+ ha_tunnel_t *tunnel, bool resync, u_int count);
#endif /** HA_CACHE_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c
index a58377bab..037b69bac 100644
--- a/src/libcharon/plugins/ha/ha_plugin.c
+++ b/src/libcharon/plugins/ha/ha_plugin.c
@@ -97,13 +97,73 @@ METHOD(plugin_t, get_name, char*,
}
/**
- * Register listener
+ * Initialize plugin
+ */
+static bool initialize_plugin(private_ha_plugin_t *this)
+{
+ char *local, *remote, *secret;
+ u_int count;
+ bool fifo, monitor, resync;
+
+ local = lib->settings->get_str(lib->settings,
+ "%s.plugins.ha.local", NULL, lib->ns);
+ remote = lib->settings->get_str(lib->settings,
+ "%s.plugins.ha.remote", NULL, lib->ns);
+ secret = lib->settings->get_str(lib->settings,
+ "%s.plugins.ha.secret", NULL, lib->ns);
+ fifo = lib->settings->get_bool(lib->settings,
+ "%s.plugins.ha.fifo_interface", TRUE, lib->ns);
+ monitor = lib->settings->get_bool(lib->settings,
+ "%s.plugins.ha.monitor", TRUE, lib->ns);
+ resync = lib->settings->get_bool(lib->settings,
+ "%s.plugins.ha.resync", TRUE, lib->ns);
+ count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
+ "%s.plugins.ha.segment_count", 1, lib->ns));
+ if (!local || !remote)
+ {
+ DBG1(DBG_CFG, "HA config misses local/remote address");
+ return FALSE;
+ }
+
+ if (secret)
+ {
+ this->tunnel = ha_tunnel_create(local, remote, secret);
+ }
+ this->socket = ha_socket_create(local, remote);
+ if (!this->socket)
+ {
+ return FALSE;
+ }
+ this->kernel = ha_kernel_create(count);
+ this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
+ count, strcmp(local, remote) > 0, monitor);
+ this->cache = ha_cache_create(this->kernel, this->socket, this->tunnel,
+ resync, count);
+ if (fifo)
+ {
+ this->ctl = ha_ctl_create(this->segments, this->cache);
+ }
+ this->attr = ha_attribute_create(this->kernel, this->segments);
+ this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
+ this->cache, this->kernel, this->attr);
+ this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
+ this->child = ha_child_create(this->socket, this->tunnel, this->segments,
+ this->kernel);
+ return TRUE;
+}
+
+/**
+ * Initialize plugin and register listener
*/
static bool plugin_cb(private_ha_plugin_t *this,
plugin_feature_t *feature, bool reg, void *cb_data)
{
if (reg)
{
+ if (!initialize_plugin(this))
+ {
+ return FALSE;
+ }
charon->bus->add_listener(charon->bus, &this->segments->listener);
charon->bus->add_listener(charon->bus, &this->ike->listener);
charon->bus->add_listener(charon->bus, &this->child->listener);
@@ -127,6 +187,7 @@ METHOD(plugin_t, get_features, int,
static plugin_feature_t f[] = {
PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
PLUGIN_PROVIDE(CUSTOM, "ha"),
+ PLUGIN_SDEPEND(CUSTOM, "kernel-ipsec"),
};
*features = f;
return countof(f);
@@ -136,14 +197,14 @@ METHOD(plugin_t, destroy, void,
private_ha_plugin_t *this)
{
DESTROY_IF(this->ctl);
- this->ike->destroy(this->ike);
- this->child->destroy(this->child);
- this->dispatcher->destroy(this->dispatcher);
- this->attr->destroy(this->attr);
- this->cache->destroy(this->cache);
- this->segments->destroy(this->segments);
- this->kernel->destroy(this->kernel);
- this->socket->destroy(this->socket);
+ DESTROY_IF(this->ike);
+ DESTROY_IF(this->child);
+ DESTROY_IF(this->dispatcher);
+ DESTROY_IF(this->attr);
+ DESTROY_IF(this->cache);
+ DESTROY_IF(this->segments);
+ DESTROY_IF(this->kernel);
+ DESTROY_IF(this->socket);
DESTROY_IF(this->tunnel);
free(this);
}
@@ -154,29 +215,6 @@ METHOD(plugin_t, destroy, void,
plugin_t *ha_plugin_create()
{
private_ha_plugin_t *this;
- char *local, *remote, *secret;
- u_int count;
- bool fifo, monitor, resync;
-
- local = lib->settings->get_str(lib->settings,
- "%s.plugins.ha.local", NULL, lib->ns);
- remote = lib->settings->get_str(lib->settings,
- "%s.plugins.ha.remote", NULL, lib->ns);
- secret = lib->settings->get_str(lib->settings,
- "%s.plugins.ha.secret", NULL, lib->ns);
- fifo = lib->settings->get_bool(lib->settings,
- "%s.plugins.ha.fifo_interface", TRUE, lib->ns);
- monitor = lib->settings->get_bool(lib->settings,
- "%s.plugins.ha.monitor", TRUE, lib->ns);
- resync = lib->settings->get_bool(lib->settings,
- "%s.plugins.ha.resync", TRUE, lib->ns);
- count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
- "%s.plugins.ha.segment_count", 1, lib->ns));
- if (!local || !remote)
- {
- DBG1(DBG_CFG, "HA config misses local/remote address");
- return NULL;
- }
if (!lib->caps->keep(lib->caps, CAP_CHOWN))
{ /* required to chown(2) control socket, ha_kernel also needs it at
@@ -195,31 +233,5 @@ plugin_t *ha_plugin_create()
},
);
- if (secret)
- {
- this->tunnel = ha_tunnel_create(local, remote, secret);
- }
- this->socket = ha_socket_create(local, remote);
- if (!this->socket)
- {
- DESTROY_IF(this->tunnel);
- free(this);
- return NULL;
- }
- this->kernel = ha_kernel_create(count);
- this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
- count, strcmp(local, remote) > 0, monitor);
- this->cache = ha_cache_create(this->kernel, this->socket, resync, count);
- if (fifo)
- {
- this->ctl = ha_ctl_create(this->segments, this->cache);
- }
- this->attr = ha_attribute_create(this->kernel, this->segments);
- this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
- this->cache, this->kernel, this->attr);
- this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
- this->child = ha_child_create(this->socket, this->tunnel, this->segments,
- this->kernel);
-
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/vici/libvici.h b/src/libcharon/plugins/vici/libvici.h
index 641370efd..3ca9de424 100644
--- a/src/libcharon/plugins/vici/libvici.h
+++ b/src/libcharon/plugins/vici/libvici.h
@@ -2,15 +2,26 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
+ * libvici.h is MIT-licensed to simplify reuse, but please note that libvici.c
+ * is not, as it depends on the GPLv2 licensed libstrongswan.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
*/
/**
diff --git a/src/libcharon/plugins/vici/python/Makefile.am b/src/libcharon/plugins/vici/python/Makefile.am
index f51737870..5936f2a5e 100644
--- a/src/libcharon/plugins/vici/python/Makefile.am
+++ b/src/libcharon/plugins/vici/python/Makefile.am
@@ -8,25 +8,27 @@ EXTRA_DIST = LICENSE MANIFEST.in \
vici/protocol.py \
vici/session.py
-setup.py: $(srcdir)/setup.py.in
+$(srcdir)/setup.py: $(srcdir)/setup.py.in
$(AM_V_GEN) sed \
-e "s:@EGG_VERSION@:$(PACKAGE_VERSION):" \
$(srcdir)/setup.py.in > $@
all-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
-dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) setup.py
+dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) $(srcdir)/setup.py
(cd $(srcdir); $(PYTHON) setup.py bdist_egg \
-b $(shell readlink -f $(builddir))/build \
-d $(shell readlink -f $(builddir))/dist)
-clean-local: setup.py
- $(PYTHON) setup.py clean -a
- rm -rf vici.egg-info dist setup.py
+clean-local:
+ (cd $(srcdir); [ ! -f setup.py ] || $(PYTHON) setup.py clean -a)
+ rm -rf $(srcdir)/setup.py $(srcdir)/vici.egg-info $(builddir)/dist
+if PYTHON_EGGS_INSTALL
install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
$(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \
dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
+endif
if USE_PY_TEST
TESTS = $(PY_TEST)
diff --git a/src/libcharon/plugins/vici/python/Makefile.in b/src/libcharon/plugins/vici/python/Makefile.in
index 3a5e5ea72..eb4bab6ca 100644
--- a/src/libcharon/plugins/vici/python/Makefile.in
+++ b/src/libcharon/plugins/vici/python/Makefile.in
@@ -579,6 +579,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+@PYTHON_EGGS_INSTALL_FALSE@install-exec-local:
clean: clean-am
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
@@ -661,25 +662,25 @@ uninstall-am:
tags-am uninstall uninstall-am
-setup.py: $(srcdir)/setup.py.in
+$(srcdir)/setup.py: $(srcdir)/setup.py.in
$(AM_V_GEN) sed \
-e "s:@EGG_VERSION@:$(PACKAGE_VERSION):" \
$(srcdir)/setup.py.in > $@
all-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
-dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) setup.py
+dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) $(srcdir)/setup.py
(cd $(srcdir); $(PYTHON) setup.py bdist_egg \
-b $(shell readlink -f $(builddir))/build \
-d $(shell readlink -f $(builddir))/dist)
-clean-local: setup.py
- $(PYTHON) setup.py clean -a
- rm -rf vici.egg-info dist setup.py
+clean-local:
+ (cd $(srcdir); [ ! -f setup.py ] || $(PYTHON) setup.py clean -a)
+ rm -rf $(srcdir)/setup.py $(srcdir)/vici.egg-info $(builddir)/dist
-install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
- $(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \
- dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
+@PYTHON_EGGS_INSTALL_TRUE@install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
+@PYTHON_EGGS_INSTALL_TRUE@ $(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \
+@PYTHON_EGGS_INSTALL_TRUE@ dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.am b/src/libcharon/plugins/vici/ruby/Makefile.am
index 3e12f86cc..e2d340431 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.am
+++ b/src/libcharon/plugins/vici/ruby/Makefile.am
@@ -15,10 +15,12 @@ all-local: vici-$(PACKAGE_VERSION).gem
clean-local:
rm -f vici.gemspec vici-$(PACKAGE_VERSION).gem
+if RUBY_GEMS_INSTALL
install-data-local: vici-$(PACKAGE_VERSION).gem
- $(GEM) install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ $(GEM) install --no-user-install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
vici-$(PACKAGE_VERSION).gem
uninstall-local:
$(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
--version $(PACKAGE_VERSION) vici
+endif
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in
index f37c09ea2..bf81e5395 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.in
+++ b/src/libcharon/plugins/vici/ruby/Makefile.in
@@ -453,6 +453,8 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+@RUBY_GEMS_INSTALL_FALSE@uninstall-local:
+@RUBY_GEMS_INSTALL_FALSE@install-data-local:
clean: clean-am
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
@@ -550,13 +552,13 @@ all-local: vici-$(PACKAGE_VERSION).gem
clean-local:
rm -f vici.gemspec vici-$(PACKAGE_VERSION).gem
-install-data-local: vici-$(PACKAGE_VERSION).gem
- $(GEM) install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
- vici-$(PACKAGE_VERSION).gem
+@RUBY_GEMS_INSTALL_TRUE@install-data-local: vici-$(PACKAGE_VERSION).gem
+@RUBY_GEMS_INSTALL_TRUE@ $(GEM) install --no-user-install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+@RUBY_GEMS_INSTALL_TRUE@ vici-$(PACKAGE_VERSION).gem
-uninstall-local:
- $(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
- --version $(PACKAGE_VERSION) vici
+@RUBY_GEMS_INSTALL_TRUE@uninstall-local:
+@RUBY_GEMS_INSTALL_TRUE@ $(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+@RUBY_GEMS_INSTALL_TRUE@ --version $(PACKAGE_VERSION) vici
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index 649161020..d23259912 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -13,6 +13,28 @@
* for more details.
*/
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#define _GNU_SOURCE
#include "vici_config.h"
@@ -1460,6 +1482,21 @@ CALLBACK(peer_sn, bool,
return FALSE;
}
+ if (!auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY))
+ {
+ identification_t *id;
+ certificate_t *cert;
+
+ cert = auth.cfg->get(auth.cfg, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ id = cert->get_subject(cert);
+ DBG1(DBG_CFG, " id not specified, defaulting to cert id '%Y'",
+ id);
+ auth.cfg->add(auth.cfg, AUTH_RULE_IDENTITY, id->clone(id));
+ }
+ }
+
if (strcasepfx(name, "local"))
{
peer->local->insert_last(peer->local, auth.cfg);
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.c b/src/libcharon/plugins/vici/vici_dispatcher.c
index 6db36fbe0..31292d6b3 100644
--- a/src/libcharon/plugins/vici/vici_dispatcher.c
+++ b/src/libcharon/plugins/vici/vici_dispatcher.c
@@ -13,6 +13,28 @@
* for more details.
*/
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "vici_dispatcher.h"
#include "vici_socket.h"
@@ -446,6 +468,24 @@ METHOD(vici_dispatcher_t, manage_event, void,
this->mutex->unlock(this->mutex);
}
+METHOD(vici_dispatcher_t, has_event_listeners, bool,
+ private_vici_dispatcher_t *this, char *name)
+{
+ bool retval = FALSE;
+
+ this->mutex->lock(this->mutex);
+ if (this->events->get(this->events, name))
+ {
+ /* the entry might be getting destroyed, but returning
+ * false positive is not a problem as a later raise_event
+ * will check things again. */
+ retval = TRUE;
+ }
+ this->mutex->unlock(this->mutex);
+
+ return retval;
+}
+
METHOD(vici_dispatcher_t, raise_event, void,
private_vici_dispatcher_t *this, char *name, u_int id,
vici_message_t *message)
@@ -504,6 +544,7 @@ vici_dispatcher_t *vici_dispatcher_create(char *uri)
.public = {
.manage_command = _manage_command,
.manage_event = _manage_event,
+ .has_event_listeners = _has_event_listeners,
.raise_event = _raise_event,
.destroy = _destroy,
},
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.h b/src/libcharon/plugins/vici/vici_dispatcher.h
index 2297a80bd..e48cf3bd1 100644
--- a/src/libcharon/plugins/vici/vici_dispatcher.h
+++ b/src/libcharon/plugins/vici/vici_dispatcher.h
@@ -13,6 +13,28 @@
* for more details.
*/
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
/**
* @defgroup vici_dispatcher vici_dispatcher
* @{ @ingroup vici
@@ -96,6 +118,17 @@ struct vici_dispatcher_t {
void (*manage_event)(vici_dispatcher_t *this, char *name, bool reg);
/**
+ * Check if an event has listeners.
+ *
+ * This can be used to check if a vici message needs to be generated or not,
+ * as in some cases the generation can be a heavy operation.
+ *
+ * @param name event name to check
+ * @return TRUE if event has listeners
+ */
+ bool (*has_event_listeners)(vici_dispatcher_t *this, char *name);
+
+ /**
* Raise an event to a specific or all clients registered to that event.
*
* @param name event name to raise
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
index af8bd283b..7ae58a317 100644
--- a/src/libcharon/plugins/vici/vici_plugin.c
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -13,6 +13,28 @@
* for more details.
*/
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "vici_plugin.h"
#include "vici_dispatcher.h"
#include "vici_query.h"
@@ -106,12 +128,14 @@ static bool register_vici(private_vici_plugin_t *this,
charon->attributes->add_provider(charon->attributes,
&this->attrs->provider);
charon->bus->add_logger(charon->bus, &this->logger->logger);
+ charon->bus->add_listener(charon->bus, &this->query->listener);
return TRUE;
}
return FALSE;
}
else
{
+ charon->bus->remove_listener(charon->bus, &this->query->listener);
charon->bus->remove_logger(charon->bus, &this->logger->logger);
charon->attributes->remove_provider(charon->attributes,
&this->attrs->provider);
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index 3e0d73cdf..d94d760b9 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -13,6 +13,28 @@
* for more details.
*/
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include "vici_query.h"
#include "vici_builder.h"
@@ -1008,6 +1030,8 @@ static void manage_commands(private_vici_query_t *this, bool reg)
this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
+ this->dispatcher->manage_event(this->dispatcher, "ike-updown", reg);
+ this->dispatcher->manage_event(this->dispatcher, "child-updown", reg);
manage_command(this, "list-sas", list_sas, reg);
manage_command(this, "list-policies", list_policies, reg);
manage_command(this, "list-conns", list_conns, reg);
@@ -1016,6 +1040,63 @@ static void manage_commands(private_vici_query_t *this, bool reg)
manage_command(this, "stats", stats, reg);
}
+METHOD(listener_t, ike_updown, bool,
+ private_vici_query_t *this, ike_sa_t *ike_sa, bool up)
+{
+ vici_builder_t *b;
+ time_t now;
+
+ if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-updown"))
+ {
+ return TRUE;
+ }
+
+ now = time_monotonic(NULL);
+
+ b = vici_builder_create();
+ b->begin_section(b, ike_sa->get_name(ike_sa));
+ list_ike(this, b, ike_sa, now);
+ b->begin_section(b, "child-sas");
+ b->end_section(b);
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher,
+ "ike-updown", 0, b->finalize(b));
+
+ return TRUE;
+}
+
+METHOD(listener_t, child_updown, bool,
+ private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
+{
+ vici_builder_t *b;
+ time_t now;
+
+ if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-updown"))
+ {
+ return TRUE;
+ }
+
+ now = time_monotonic(NULL);
+ b = vici_builder_create();
+
+ b->begin_section(b, ike_sa->get_name(ike_sa));
+ list_ike(this, b, ike_sa, now);
+ b->begin_section(b, "child-sas");
+
+ b->begin_section(b, child_sa->get_name(child_sa));
+ list_child(this, b, child_sa, now);
+ b->end_section(b);
+
+ b->end_section(b);
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher,
+ "child-updown", 0, b->finalize(b));
+
+ return TRUE;
+}
+
METHOD(vici_query_t, destroy, void,
private_vici_query_t *this)
{
@@ -1032,6 +1113,10 @@ vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
INIT(this,
.public = {
+ .listener = {
+ .ike_updown = _ike_updown,
+ .child_updown = _child_updown,
+ },
.destroy = _destroy,
},
.dispatcher = dispatcher,
diff --git a/src/libcharon/plugins/vici/vici_query.h b/src/libcharon/plugins/vici/vici_query.h
index da72b1411..0149e8d4f 100644
--- a/src/libcharon/plugins/vici/vici_query.h
+++ b/src/libcharon/plugins/vici/vici_query.h
@@ -13,11 +13,34 @@
* for more details.
*/
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
/**
* @defgroup vici_query vici_query
* @{ @ingroup vici
*/
+#include <bus/listeners/listener.h>
#include "vici_dispatcher.h"
#ifndef VICI_QUERY_H_
@@ -31,6 +54,11 @@ typedef struct vici_query_t vici_query_t;
struct vici_query_t {
/**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
* Destroy a vici_query_t.
*/
void (*destroy)(vici_query_t *this);
diff --git a/src/libcharon/plugins/vici/vici_socket.c b/src/libcharon/plugins/vici/vici_socket.c
index 916772871..67fd7e8e3 100644
--- a/src/libcharon/plugins/vici/vici_socket.c
+++ b/src/libcharon/plugins/vici/vici_socket.c
@@ -118,6 +118,8 @@ typedef struct {
array_t *queue;
/** do we have job processing input queue? */
bool has_processor;
+ /** is this client disconnecting */
+ bool disconnecting;
/** client connection identifier */
u_int id;
/** any users reading over this connection? */
@@ -187,6 +189,10 @@ static entry_t* find_entry(private_vici_socket_t *this, stream_t *stream,
continue;
}
}
+ if (entry->disconnecting)
+ {
+ continue;
+ }
candidate = TRUE;
if ((reader && entry->readers) ||
@@ -304,7 +310,7 @@ static void disconnect(private_vici_socket_t *this, u_int id)
* Write queued output data
*/
static bool do_write(private_vici_socket_t *this, entry_t *entry,
- stream_t *stream)
+ stream_t *stream, char *errmsg, size_t errlen)
{
msg_buf_t *out;
ssize_t len;
@@ -326,7 +332,8 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
{
return TRUE;
}
- DBG1(DBG_CFG, "vici header write error: %s", strerror(errno));
+ snprintf(errmsg, errlen, "vici header write error: %s",
+ strerror(errno));
return FALSE;
}
out->hdrlen += len;
@@ -339,7 +346,7 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
out->buf.len - out->done, FALSE);
if (len == 0)
{
- DBG1(DBG_CFG, "premature vici disconnect");
+ snprintf(errmsg, errlen, "premature vici disconnect");
return FALSE;
}
if (len < 0)
@@ -348,7 +355,7 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
{
return TRUE;
}
- DBG1(DBG_CFG, "vici write error: %s", strerror(errno));
+ snprintf(errmsg, errlen, "vici write error: %s", strerror(errno));
return FALSE;
}
out->done += len;
@@ -369,13 +376,14 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
CALLBACK(on_write, bool,
private_vici_socket_t *this, stream_t *stream)
{
+ char errmsg[256] = "";
entry_t *entry;
bool ret = FALSE;
entry = find_entry(this, stream, 0, FALSE, TRUE);
if (entry)
{
- ret = do_write(this, entry, stream);
+ ret = do_write(this, entry, stream, errmsg, sizeof(errmsg));
if (ret)
{
/* unregister if we have no more messages to send */
@@ -383,9 +391,15 @@ CALLBACK(on_write, bool,
}
else
{
+ entry->disconnecting = TRUE;
disconnect(entry->this, entry->id);
}
put_entry(this, entry, FALSE, TRUE);
+
+ if (!ret && errmsg[0])
+ {
+ DBG1(DBG_CFG, errmsg);
+ }
}
return ret;
@@ -395,7 +409,7 @@ CALLBACK(on_write, bool,
* Read in available header with data, non-blocking cumulating to buffer
*/
static bool do_read(private_vici_socket_t *this, entry_t *entry,
- stream_t *stream)
+ stream_t *stream, char *errmsg, size_t errlen)
{
u_int32_t msglen;
ssize_t len;
@@ -415,7 +429,8 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
{
return TRUE;
}
- DBG1(DBG_CFG, "vici header read error: %s", strerror(errno));
+ snprintf(errmsg, errlen, "vici header read error: %s",
+ strerror(errno));
return FALSE;
}
entry->in.hdrlen += len;
@@ -424,8 +439,8 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
msglen = untoh32(entry->in.hdr);
if (msglen > VICI_MESSAGE_SIZE_MAX)
{
- DBG1(DBG_CFG, "vici message length %u exceeds %u bytes limit, "
- "ignored", msglen, VICI_MESSAGE_SIZE_MAX);
+ snprintf(errmsg, errlen, "vici message length %u exceeds %u "
+ "bytes limit, ignored", msglen, VICI_MESSAGE_SIZE_MAX);
return FALSE;
}
/* header complete, continue with data */
@@ -440,7 +455,7 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
entry->in.buf.len - entry->in.done, FALSE);
if (len == 0)
{
- DBG1(DBG_CFG, "premature vici disconnect");
+ snprintf(errmsg, errlen, "premature vici disconnect");
return FALSE;
}
if (len < 0)
@@ -449,7 +464,7 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
{
return TRUE;
}
- DBG1(DBG_CFG, "vici read error: %s", strerror(errno));
+ snprintf(errmsg, errlen, "vici read error: %s", strerror(errno));
return FALSE;
}
entry->in.done += len;
@@ -502,6 +517,7 @@ CALLBACK(process_queue, job_requeue_t,
CALLBACK(on_read, bool,
private_vici_socket_t *this, stream_t *stream)
{
+ char errmsg[256] = "";
entry_selector_t *sel;
entry_t *entry;
bool ret = FALSE;
@@ -509,9 +525,10 @@ CALLBACK(on_read, bool,
entry = find_entry(this, stream, 0, TRUE, FALSE);
if (entry)
{
- ret = do_read(this, entry, stream);
+ ret = do_read(this, entry, stream, errmsg, sizeof(errmsg));
if (!ret)
{
+ entry->disconnecting = TRUE;
disconnect(this, entry->id);
}
else if (entry->in.hdrlen == sizeof(entry->in.hdr) &&
@@ -534,6 +551,11 @@ CALLBACK(on_read, bool,
}
}
put_entry(this, entry, TRUE, FALSE);
+
+ if (!ret && errmsg[0])
+ {
+ DBG1(DBG_CFG, errmsg);
+ }
}
return ret;
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic.c b/src/libcharon/plugins/xauth_generic/xauth_generic.c
index c37da0cb0..e65d1a1fe 100644
--- a/src/libcharon/plugins/xauth_generic/xauth_generic.c
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic.c
@@ -180,7 +180,7 @@ METHOD(xauth_method_t, process_server, status_t,
SHARED_EAP, this->server, this->peer);
while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
{
- if (chunk_equals(shared->get_key(shared), pass))
+ if (chunk_equals_const(shared->get_key(shared), pass))
{
status = SUCCESS;
break;