From a34ffd1c05ae7b32c953a83addbf0a135b141205 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 3 Jan 2013 14:09:05 +0100 Subject: [PATCH 1/3] Add a chunk_from_str() initializer that does not include 0-terminator --- src/libstrongswan/utils/chunk.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index 67848eec1..bc14b7394 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -190,6 +190,11 @@ static inline void chunk_clear(chunk_t *chunk) */ #define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing)) +/** + * Initialize a chunk from a static string, not containing 0-terminator + */ +#define chunk_from_str(str) chunk_create(str, strlen(str)) + /** * Allocate a chunk on the heap */ From d022322bed29e0b6d1ca09edb891402d7e2cc73f Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 15 Mar 2013 10:41:04 +0100 Subject: [PATCH 2/3] Add connection name specific stroke counters --- src/libcharon/plugins/stroke/stroke_counter.c | 135 +++++++++++++++++- src/libcharon/plugins/stroke/stroke_counter.h | 3 +- src/libcharon/plugins/stroke/stroke_socket.c | 21 ++- src/stroke/stroke.c | 26 +++- src/stroke/stroke_keywords.h | 3 +- src/stroke/stroke_keywords.txt | 2 +- src/stroke/stroke_msg.h | 11 +- 7 files changed, 181 insertions(+), 20 deletions(-) diff --git a/src/libcharon/plugins/stroke/stroke_counter.c b/src/libcharon/plugins/stroke/stroke_counter.c index 56eda945a..e64415f5d 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 +#include ENUM(stroke_counter_type_names, COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP, @@ -55,16 +56,111 @@ 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; + + 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]++; + } +} + +/** + * Get a counter value for a specific connection name + */ +static u_int64_t get_named_count(private_stroke_counter_t *this, + char *name, stroke_counter_type_t type) +{ + entry_t *entry; + + entry = this->conns->get(this->conns, name); + if (entry) + { + return entry->counter[type]; + } + return 0; +} + METHOD(listener_t, alert, bool, private_stroke_counter_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args) @@ -86,6 +182,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 +206,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 +218,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,13 +293,14 @@ 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) + private_stroke_counter_t *this, FILE *out, char *name) { u_int64_t counter[COUNTER_MAX]; int i; @@ -209,11 +309,25 @@ METHOD(stroke_counter_t, print, void, this->lock->lock(this->lock); for (i = 0; i < countof(this->counter); i++) { - counter[i] = this->counter[i]; + if (name) + { + counter[i] = get_named_count(this, name, i); + } + else + { + counter[i] = this->counter[i]; + } } this->lock->unlock(this->lock); - fprintf(out, "\nList of IKE counters:\n\n"); + if (name) + { + fprintf(out, "\nList of IKE counters for '%s':\n\n", name); + } + else + { + fprintf(out, "\nList of IKE counters:\n\n"); + } /* but do blocking write without the lock. */ for (i = 0; i < countof(this->counter); i++) @@ -225,6 +339,17 @@ METHOD(stroke_counter_t, print, void, 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); } @@ -247,6 +372,8 @@ stroke_counter_t *stroke_counter_create() .print = _print, .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..b39fcb8dd 100644 --- a/src/libcharon/plugins/stroke/stroke_counter.h +++ b/src/libcharon/plugins/stroke/stroke_counter.h @@ -87,8 +87,9 @@ 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); /** * Destroy a stroke_counter_t. diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 2771f0146..ebb3c723d 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); - } } /** @@ -504,6 +501,17 @@ static void stroke_user_creds(private_stroke_socket_t *this, this->config->set_user_credentials(this->config, msg, out); } +/** + * 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); + + this->counter->print(this->counter, out, msg->counters.name); +} + /** * set the verbosity debug output */ @@ -665,6 +673,8 @@ 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); default: DBG1(DBG_CFG, "received unknown stroke"); break; @@ -855,4 +865,3 @@ stroke_socket_t *stroke_socket_create() return &this->public; } - diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index e289296c1..1be275c28 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -266,7 +266,6 @@ static int list_flags[] = { LIST_OCSP, LIST_ALGS, LIST_PLUGINS, - LIST_COUNTERS, LIST_ALL }; @@ -365,6 +364,16 @@ static int user_credentials(char *name, char *user, char *pass) return send_stroke_msg(&msg); } +static int counters(char *name) +{ + stroke_msg_t msg; + + msg.type = STR_COUNTERS; + msg.length = offsetof(stroke_msg_t, buffer); + msg.counters.name = push_string(&msg, name); + return send_stroke_msg(&msg); +} + static int set_loglevel(char *type, u_int level) { stroke_msg_t msg; @@ -419,7 +428,7 @@ static void exit_usage(char *error) printf(" Show list of authority and attribute certificates:\n"); printf(" stroke listcacerts|listocspcerts|listaacerts|listacerts\n"); printf(" Show list of end entity certificates, ca info records and crls:\n"); - printf(" stroke listcerts|listcainfos|listcrls|listcounters|listall\n"); + printf(" stroke listcerts|listcainfos|listcrls|listall\n"); printf(" Show list of supported algorithms:\n"); printf(" stroke listalgs\n"); printf(" Reload authority and attribute certificates:\n"); @@ -445,6 +454,8 @@ static void exit_usage(char *error) printf(" where: NAME is a connection name added with \"stroke add\"\n"); printf(" USERNAME is the username\n"); printf(" PASSWORD is the optional password, you'll be asked to enter it if not given\n"); + printf(" Show IKE counters:\n"); + printf(" stroke listcounters [connection-name]\n"); exit_error(error); } @@ -553,7 +564,6 @@ int main(int argc, char *argv[]) case STROKE_LIST_OCSP: case STROKE_LIST_ALGS: case STROKE_LIST_PLUGINS: - case STROKE_LIST_COUNTERS: case STROKE_LIST_ALL: res = list(token->kw, argc > 2 && strcmp(argv[2], "--utc") == 0); break; @@ -594,6 +604,16 @@ int main(int argc, char *argv[]) } res = user_credentials(argv[2], argv[3], argc > 4 ? argv[4] : NULL); break; + case STROKE_COUNTERS: + if (argc > 2) + { + res = counters(argv[2]); + } + else + { + res = counters(NULL); + } + break; default: exit_usage(NULL); } diff --git a/src/stroke/stroke_keywords.h b/src/stroke/stroke_keywords.h index 0ad87b705..12abce1d3 100644 --- a/src/stroke/stroke_keywords.h +++ b/src/stroke/stroke_keywords.h @@ -42,7 +42,6 @@ typedef enum { STROKE_LIST_OCSP, STROKE_LIST_ALGS, STROKE_LIST_PLUGINS, - STROKE_LIST_COUNTERS, STROKE_LIST_ALL, STROKE_REREAD_SECRETS, STROKE_REREAD_CACERTS, @@ -59,6 +58,7 @@ typedef enum { STROKE_LEASES, STROKE_MEMUSAGE, STROKE_USER_CREDS, + STROKE_COUNTERS, } stroke_keyword_t; #define STROKE_LIST_FIRST STROKE_LIST_PUBKEYS @@ -71,4 +71,3 @@ typedef struct stroke_token stroke_token_t; extern const stroke_token_t* in_word_set(register const char *str, register unsigned int len); #endif /* _STROKE_KEYWORDS_H_ */ - diff --git a/src/stroke/stroke_keywords.txt b/src/stroke/stroke_keywords.txt index 95b2981d9..12c590962 100644 --- a/src/stroke/stroke_keywords.txt +++ b/src/stroke/stroke_keywords.txt @@ -49,7 +49,6 @@ listcrls, STROKE_LIST_CRLS listocsp, STROKE_LIST_OCSP listalgs, STROKE_LIST_ALGS listplugins, STROKE_LIST_PLUGINS -listcounters, STROKE_LIST_COUNTERS listall, STROKE_LIST_ALL rereadsecrets, STROKE_REREAD_SECRETS rereadcacerts, STROKE_REREAD_CACERTS @@ -66,3 +65,4 @@ exportx509, STROKE_EXPORT_X509 leases, STROKE_LEASES memusage, STROKE_MEMUSAGE user-creds, STROKE_USER_CREDS +listcounters, STROKE_COUNTERS diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index e972a5984..494acba11 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -67,10 +67,8 @@ enum list_flag_t { LIST_ALGS = 0x0400, /** list plugin information */ LIST_PLUGINS = 0x0800, - /** list IKE counters */ - LIST_COUNTERS = 0x1000, /** all list options */ - LIST_ALL = 0x1FFF, + LIST_ALL = 0x0FFF, }; typedef enum reread_flag_t reread_flag_t; @@ -225,6 +223,8 @@ struct stroke_msg_t { STR_MEMUSAGE, /* set username and password for a connection */ STR_USER_CREDS, + /* print counters */ + STR_COUNTERS, /* more to come */ } type; @@ -354,6 +354,11 @@ struct stroke_msg_t { char *username; char *password; } user_creds; + + /* data for STR_COUNTERS */ + struct { + char *name; + } counters; }; char buffer[STROKE_BUF_LEN]; }; From cf729248b28473b9651e347741d351cf0d34892f Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 15 Mar 2013 10:55:22 +0100 Subject: [PATCH 3/3] Add a "resetcounters" command to ipsec, clearing global or connection counters --- src/ipsec/_ipsec.in | 7 +++--- src/libcharon/plugins/stroke/stroke_counter.c | 22 +++++++++++++++++++ src/libcharon/plugins/stroke/stroke_counter.h | 7 ++++++ src/libcharon/plugins/stroke/stroke_socket.c | 10 ++++++++- src/stroke/stroke.c | 15 +++++-------- src/stroke/stroke_keywords.h | 1 + src/stroke/stroke_keywords.txt | 1 + src/stroke/stroke_msg.h | 4 +++- 8 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/ipsec/_ipsec.in b/src/ipsec/_ipsec.in index 8b6ad660d..6b406f6d9 100644 --- a/src/ipsec/_ipsec.in +++ b/src/ipsec/_ipsec.in @@ -59,7 +59,8 @@ case "$1" in echo " listalgs|listpubkeys|listcerts [--utc]" echo " listcacerts|listaacerts|listocspcerts [--utc]" echo " listacerts|listgroups|listcainfos [--utc]" - echo " listcrls|listocsp|listcards|listplugins|listcounters|listall [--utc]" + echo " listcrls|listocsp|listcards|listplugins|listall [--utc]" + echo " listcounters|resetcounters [name]" echo " leases [ [
]]" echo " rereadsecrets|rereadgroups" echo " rereadcacerts|rereadaacerts|rereadocspcerts" @@ -149,10 +150,10 @@ leases) listalgs|listpubkeys|listplugins|\ listcerts|listcacerts|listaacerts|\ listacerts|listgroups|listocspcerts|\ -listcainfos|listcrls|listocsp|listcounters|listall|\ +listcainfos|listcrls|listocsp|listall|\ rereadsecrets|rereadcacerts|rereadaacerts|\ rereadacerts|rereadocspcerts|rereadcrls|\ -rereadall|purgeocsp) +rereadall|purgeocsp|listcounters|resetcounters) op="$1" rc=7 shift diff --git a/src/libcharon/plugins/stroke/stroke_counter.c b/src/libcharon/plugins/stroke/stroke_counter.c index e64415f5d..ff4746bf4 100644 --- a/src/libcharon/plugins/stroke/stroke_counter.c +++ b/src/libcharon/plugins/stroke/stroke_counter.c @@ -336,6 +336,27 @@ METHOD(stroke_counter_t, print, void, } } +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) { @@ -370,6 +391,7 @@ stroke_counter_t *stroke_counter_create() .message = _message_hook, }, .print = _print, + .reset = _reset, .destroy = _destroy, }, .conns = hashtable_create((hashtable_hash_t)hash, diff --git a/src/libcharon/plugins/stroke/stroke_counter.h b/src/libcharon/plugins/stroke/stroke_counter.h index b39fcb8dd..fecf39f56 100644 --- a/src/libcharon/plugins/stroke/stroke_counter.h +++ b/src/libcharon/plugins/stroke/stroke_counter.h @@ -91,6 +91,13 @@ struct stroke_counter_t { */ 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_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index ebb3c723d..7d41682fb 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -509,7 +509,14 @@ static void stroke_counters(private_stroke_socket_t *this, { pop_string(msg, &msg->counters.name); - this->counter->print(this->counter, out, 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); + } } /** @@ -675,6 +682,7 @@ static job_requeue_t process(stroke_job_context_t *ctx) break; case STR_COUNTERS: stroke_counters(this, msg, out); + break; default: DBG1(DBG_CFG, "received unknown stroke"); break; diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index 1be275c28..c8c8e7cf7 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -364,13 +364,15 @@ static int user_credentials(char *name, char *user, char *pass) return send_stroke_msg(&msg); } -static int counters(char *name) +static int counters(int reset, char *name) { stroke_msg_t msg; msg.type = STR_COUNTERS; msg.length = offsetof(stroke_msg_t, buffer); msg.counters.name = push_string(&msg, name); + msg.counters.reset = reset; + return send_stroke_msg(&msg); } @@ -605,14 +607,9 @@ int main(int argc, char *argv[]) res = user_credentials(argv[2], argv[3], argc > 4 ? argv[4] : NULL); break; case STROKE_COUNTERS: - if (argc > 2) - { - res = counters(argv[2]); - } - else - { - res = counters(NULL); - } + case STROKE_COUNTERS_RESET: + res = counters(token->kw == STROKE_COUNTERS_RESET, + argc > 2 ? argv[2] : NULL); break; default: exit_usage(NULL); diff --git a/src/stroke/stroke_keywords.h b/src/stroke/stroke_keywords.h index 12abce1d3..f5979a0e5 100644 --- a/src/stroke/stroke_keywords.h +++ b/src/stroke/stroke_keywords.h @@ -59,6 +59,7 @@ typedef enum { STROKE_MEMUSAGE, STROKE_USER_CREDS, STROKE_COUNTERS, + STROKE_COUNTERS_RESET, } stroke_keyword_t; #define STROKE_LIST_FIRST STROKE_LIST_PUBKEYS diff --git a/src/stroke/stroke_keywords.txt b/src/stroke/stroke_keywords.txt index 12c590962..5d2ebd9e2 100644 --- a/src/stroke/stroke_keywords.txt +++ b/src/stroke/stroke_keywords.txt @@ -66,3 +66,4 @@ leases, STROKE_LEASES memusage, STROKE_MEMUSAGE user-creds, STROKE_USER_CREDS listcounters, STROKE_COUNTERS +resetcounters, STROKE_COUNTERS_RESET diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index 494acba11..c415a92c3 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -223,7 +223,7 @@ struct stroke_msg_t { STR_MEMUSAGE, /* set username and password for a connection */ STR_USER_CREDS, - /* print counters */ + /* print/reset counters */ STR_COUNTERS, /* more to come */ } type; @@ -357,6 +357,8 @@ struct stroke_msg_t { /* data for STR_COUNTERS */ struct { + /* reset or print counters? */ + int reset; char *name; } counters; };