aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/encoding/payloads/id_payload.c68
-rw-r--r--src/libcharon/encoding/payloads/id_payload.h6
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c40
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c5
-rw-r--r--src/libcharon/plugins/unity/unity_narrow.c2
-rw-r--r--src/libcharon/plugins/vici/vici_config.c9
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c16
7 files changed, 109 insertions, 37 deletions
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
index ae0b19a9d..43f28fc20 100644
--- a/src/libcharon/encoding/payloads/id_payload.c
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -245,18 +245,20 @@ METHOD(id_payload_t, get_identification, identification_t*,
* Create a traffic selector from an range ID
*/
static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
- ts_type_t type)
+ ts_type_t type,
+ uint16_t from_port, uint16_t to_port)
{
return traffic_selector_create_from_bytes(this->protocol_id, type,
- chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
- chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
+ chunk_create(this->id_data.ptr, this->id_data.len / 2), from_port,
+ chunk_skip(this->id_data, this->id_data.len / 2), to_port);
}
/**
* Create a traffic selector from an subnet ID
*/
static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
- ts_type_t type)
+ ts_type_t type,
+ uint16_t from_port, uint16_t to_port)
{
traffic_selector_t *ts;
chunk_t net, netmask;
@@ -269,7 +271,7 @@ static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
}
ts = traffic_selector_create_from_bytes(this->protocol_id, type,
- net, this->port, netmask, this->port ?: 65535);
+ net, from_port, netmask, to_port);
chunk_free(&netmask);
return ts;
}
@@ -278,51 +280,76 @@ static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
* Create a traffic selector from an IP ID
*/
static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
- ts_type_t type)
+ ts_type_t type,
+ uint16_t from_port, uint16_t to_port)
{
return traffic_selector_create_from_bytes(this->protocol_id, type,
- this->id_data, this->port, this->id_data, this->port ?: 65535);
+ this->id_data, from_port, this->id_data, to_port);
}
METHOD(id_payload_t, get_ts, traffic_selector_t*,
- private_id_payload_t *this)
+ private_id_payload_t *this, id_payload_t *other_, bool initiator)
{
+ private_id_payload_t *other = (private_id_payload_t *) other_;
+ uint16_t from_port, to_port;
+
+ if (other && this->protocol_id == IPPROTO_GRE && other->protocol_id == IPPROTO_GRE)
+ {
+ if (initiator)
+ {
+ from_port = this->port;
+ to_port = other->port;
+ }
+ else
+ {
+ from_port = other->port;
+ to_port = this->port;
+ }
+ if (from_port == 0 && to_port == 0)
+ to_port = 0xffff;
+ }
+ else
+ {
+ from_port = this->port;
+ to_port = this->port ?: 0xffff;
+ }
+
switch (this->id_type)
{
case ID_IPV4_ADDR_SUBNET:
if (this->id_data.len == 8)
{
- return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
+ return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE, from_port, to_port);
}
break;
case ID_IPV6_ADDR_SUBNET:
if (this->id_data.len == 32)
{
- return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
+ return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE, from_port, to_port);
}
break;
case ID_IPV4_ADDR_RANGE:
if (this->id_data.len == 8)
{
- return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
+ return get_ts_from_range(this, TS_IPV4_ADDR_RANGE, from_port, to_port);
}
break;
case ID_IPV6_ADDR_RANGE:
if (this->id_data.len == 32)
{
- return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
+ return get_ts_from_range(this, TS_IPV6_ADDR_RANGE, from_port, to_port);
}
break;
case ID_IPV4_ADDR:
if (this->id_data.len == 4)
{
- return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
+ return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE, from_port, to_port);
}
break;
case ID_IPV6_ADDR:
if (this->id_data.len == 16)
{
- return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
+ return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE, from_port, to_port);
}
break;
default:
@@ -397,7 +424,7 @@ id_payload_t *id_payload_create_from_identification(payload_type_t type,
/*
* Described in header.
*/
-id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
+id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts, bool initiator)
{
private_id_payload_t *this;
uint8_t mask;
@@ -460,8 +487,17 @@ id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
ts->get_from_address(ts), ts->get_to_address(ts));
net->destroy(net);
}
- this->port = ts->get_from_port(ts);
this->protocol_id = ts->get_protocol(ts);
+ if (initiator || this->protocol_id != IPPROTO_GRE)
+ {
+ this->port = ts->get_from_port(ts);
+ }
+ else
+ {
+ this->port = ts->get_to_port(ts);
+ if (this->port == 0xffff && ts->get_from_port(ts) == 0)
+ this->port = 0;
+ }
this->payload_length += this->id_data.len;
return &this->public;
diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h
index df1d07553..7558e91f2 100644
--- a/src/libcharon/encoding/payloads/id_payload.h
+++ b/src/libcharon/encoding/payloads/id_payload.h
@@ -48,11 +48,11 @@ struct id_payload_t {
identification_t *(*get_identification) (id_payload_t *this);
/**
- * Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity.
+ * Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity pair.
*
* @return traffic selector, NULL on failure
*/
- traffic_selector_t* (*get_ts)(id_payload_t *this);
+ traffic_selector_t* (*get_ts)(id_payload_t *this, id_payload_t *other, bool initiator);
/**
* Get encoded payload without fixed payload header (used for IKEv1).
@@ -91,6 +91,6 @@ id_payload_t *id_payload_create_from_identification(payload_type_t type,
* @param ts traffic selector
* @return PLV1_ID id_paylad_t object.
*/
-id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts);
+id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts, bool initiator);
#endif /** ID_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 4e79dfced..27ea824ee 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -824,7 +824,18 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
ts2subnet(src, &sel.saddr, &sel.prefixlen_s);
ts2ports(dst, &sel.dport, &sel.dport_mask);
ts2ports(src, &sel.sport, &sel.sport_mask);
- if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) &&
+ if (sel.proto == IPPROTO_GRE)
+ {
+ sel.sport = htons(src->get_from_port(src));
+ sel.dport = htons(src->get_to_port(src));
+ sel.sport_mask = ~0;
+ sel.dport_mask = ~0;
+ if (sel.sport == htons(0) && sel.dport == htons(0xffff))
+ {
+ sel.sport = sel.dport = sel.sport_mask = sel.dport_mask = 0;
+ }
+ }
+ else if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) &&
(sel.dport || sel.sport))
{
/* the kernel expects the ICMP type and code in the source and
@@ -848,7 +859,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
{
u_char *addr;
uint8_t prefixlen;
- uint16_t port = 0;
+ uint16_t from_port = 0, to_port = 65535;
host_t *host = NULL;
if (src)
@@ -857,7 +868,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
prefixlen = sel->prefixlen_s;
if (sel->sport_mask)
{
- port = ntohs(sel->sport);
+ from_port = to_port = ntohs(sel->sport);
}
}
else
@@ -866,14 +877,27 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
prefixlen = sel->prefixlen_d;
if (sel->dport_mask)
{
- port = ntohs(sel->dport);
+ from_port = to_port = ntohs(sel->dport);
+ }
+ }
+ if (sel->proto == IPPROTO_GRE)
+ {
+ if (sel->sport_mask)
+ {
+ from_port = ntohs(sel->sport);
+ to_port = ntohs(sel->dport);
+ }
+ else
+ {
+ from_port = 0;
+ to_port = 0xffff;
}
}
- if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6)
+ else if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6)
{ /* convert ICMP[v6] message type and code as supplied by the kernel in
* source and destination ports (both in network order) */
- port = (sel->sport >> 8) | (sel->dport & 0xff00);
- port = ntohs(port);
+ from_port = (sel->sport >> 8) | (sel->dport & 0xff00);
+ from_port = to_port = ntohs(from_port);
}
/* The Linux 2.6 kernel does not set the selector's family field,
* so as a kludge we additionally test the prefix length.
@@ -890,7 +914,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src)
if (host)
{
return traffic_selector_create_from_subnet(host, prefixlen,
- sel->proto, port, port ?: 65535);
+ sel->proto, from_port, to_port);
}
return NULL;
}
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index ac0129210..b2060e2eb 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -936,6 +936,11 @@ static bool parse_protoport(char *token, uint16_t *from_port,
*from_port = 0xffff;
*to_port = 0;
}
+ else if (*port && *protocol == IPPROTO_GRE)
+ {
+ p = strtol(port, &endptr, 0);
+ traffic_selector_split_grekey(p, from_port, to_port);
+ }
else if (*port)
{
svc = getservbyname(port, NULL);
diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c
index 227d24be8..7749d8c2c 100644
--- a/src/libcharon/plugins/unity/unity_narrow.c
+++ b/src/libcharon/plugins/unity/unity_narrow.c
@@ -247,7 +247,7 @@ METHOD(listener_t, message, bool,
if (!first)
{
id_payload = (id_payload_t*)payload;
- tsr = id_payload->get_ts(id_payload);
+ tsr = id_payload->get_ts(id_payload, NULL, FALSE);
break;
}
first = FALSE;
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index b3e835f59..710b57994 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -680,8 +680,13 @@ CALLBACK(parse_ts, bool,
}
else if (*port && !streq(port, "any"))
{
- svc = getservbyname(port, NULL);
- if (svc)
+ if (proto == IPPROTO_GRE)
+ {
+ p = strtol(port, &end, 0);
+ if (*end) return FALSE;
+ traffic_selector_split_grekey(p, &from, &to);
+ }
+ else if ((svc = getservbyname(port, NULL)) != NULL)
{
from = to = ntohs(svc->s_port);
}
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 49b476ad8..315a29abe 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -567,9 +567,9 @@ static void add_ts(private_quick_mode_t *this, message_t *message)
{
id_payload_t *id_payload;
- id_payload = id_payload_create_from_ts(this->tsi);
+ id_payload = id_payload_create_from_ts(this->tsi, TRUE);
message->add_payload(message, &id_payload->payload_interface);
- id_payload = id_payload_create_from_ts(this->tsr);
+ id_payload = id_payload_create_from_ts(this->tsr, FALSE);
message->add_payload(message, &id_payload->payload_interface);
}
@@ -580,7 +580,7 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
{
traffic_selector_t *tsi = NULL, *tsr = NULL;
enumerator_t *enumerator;
- id_payload_t *id_payload;
+ id_payload_t *idi = NULL, *idr = NULL;
payload_t *payload;
host_t *hsi, *hsr;
bool first = TRUE;
@@ -590,20 +590,22 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
{
if (payload->get_type(payload) == PLV1_ID)
{
- id_payload = (id_payload_t*)payload;
-
if (first)
{
- tsi = id_payload->get_ts(id_payload);
+ idi = (id_payload_t*)payload;
first = FALSE;
}
else
{
- tsr = id_payload->get_ts(id_payload);
+ idr = (id_payload_t*)payload;
break;
}
}
}
+ if (idi && idr) {
+ tsi = idi->get_ts(idi, idr, TRUE);
+ tsr = idr->get_ts(idr, idi, FALSE);
+ }
enumerator->destroy(enumerator);
/* create host2host selectors if ID payloads missing */