aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-08-07 17:06:36 +0200
committerMartin Willi <martin@revosec.ch>2013-09-04 10:49:48 +0200
commit1fd5c7fbac3d63970cba763bc63890828f8ace7d (patch)
tree927c35c99837e514536810980e53b233ecf8d86c
parent47b4a5140262fb2659053040901cc15c5b1d5e1e (diff)
downloadstrongswan-1fd5c7fbac3d63970cba763bc63890828f8ace7d.tar.bz2
strongswan-1fd5c7fbac3d63970cba763bc63890828f8ace7d.tar.xz
load-tester: support extended traffic selector syntax, as in leftsubnet
In addition the initiator may use %unique as port, using a distinct port for each connection, starting from 1025.
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c181
1 files changed, 168 insertions, 13 deletions
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index 1c915cdbc..f544912e6 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -15,12 +15,16 @@
#include "load_tester_config.h"
+#include <netdb.h>
+
#include <daemon.h>
#include <hydra.h>
#include <attributes/mem_pool.h>
#include <collections/hashtable.h>
#include <threading/mutex.h>
+#define UNIQUE_PORT_START 1025
+
typedef struct private_load_tester_config_t private_load_tester_config_t;
/**
@@ -119,6 +123,11 @@ struct private_load_tester_config_t {
char *responder_tsr;
/**
+ * Current port for unique initiator ports
+ */
+ u_int16_t unique_port;
+
+ /**
* IKE_SA rekeying delay
*/
u_int ike_rekey;
@@ -422,27 +431,172 @@ static void generate_auth_cfg(private_load_tester_config_t *this, char *str,
}
/**
+ * Parse a protoport specifier
+ */
+static bool parse_protoport(char *token, u_int16_t *from_port,
+ u_int16_t *to_port, u_int8_t *protocol)
+{
+ char *sep, *port = "", *endptr;
+ struct protoent *proto;
+ struct servent *svc;
+ long int p;
+
+ sep = strrchr(token, ']');
+ if (!sep)
+ {
+ return FALSE;
+ }
+ *sep = '\0';
+
+ sep = strchr(token, '/');
+ if (sep)
+ { /* protocol/port */
+ *sep = '\0';
+ port = sep + 1;
+ }
+
+ if (streq(token, "%any"))
+ {
+ *protocol = 0;
+ }
+ else
+ {
+ proto = getprotobyname(token);
+ if (proto)
+ {
+ *protocol = proto->p_proto;
+ }
+ else
+ {
+ p = strtol(token, &endptr, 0);
+ if ((*token && *endptr) || p < 0 || p > 0xff)
+ {
+ return FALSE;
+ }
+ *protocol = (u_int8_t)p;
+ }
+ }
+ if (streq(port, "%any"))
+ {
+ *from_port = 0;
+ *to_port = 0xffff;
+ }
+ else if (streq(port, "%opaque"))
+ {
+ *from_port = 0xffff;
+ *to_port = 0;
+ }
+ else if (streq(port, "%unique"))
+ {
+ *from_port = *to_port = 0;
+ }
+ else if (*port)
+ {
+ svc = getservbyname(port, NULL);
+ if (svc)
+ {
+ *from_port = *to_port = ntohs(svc->s_port);
+ }
+ else
+ {
+ p = strtol(port, &endptr, 0);
+ if (p < 0 || p > 0xffff)
+ {
+ return FALSE;
+ }
+ *from_port = p;
+ if (*endptr == '-')
+ {
+ port = endptr + 1;
+ p = strtol(port, &endptr, 0);
+ if (p < 0 || p > 0xffff)
+ {
+ return FALSE;
+ }
+ }
+ *to_port = p;
+ if (*endptr)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
* Add a TS from a string to a child_cfg
*/
-static void add_ts(char *string, child_cfg_t *cfg, bool local)
+static void add_ts(private_load_tester_config_t *this,
+ char *string, child_cfg_t *cfg, bool local, bool initiator)
{
traffic_selector_t *ts;
if (string)
{
- ts = traffic_selector_create_from_cidr(string, 0, 0, 65535);
- if (!ts)
+ enumerator_t *enumerator;
+ char *subnet, *pos;
+ u_int16_t from_port, to_port;
+ u_int8_t proto;
+
+ enumerator = enumerator_create_token(string, ",", " ");
+ while (enumerator->enumerate(enumerator, &subnet))
{
- DBG1(DBG_CFG, "parsing TS string '%s' failed", string);
+ proto = 0;
+ from_port = 0;
+ to_port = 65535;
+
+ pos = strchr(subnet, '[');
+ if (pos)
+ {
+ *(pos++) = '\0';
+ if (!parse_protoport(pos, &from_port, &to_port, &proto))
+ {
+ DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet",
+ pos);
+ continue;
+ }
+ }
+ if (from_port == 0 && to_port == 0)
+ { /* %unique */
+ if (initiator)
+ {
+ from_port = this->unique_port++;
+ from_port = to_port = max(from_port, UNIQUE_PORT_START);
+ }
+ else
+ { /* not supported as responder, use %any */
+ to_port = 65535;
+ }
+ }
+ if (streq(subnet, "%dynamic"))
+ {
+ ts = traffic_selector_create_dynamic(proto,
+ from_port, to_port);
+ }
+ else
+ {
+ ts = traffic_selector_create_from_cidr(subnet, proto,
+ from_port, to_port);
+ }
+ if (ts)
+ {
+ cfg->add_traffic_selector(cfg, local, ts);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid subnet: %s, skipped", subnet);
+ }
}
+ enumerator->destroy(enumerator);
}
else
{
ts = traffic_selector_create_dynamic(0, 0, 65535);
- }
- if (ts)
- {
- cfg->add_traffic_selector(cfg, local, ts);
+ if (ts)
+ {
+ cfg->add_traffic_selector(cfg, local, ts);
+ }
}
}
@@ -610,18 +764,18 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
{ /* initiator */
if (this->vip)
{
- add_ts(NULL, child_cfg, TRUE);
+ add_ts(this, NULL, child_cfg, TRUE, TRUE);
}
else
{
- add_ts(this->initiator_tsi, child_cfg, TRUE);
+ add_ts(this, this->initiator_tsi, child_cfg, TRUE, TRUE);
}
- add_ts(this->initiator_tsr, child_cfg, FALSE);
+ add_ts(this, this->initiator_tsr, child_cfg, FALSE, TRUE);
}
else
{ /* responder */
- add_ts(this->responder_tsr, child_cfg, TRUE);
- add_ts(this->responder_tsi, child_cfg, FALSE);
+ add_ts(this, this->responder_tsr, child_cfg, TRUE, FALSE);
+ add_ts(this, this->responder_tsi, child_cfg, FALSE, FALSE);
}
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
return peer_cfg;
@@ -759,6 +913,7 @@ load_tester_config_t *load_tester_config_create()
(hashtable_equals_t)equals, 256),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.num = 1,
+ .unique_port = UNIQUE_PORT_START,
);
if (lib->settings->get_bool(lib->settings,