summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/stroke
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins/stroke')
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in33
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c79
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c100
-rw-r--r--src/libcharon/plugins/stroke/stroke_counter.c222
-rw-r--r--src/libcharon/plugins/stroke/stroke_counter.h10
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c49
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c19
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c44
8 files changed, 459 insertions, 97 deletions
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 38924708a..77497e2b9 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -16,6 +16,23 @@
@SET_MAKE@
VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -109,6 +126,11 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libstrongswan_stroke_la_SOURCES)
DIST_SOURCES = $(libstrongswan_stroke_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -125,6 +147,8 @@ BTLIB = @BTLIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CHECK_CFLAGS = @CHECK_CFLAGS@
+CHECK_LIBS = @CHECK_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -141,6 +165,7 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -209,8 +234,6 @@ am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
attest_plugins = @attest_plugins@
-axis2c_CFLAGS = @axis2c_CFLAGS@
-axis2c_LIBS = @axis2c_LIBS@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
@@ -266,7 +289,6 @@ nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
openac_plugins = @openac_plugins@
-p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
@@ -368,7 +390,6 @@ clean-noinstLTLIBRARIES:
done
install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@@ -376,6 +397,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
}
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 9f6124dc9..86f0fe431 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -234,7 +234,8 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
msg->add_conn.other.address,
msg->add_conn.other.allow_any,
msg->add_conn.other.ikeport,
- msg->add_conn.fragmentation);
+ msg->add_conn.fragmentation,
+ msg->add_conn.ikedscp);
add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
return ike_cfg;
}
@@ -447,39 +448,43 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
identity = identification_create_from_string(id);
if (cert)
{
- certificate = this->cred->load_peer(this->cred, cert);
- if (certificate)
+ enumerator_t *enumerator;
+ bool has_subject = FALSE;
+ certificate_t *first = NULL;
+
+ enumerator = enumerator_create_token(cert, ",", " ");
+ while (enumerator->enumerate(enumerator, &cert))
{
- if (local)
- {
- this->ca->check_for_hash_and_url(this->ca, certificate);
- }
- cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
- if (identity->get_type(identity) == ID_ANY ||
- !certificate->has_subject(certificate, identity))
+ certificate = this->cred->load_peer(this->cred, cert);
+ if (certificate)
{
- DBG1(DBG_CFG, " id '%Y' not confirmed by certificate, "
- "defaulting to '%Y'", identity,
- certificate->get_subject(certificate));
- identity->destroy(identity);
- identity = certificate->get_subject(certificate);
- identity = identity->clone(identity);
+ if (local)
+ {
+ this->ca->check_for_hash_and_url(this->ca, certificate);
+ }
+ cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
+ if (!first)
+ {
+ first = certificate;
+ }
+ if (identity->get_type(identity) != ID_ANY &&
+ certificate->has_subject(certificate, identity))
+ {
+ has_subject = TRUE;
+ }
}
}
- }
- if (identity->get_type(identity) != ID_ANY)
- {
- cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
- if (loose)
+ enumerator->destroy(enumerator);
+
+ if (first && !has_subject)
{
- cfg->add(cfg, AUTH_RULE_IDENTITY_LOOSE, TRUE);
+ DBG1(DBG_CFG, " id '%Y' not confirmed by certificate, "
+ "defaulting to '%Y'", identity, first->get_subject(first));
+ identity->destroy(identity);
+ identity = first->get_subject(first);
+ identity = identity->clone(identity);
}
}
- else
- {
- identity->destroy(identity);
- }
-
/* add raw RSA public key */
pubkey = end->rsakey;
if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert"))
@@ -491,6 +496,18 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
}
}
+ if (identity->get_type(identity) != ID_ANY)
+ {
+ cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
+ if (loose)
+ {
+ cfg->add(cfg, AUTH_RULE_IDENTITY_LOOSE, TRUE);
+ }
+ }
+ else
+ {
+ identity->destroy(identity);
+ }
/* CA constraint */
if (ca)
@@ -877,7 +894,7 @@ static void add_ts(private_stroke_config_t *this,
if (end->tohost)
{
ts = traffic_selector_create_dynamic(end->protocol,
- end->port ? end->port : 0, end->port ? end->port : 65535);
+ end->from_port, end->to_port);
child_cfg->add_traffic_selector(child_cfg, local, ts);
}
else
@@ -890,7 +907,7 @@ static void add_ts(private_stroke_config_t *this,
if (net)
{
ts = traffic_selector_create_from_subnet(net, 0, end->protocol,
- end->port);
+ end->from_port, end->to_port);
child_cfg->add_traffic_selector(child_cfg, local, ts);
}
}
@@ -902,8 +919,8 @@ static void add_ts(private_stroke_config_t *this,
enumerator = enumerator_create_token(end->subnets, ",", " ");
while (enumerator->enumerate(enumerator, &subnet))
{
- ts = traffic_selector_create_from_cidr(subnet,
- end->protocol, end->port);
+ ts = traffic_selector_create_from_cidr(subnet, end->protocol,
+ end->from_port, end->to_port);
if (ts)
{
child_cfg->add_traffic_selector(child_cfg, local, ts);
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 233d4088f..91130d1ee 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -33,6 +33,11 @@ struct private_stroke_control_t {
* public functions
*/
stroke_control_t public;
+
+ /**
+ * Timeout for stroke commands, im ms
+ */
+ u_int timeout;
};
@@ -97,8 +102,8 @@ static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
/**
* call the charon controller to initiate the connection
*/
-static void charon_initiate(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
- stroke_msg_t *msg, FILE *out)
+static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg,
+ child_cfg_t *child_cfg, stroke_msg_t *msg, FILE *out)
{
if (msg->output_verbosity < 0)
{
@@ -108,9 +113,27 @@ static void charon_initiate(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
else
{
stroke_log_info_t info = { msg->output_verbosity, out };
+ status_t status;
- charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- (controller_cb_t)stroke_log, &info, 0);
+ status = charon->controller->initiate(charon->controller,
+ peer_cfg, child_cfg, (controller_cb_t)stroke_log,
+ &info, this->timeout);
+ switch (status)
+ {
+ case SUCCESS:
+ fprintf(out, "connection '%s' established successfully\n",
+ msg->initiate.name);
+ break;
+ case OUT_OF_RES:
+ fprintf(out, "connection '%s' not established after %dms, "
+ "detaching\n", msg->initiate.name, this->timeout);
+ break;
+ default:
+ case FAILED:
+ fprintf(out, "establishing connection '%s' failed\n",
+ msg->initiate.name);
+ break;
+ }
}
}
@@ -133,7 +156,7 @@ METHOD(stroke_control_t, initiate, void,
while (enumerator->enumerate(enumerator, &child_cfg))
{
empty = FALSE;
- charon_initiate(peer_cfg->get_ref(peer_cfg),
+ charon_initiate(this, peer_cfg->get_ref(peer_cfg),
child_cfg->get_ref(child_cfg), msg, out);
}
enumerator->destroy(enumerator);
@@ -169,7 +192,7 @@ METHOD(stroke_control_t, initiate, void,
return;
}
}
- charon_initiate(peer_cfg, child_cfg, msg, out);
+ charon_initiate(this, peer_cfg, child_cfg, msg, out);
}
/**
@@ -239,6 +262,41 @@ static bool parse_specifier(char *string, u_int32_t *id,
return TRUE;
}
+/**
+ * Report the result of a terminate() call to console
+ */
+static void report_terminate_status(private_stroke_control_t *this,
+ status_t status, FILE *out, u_int32_t id, bool child)
+{
+ char *prefix, *postfix;
+
+ if (child)
+ {
+ prefix = "CHILD_SA {";
+ postfix = "}";
+ }
+ else
+ {
+ prefix = "IKE_SA [";
+ postfix = "]";
+ }
+
+ switch (status)
+ {
+ case SUCCESS:
+ fprintf(out, "%s%d%s closed successfully\n", prefix, id, postfix);
+ break;
+ case OUT_OF_RES:
+ fprintf(out, "%s%d%s not closed after %dms, detaching\n",
+ prefix, id, postfix, this->timeout);
+ break;
+ default:
+ case FAILED:
+ fprintf(out, "closing %s%d%s failed\n", prefix, id, postfix);
+ break;
+ }
+}
+
METHOD(stroke_control_t, terminate, void,
private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
@@ -250,6 +308,7 @@ METHOD(stroke_control_t, terminate, void,
linked_list_t *ike_list, *child_list;
stroke_log_info_t info;
uintptr_t del;
+ status_t status;
if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
{
@@ -264,15 +323,15 @@ METHOD(stroke_control_t, terminate, void,
{
if (child)
{
- charon->controller->terminate_child(charon->controller, id,
- (controller_cb_t)stroke_log, &info, 0);
+ status = charon->controller->terminate_child(charon->controller, id,
+ (controller_cb_t)stroke_log, &info, this->timeout);
}
else
{
- charon->controller->terminate_ike(charon->controller, id,
- (controller_cb_t)stroke_log, &info, 0);
+ status = charon->controller->terminate_ike(charon->controller, id,
+ (controller_cb_t)stroke_log, &info, this->timeout);
}
- return;
+ return report_terminate_status(this, status, out, id, child);
}
ike_list = linked_list_create();
@@ -320,16 +379,18 @@ METHOD(stroke_control_t, terminate, void,
enumerator = child_list->create_enumerator(child_list);
while (enumerator->enumerate(enumerator, &del))
{
- charon->controller->terminate_child(charon->controller, del,
- (controller_cb_t)stroke_log, &info, 0);
+ status = charon->controller->terminate_child(charon->controller, del,
+ (controller_cb_t)stroke_log, &info, this->timeout);
+ report_terminate_status(this, status, out, del, TRUE);
}
enumerator->destroy(enumerator);
enumerator = ike_list->create_enumerator(ike_list);
while (enumerator->enumerate(enumerator, &del))
{
- charon->controller->terminate_ike(charon->controller, del,
- (controller_cb_t)stroke_log, &info, 0);
+ status = charon->controller->terminate_ike(charon->controller, del,
+ (controller_cb_t)stroke_log, &info, this->timeout);
+ report_terminate_status(this, status, out, del, FALSE);
}
enumerator->destroy(enumerator);
@@ -487,6 +548,7 @@ METHOD(stroke_control_t, purge_ike, void,
linked_list_t *list;
uintptr_t del;
stroke_log_info_t info;
+ status_t status;
info.out = out;
info.level = msg->output_verbosity;
@@ -509,8 +571,9 @@ METHOD(stroke_control_t, purge_ike, void,
enumerator = list->create_enumerator(list);
while (enumerator->enumerate(enumerator, &del))
{
- charon->controller->terminate_ike(charon->controller, del,
- (controller_cb_t)stroke_log, &info, 0);
+ status = charon->controller->terminate_ike(charon->controller, del,
+ (controller_cb_t)stroke_log, &info, this->timeout);
+ report_terminate_status(this, status, out, del, TRUE);
}
enumerator->destroy(enumerator);
list->destroy(list);
@@ -670,8 +733,9 @@ stroke_control_t *stroke_control_create()
.unroute = _unroute,
.destroy = _destroy,
},
+ .timeout = lib->settings->get_int(lib->settings,
+ "%s.plugins.stroke.timeout", 0, charon->name),
);
return &this->public;
}
-
diff --git a/src/libcharon/plugins/stroke/stroke_counter.c b/src/libcharon/plugins/stroke/stroke_counter.c
index 56eda945a..5fa1fb165 100644
--- a/src/libcharon/plugins/stroke/stroke_counter.c
+++ b/src/libcharon/plugins/stroke/stroke_counter.c
@@ -16,6 +16,7 @@
#include "stroke_counter.h"
#include <threading/spinlock.h>
+#include <collections/hashtable.h>
ENUM(stroke_counter_type_names,
COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP,
@@ -55,16 +56,98 @@ struct private_stroke_counter_t {
stroke_counter_t public;
/**
- * Counter values
+ * Global counter values
*/
u_int64_t counter[COUNTER_MAX];
/**
+ * Counters for specific connection names, char* => entry_t
+ */
+ hashtable_t *conns;
+
+ /**
* Lock for counter values
*/
spinlock_t *lock;
};
+/**
+ * Counters for a specific connection name
+ */
+typedef struct {
+ /** connection name */
+ char *name;
+ /** counter values for connection */
+ u_int64_t counter[COUNTER_MAX];
+} entry_t;
+
+/**
+ * Destroy named entry
+ */
+static void destroy_entry(entry_t *this)
+{
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Hashtable hash function
+ */
+static u_int hash(char *name)
+{
+ return chunk_hash(chunk_from_str(name));
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool equals(char *a, char *b)
+{
+ return streq(a, b);
+}
+
+/**
+ * Get the name of an IKE_SA, but return NULL if it is not known yet
+ */
+static char *get_ike_sa_name(ike_sa_t *ike_sa)
+{
+ peer_cfg_t *peer_cfg;
+
+ if (ike_sa)
+ {
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ if (peer_cfg)
+ {
+ return peer_cfg->get_name(peer_cfg);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Increase a counter for a named entry
+ */
+static void count_named(private_stroke_counter_t *this,
+ ike_sa_t *ike_sa, stroke_counter_type_t type)
+{
+ entry_t *entry;
+ char *name;
+
+ name = get_ike_sa_name(ike_sa);
+ if (name)
+ {
+ entry = this->conns->get(this->conns, name);
+ if (!entry)
+ {
+ INIT(entry,
+ .name = strdup(name),
+ );
+ this->conns->put(this->conns, entry->name, entry);
+ }
+ entry->counter[type]++;
+ }
+}
+
METHOD(listener_t, alert, bool,
private_stroke_counter_t *this, ike_sa_t *ike_sa,
alert_t alert, va_list args)
@@ -86,6 +169,7 @@ METHOD(listener_t, alert, bool,
this->lock->lock(this->lock);
this->counter[type]++;
+ count_named(this, ike_sa, type);
this->lock->unlock(this->lock);
return TRUE;
@@ -109,6 +193,7 @@ METHOD(listener_t, ike_rekey, bool,
this->lock->lock(this->lock);
this->counter[type]++;
+ count_named(this, old, type);
this->lock->unlock(this->lock);
return TRUE;
@@ -120,6 +205,7 @@ METHOD(listener_t, child_rekey, bool,
{
this->lock->lock(this->lock);
this->counter[COUNTER_CHILD_SA_REKEY]++;
+ count_named(this, ike_sa, COUNTER_CHILD_SA_REKEY);
this->lock->unlock(this->lock);
return TRUE;
@@ -194,18 +280,94 @@ METHOD(listener_t, message_hook, bool,
this->lock->lock(this->lock);
this->counter[type]++;
+ count_named(this, ike_sa, type);
this->lock->unlock(this->lock);
return TRUE;
}
-METHOD(stroke_counter_t, print, void,
- private_stroke_counter_t *this, FILE *out)
+/**
+ * Print a single counter value to out
+ */
+static void print_counter(FILE *out, stroke_counter_type_t type,
+ u_int64_t counter)
+{
+ fprintf(out, "%-18N %12llu\n", stroke_counter_type_names, type, counter);
+}
+
+/**
+ * Print IKE counters for a specific connection
+ */
+static void print_one(private_stroke_counter_t *this, FILE *out, char *name)
+{
+ u_int64_t counter[COUNTER_MAX];
+ entry_t *entry;
+ int i;
+
+ this->lock->lock(this->lock);
+ entry = this->conns->get(this->conns, name);
+ if (entry)
+ {
+ for (i = 0; i < countof(this->counter); i++)
+ {
+ counter[i] = entry->counter[i];
+ }
+ }
+ this->lock->unlock(this->lock);
+
+ if (entry)
+ {
+ fprintf(out, "\nList of IKE counters for '%s':\n\n", name);
+ for (i = 0; i < countof(this->counter); i++)
+ {
+ print_counter(out, i, counter[i]);
+ }
+ }
+ else
+ {
+ fprintf(out, "No IKE counters found for '%s'\n", name);
+ }
+}
+
+/**
+ * Print counters for all connections
+ */
+static void print_all(private_stroke_counter_t *this, FILE *out)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ linked_list_t *list;
+ char *name;
+
+ list = linked_list_create();
+
+ this->lock->lock(this->lock);
+ enumerator = this->conns->create_enumerator(this->conns);
+ while (enumerator->enumerate(enumerator, &name, &entry))
+ {
+ list->insert_last(list, strdup(name));
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ print_one(this, out, name);
+ }
+ enumerator->destroy(enumerator);
+
+ list->destroy_function(list, free);
+}
+
+/**
+ * Print global counters
+ */
+static void print_global(private_stroke_counter_t *this, FILE *out)
{
u_int64_t counter[COUNTER_MAX];
int i;
- /* Take a snapshot to have congruent results, */
this->lock->lock(this->lock);
for (i = 0; i < countof(this->counter); i++)
{
@@ -215,16 +377,61 @@ METHOD(stroke_counter_t, print, void,
fprintf(out, "\nList of IKE counters:\n\n");
- /* but do blocking write without the lock. */
for (i = 0; i < countof(this->counter); i++)
{
- fprintf(out, "%-18N %12llu\n", stroke_counter_type_names, i, counter[i]);
+ print_counter(out, i, counter[i]);
}
}
+METHOD(stroke_counter_t, print, void,
+ private_stroke_counter_t *this, FILE *out, char *name)
+{
+ if (name)
+ {
+ if (streq(name, "all"))
+ {
+ return print_all(this, out);
+ }
+ return print_one(this, out, name);
+ }
+ return print_global(this, out);
+}
+
+METHOD(stroke_counter_t, reset, void,
+ private_stroke_counter_t *this, char *name)
+{
+ this->lock->lock(this->lock);
+ if (name)
+ {
+ entry_t *entry;
+
+ entry = this->conns->remove(this->conns, name);
+ if (entry)
+ {
+ destroy_entry(entry);
+ }
+ }
+ else
+ {
+ memset(&this->counter, 0, sizeof(this->counter));
+ }
+ this->lock->unlock(this->lock);
+}
+
METHOD(stroke_counter_t, destroy, void,
private_stroke_counter_t *this)
{
+ enumerator_t *enumerator;
+ char *name;
+ entry_t *entry;
+
+ enumerator = this->conns->create_enumerator(this->conns);
+ while (enumerator->enumerate(enumerator, &name, &entry))
+ {
+ destroy_entry(entry);
+ }
+ enumerator->destroy(enumerator);
+ this->conns->destroy(this->conns);
this->lock->destroy(this->lock);
free(this);
}
@@ -245,8 +452,11 @@ stroke_counter_t *stroke_counter_create()
.message = _message_hook,
},
.print = _print,
+ .reset = _reset,
.destroy = _destroy,
},
+ .conns = hashtable_create((hashtable_hash_t)hash,
+ (hashtable_equals_t)equals, 4),
.lock = spinlock_create(),
);
diff --git a/src/libcharon/plugins/stroke/stroke_counter.h b/src/libcharon/plugins/stroke/stroke_counter.h
index efaae0d6f..fecf39f56 100644
--- a/src/libcharon/plugins/stroke/stroke_counter.h
+++ b/src/libcharon/plugins/stroke/stroke_counter.h
@@ -87,8 +87,16 @@ struct stroke_counter_t {
* Print counter values to an output stream.
*
* @param out output stream to write to
+ * @param name connection name to get counters for, NULL for global
*/
- void (*print)(stroke_counter_t *this, FILE *out);
+ void (*print)(stroke_counter_t *this, FILE *out, char *name);
+
+ /**
+ * Reset global or connection specific counters.
+ *
+ * @param name name of connection counters to reset, NULL for global
+ */
+ void (*reset)(stroke_counter_t *this, char *name);
/**
* Destroy a stroke_counter_t.
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index c401bc6f1..eda746f7e 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -701,7 +701,7 @@ static shared_key_t* pin_cb(pin_cb_data_t *data, shared_key_type_t type,
/**
* Load a smartcard with a PIN
*/
-static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
+static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr,
FILE *prompt)
{
chunk_t sc = chunk_empty, secret = chunk_empty;
@@ -796,7 +796,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
if (key)
{
DBG1(DBG_CFG, " loaded private key from %.*s", (int)sc.len, sc.ptr);
- this->creds->add_key(this->creds, key);
+ secrets->add_key(secrets, key);
}
return TRUE;
}
@@ -804,7 +804,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
/**
* Load a private key
*/
-static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
+static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr,
FILE *prompt, key_type_t key_type)
{
char path[PATH_MAX];
@@ -894,7 +894,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
{
DBG1(DBG_CFG, " loaded %N private key from '%s'",
key_type_names, key->get_type(key), path);
- this->creds->add_key(this->creds, key);
+ secrets->add_key(secrets, key);
}
else
{
@@ -906,7 +906,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
/**
* Load a shared key
*/
-static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr,
+static bool load_shared(mem_cred_t *secrets, chunk_t line, int line_nr,
shared_key_type_t type, chunk_t ids)
{
shared_key_t *shared_key;
@@ -961,15 +961,15 @@ static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr,
owners->insert_last(owners,
identification_create_from_encoding(ID_ANY, chunk_empty));
}
- this->creds->add_shared_list(this->creds, shared_key, owners);
+ secrets->add_shared_list(secrets, shared_key, owners);
return TRUE;
}
/**
* reload ipsec.secrets
*/
-static void load_secrets(private_stroke_cred_t *this, char *file, int level,
- FILE *prompt)
+static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets,
+ char *file, int level, FILE *prompt)
{
int line_nr = 0, fd;
chunk_t src, line;
@@ -991,6 +991,11 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
close(fd);
return;
}
+ if (sb.st_size == 0)
+ { /* skip empty files, as mmap() complains */
+ close(fd);
+ return;
+ }
addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED)
{
@@ -1000,9 +1005,9 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
}
src = chunk_create(addr, sb.st_size);
- if (level == 0)
- { /* flush secrets on non-recursive invocation */
- this->creds->clear_secrets(this->creds);
+ if (!secrets)
+ {
+ secrets = mem_cred_create();
}
while (fetchline(&src, &line))
@@ -1072,14 +1077,15 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
{
for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
{
- load_secrets(this, *expanded, level + 1, prompt);
+ load_secrets(this, secrets, *expanded, level + 1,
+ prompt);
}
}
globfree(&buf);
}
#else /* HAVE_GLOB_H */
/* if glob(3) is not available, try to load pattern directly */
- load_secrets(this, pattern, level + 1, prompt);
+ load_secrets(this, secrets, pattern, level + 1, prompt);
#endif /* HAVE_GLOB_H */
continue;
}
@@ -1109,7 +1115,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
}
if (match("RSA", &token) || match("ECDSA", &token))
{
- if (!load_private(this, line, line_nr, prompt,
+ if (!load_private(secrets, line, line_nr, prompt,
match("RSA", &token) ? KEY_RSA : KEY_ECDSA))
{
break;
@@ -1117,7 +1123,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
}
else if (match("PIN", &token))
{
- if (!load_pin(this, line, line_nr, prompt))
+ if (!load_pin(secrets, line, line_nr, prompt))
{
break;
}
@@ -1127,7 +1133,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
(match("NTLM", &token) && (type = SHARED_NT_HASH)) ||
(match("XAUTH", &token) && (type = SHARED_EAP)))
{
- if (!load_shared(this, line, line_nr, type, ids))
+ if (!load_shared(secrets, line, line_nr, type, ids))
{
break;
}
@@ -1141,6 +1147,12 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level,
}
munmap(addr, sb.st_size);
close(fd);
+
+ if (level == 0)
+ { /* replace secrets in active credential set */
+ this->creds->replace_secrets(this->creds, secrets, FALSE);
+ secrets->destroy(secrets);
+ }
}
/**
@@ -1175,7 +1187,7 @@ METHOD(stroke_cred_t, reread, void,
if (msg->reread.flags & REREAD_SECRETS)
{
DBG1(DBG_CFG, "rereading secrets");
- load_secrets(this, SECRETS_FILE, 0, prompt);
+ load_secrets(this, NULL, SECRETS_FILE, 0, prompt);
}
if (msg->reread.flags & REREAD_CACERTS)
{
@@ -1258,8 +1270,7 @@ stroke_cred_t *stroke_cred_create()
FALSE, charon->name);
load_certs(this);
- load_secrets(this, SECRETS_FILE, 0, NULL);
+ load_secrets(this, NULL, SECRETS_FILE, 0, NULL);
return &this->public;
}
-
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index b3a20a6c7..a2e1c80a5 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -205,7 +205,7 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
{
time_t use_in, use_out, rekey, now;
- u_int64_t bytes_in, bytes_out;
+ u_int64_t bytes_in, bytes_out, packets_in, packets_out;
proposal_t *proposal;
child_cfg_t *config = child_sa->get_config(child_sa);
@@ -273,18 +273,24 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
}
}
- child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in);
+ child_sa->get_usestats(child_sa, TRUE,
+ &use_in, &bytes_in, &packets_in);
fprintf(out, ", %" PRIu64 " bytes_i", bytes_in);
if (use_in)
{
- fprintf(out, " (%" PRIu64 "s ago)", (u_int64_t)(now - use_in));
+ fprintf(out, " (%" PRIu64 " pkt%s, %" PRIu64 "s ago)",
+ packets_in, (packets_in == 1) ? "": "s",
+ (u_int64_t)(now - use_in));
}
- child_sa->get_usestats(child_sa, FALSE, &use_out, &bytes_out);
+ child_sa->get_usestats(child_sa, FALSE,
+ &use_out, &bytes_out, &packets_out);
fprintf(out, ", %" PRIu64 " bytes_o", bytes_out);
if (use_out)
{
- fprintf(out, " (%" PRIu64 "s ago)", (u_int64_t)(now - use_out));
+ fprintf(out, " (%" PRIu64 " pkt%s, %" PRIu64 "s ago)",
+ packets_out, (packets_out == 1) ? "": "s",
+ (u_int64_t)(now - use_out));
}
fprintf(out, ", rekeying ");
@@ -1242,7 +1248,7 @@ static void list_algs(FILE *out)
int len;
fprintf(out, "\n");
- fprintf(out, "List of registered IKEv2 Algorithms:\n");
+ fprintf(out, "List of registered IKE algorithms:\n");
fprintf(out, "\n encryption:");
len = 13;
enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
@@ -1541,4 +1547,3 @@ stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
return &this->public;
}
-
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 2771f0146..aa5c73b8b 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -388,17 +388,14 @@ static void stroke_status(private_stroke_socket_t *this,
/**
* list various information
*/
-static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
+ FILE *out)
{
if (msg->list.flags & LIST_CAINFOS)
{
this->ca->list(this->ca, msg, out);
}
this->list->list(this->list, msg, out);
- if (msg->list.flags & LIST_COUNTERS)
- {
- this->counter->print(this->counter, out);
- }
}
/**
@@ -505,6 +502,24 @@ static void stroke_user_creds(private_stroke_socket_t *this,
}
/**
+ * Print stroke counter values
+ */
+static void stroke_counters(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->counters.name);
+
+ if (msg->counters.reset)
+ {
+ this->counter->reset(this->counter, msg->counters.name);
+ }
+ else
+ {
+ this->counter->print(this->counter, out, msg->counters.name);
+ }
+}
+
+/**
* set the verbosity debug output
*/
static void stroke_loglevel(private_stroke_socket_t *this,
@@ -516,11 +531,18 @@ static void stroke_loglevel(private_stroke_socket_t *this,
DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
msg->loglevel.level, msg->loglevel.type);
- group = enum_from_name(debug_names, msg->loglevel.type);
- if ((int)group < 0)
+ if (strcaseeq(msg->loglevel.type, "any"))
{
- fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
- return;
+ group = DBG_ANY;
+ }
+ else
+ {
+ group = enum_from_name(debug_names, msg->loglevel.type);
+ if ((int)group < 0)
+ {
+ fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
+ return;
+ }
}
charon->set_level(charon, group, msg->loglevel.level);
}
@@ -665,6 +687,9 @@ static job_requeue_t process(stroke_job_context_t *ctx)
case STR_USER_CREDS:
stroke_user_creds(this, msg, out);
break;
+ case STR_COUNTERS:
+ stroke_counters(this, msg, out);
+ break;
default:
DBG1(DBG_CFG, "received unknown stroke");
break;
@@ -855,4 +880,3 @@ stroke_socket_t *stroke_socket_create()
return &this->public;
}
-