diff options
Diffstat (limited to 'src/libcharon/encoding/payloads/id_payload.c')
-rw-r--r-- | src/libcharon/encoding/payloads/id_payload.c | 68 |
1 files changed, 52 insertions, 16 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; |