diff options
author | Timo Teräs <timo.teras@iki.fi> | 2015-09-21 13:42:18 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2017-11-20 10:44:40 +0200 |
commit | 78368225baa57342645a88f06b416185a7c85b01 (patch) | |
tree | 07a1f07b7b844a5db96c8968c06985c1b5a606c8 /src/libcharon/encoding/payloads | |
parent | 941ec20df80cbe0f0287742d06859d80fb343736 (diff) | |
download | strongswan-tteras.tar.bz2 strongswan-tteras.tar.xz |
support gre key in ikev1tteras
this implements gre key negotiation in ikev1 similarly to the
ipsec-tools patch in alpine.
the from/to port pair is internally used as gre key for gre
protocol traffic selectors. since from/to pairs 0/0xffff and
0xffff/0 have special meaning, the gre keys 0xffff and 0xffff0000
will not work.
this is not standard compliant, and should probably not be upstreamed
or used widely, but it is applied for interoperability with alpine
racoon for the time being.
Diffstat (limited to 'src/libcharon/encoding/payloads')
-rw-r--r-- | src/libcharon/encoding/payloads/id_payload.c | 68 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/id_payload.h | 6 |
2 files changed, 55 insertions, 19 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_ @}*/ |