diff options
author | Martin Willi <martin@revosec.ch> | 2013-06-19 16:36:27 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-06-19 16:36:27 +0200 |
commit | 4e8142e8e9b45f11460db2d360f20e207ed7e6d4 (patch) | |
tree | b1aec2210ece0afb2a12f0a9196e20e6f2ac05a4 /src/libcharon/plugins/stroke/stroke_config.c | |
parent | 4f88ad669a2a5d65bd7e6d60896df14246f58a5e (diff) | |
parent | 24df067810993dc9736f7bcc274d4063d4d1c721 (diff) | |
download | strongswan-4e8142e8e9b45f11460db2d360f20e207ed7e6d4.tar.bz2 strongswan-4e8142e8e9b45f11460db2d360f20e207ed7e6d4.tar.xz |
Merge branch 'nat-transport'
Enable transport mode in NAT situations when using IKEv2. Additionally brings
an extended leftsubnet format, where each subnet can take a separate protocol
and port.
Diffstat (limited to 'src/libcharon/plugins/stroke/stroke_config.c')
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_config.c | 116 |
1 files changed, 113 insertions, 3 deletions
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 988129f03..64af5bb9c 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -21,6 +21,8 @@ #include <threading/mutex.h> #include <utils/lexparser.h> +#include <netdb.h> + typedef struct private_stroke_config_t private_stroke_config_t; /** @@ -883,6 +885,89 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, } /** + * 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 = 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 (*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; +} + +/** * build a traffic selector from a stroke_end */ static void add_ts(private_stroke_config_t *this, @@ -913,13 +998,38 @@ static void add_ts(private_stroke_config_t *this, else { enumerator_t *enumerator; - char *subnet; + char *subnet, *pos; + u_int16_t from_port, to_port; + u_int8_t proto; enumerator = enumerator_create_token(end->subnets, ",", " "); while (enumerator->enumerate(enumerator, &subnet)) { - ts = traffic_selector_create_from_cidr(subnet, end->protocol, - end->from_port, end->to_port); + from_port = end->from_port; + to_port = end->to_port; + proto = end->protocol; + + 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 (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) { child_cfg->add_traffic_selector(child_cfg, local, ts); |