diff options
Diffstat (limited to 'src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c')
-rw-r--r-- | src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c | 40 |
1 files changed, 32 insertions, 8 deletions
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; } |