From 0146dca70b877b73c5fd9c67912b8a0ca8a7bac7 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Mon, 27 Apr 2020 17:59:34 +0200 Subject: xfrm: add support for UDPv6 encapsulation of ESP This patch adds support for encapsulation of ESP over UDPv6. The code is very similar to the IPv4 encapsulation implementation, and allows to easily add espintcp on IPv6 as a follow-up. Signed-off-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/ipv4/udp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'net/ipv4') diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 32564b350823..1b7ebbcae497 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -112,6 +112,9 @@ #include #include #include +#if IS_ENABLED(CONFIG_IPV6) +#include +#endif struct udp_table udp_table __read_mostly; EXPORT_SYMBOL(udp_table); @@ -2563,7 +2566,12 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, #ifdef CONFIG_XFRM case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP_NON_IKE: - up->encap_rcv = xfrm4_udp_encap_rcv; +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) + up->encap_rcv = ipv6_stub->xfrm6_udp_encap_rcv; + else +#endif + up->encap_rcv = xfrm4_udp_encap_rcv; #endif fallthrough; case UDP_ENCAP_L2TPINUDP: -- cgit From 26333c37fc285e7372f1b9461f3ae0ba3dc699c9 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Mon, 27 Apr 2020 17:59:35 +0200 Subject: xfrm: add IPv6 support for espintcp This extends espintcp to support IPv6, building on the existing code and the new UDPv6 encapsulation support. Most of the code is either reused directly (stream parser, ULP) or very similar to the IPv4 variant (net/ipv6/esp6.c changes). The separation of config options for IPv4 and IPv6 espintcp requires a bit of Kconfig gymnastics to enable the core code. Signed-off-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/ipv4/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'net/ipv4') diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 25a8888826b8..014aaa17dc79 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -384,6 +384,7 @@ config INET_ESPINTCP depends on XFRM && INET_ESP select STREAM_PARSER select NET_SOCK_MSG + select XFRM_ESPINTCP help Support for RFC 8229 encapsulation of ESP and IKE over TCP/IPv4 sockets. -- cgit From 6d64be3da282908bb17b0803b9edad8852ffea56 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 4 May 2020 10:06:03 +0200 Subject: xfrm: avoid extract_output indirection for ipv4 We can use a direct call for ipv4, so move the needed functions to net/xfrm/xfrm_output.c and call them directly. For ipv6 the indirection can be avoided as well but it will need a bit more work -- to ease review it will be done in another patch. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_output.c | 40 ---------------------------------------- net/ipv4/xfrm4_state.c | 1 - 2 files changed, 41 deletions(-) (limited to 'net/ipv4') diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 89ba7c87de5d..21c8fa0a31ed 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -14,46 +14,6 @@ #include #include -static int xfrm4_tunnel_check_size(struct sk_buff *skb) -{ - int mtu, ret = 0; - - if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE) - goto out; - - if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->ignore_df) - goto out; - - mtu = dst_mtu(skb_dst(skb)); - if ((!skb_is_gso(skb) && skb->len > mtu) || - (skb_is_gso(skb) && - !skb_gso_validate_network_len(skb, ip_skb_dst_mtu(skb->sk, skb)))) { - skb->protocol = htons(ETH_P_IP); - - if (skb->sk) - xfrm_local_error(skb, mtu); - else - icmp_send(skb, ICMP_DEST_UNREACH, - ICMP_FRAG_NEEDED, htonl(mtu)); - ret = -EMSGSIZE; - } -out: - return ret; -} - -int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb) -{ - int err; - - err = xfrm4_tunnel_check_size(skb); - if (err) - return err; - - XFRM_MODE_SKB_CB(skb)->protocol = ip_hdr(skb)->protocol; - - return xfrm4_extract_header(skb); -} - int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb) { memset(IPCB(skb), 0, sizeof(*IPCB(skb))); diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index f8ed3c3bb928..d7c200779e4f 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -37,7 +37,6 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { .output = xfrm4_output, .output_finish = xfrm4_output_finish, .extract_input = xfrm4_extract_input, - .extract_output = xfrm4_extract_output, .transport_finish = xfrm4_transport_finish, .local_error = xfrm4_local_error, }; -- cgit From a269fbfc4e9ffe48c1f8142e60a49b6f2e588c58 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 4 May 2020 10:06:04 +0200 Subject: xfrm: state: remove extract_input indirection from xfrm_state_afinfo In order to keep CONFIG_IPV6=m working, xfrm6_extract_header needs to be duplicated. It will be removed again in a followup change when the remaining caller is moved to net/xfrm as well. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_input.c | 5 ----- net/ipv4/xfrm4_state.c | 1 - 2 files changed, 6 deletions(-) (limited to 'net/ipv4') diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index f8de2482a529..ad2afeef4f10 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -18,11 +18,6 @@ #include #include -int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb) -{ - return xfrm4_extract_header(skb); -} - static int xfrm4_rcv_encap_finish2(struct net *net, struct sock *sk, struct sk_buff *skb) { diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index d7c200779e4f..521fc1bc069c 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -36,7 +36,6 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { .proto = IPPROTO_IPIP, .output = xfrm4_output, .output_finish = xfrm4_output_finish, - .extract_input = xfrm4_extract_input, .transport_finish = xfrm4_transport_finish, .local_error = xfrm4_local_error, }; -- cgit From 171916cbd53dec5c7b05efb56a201671d92effc1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 4 May 2020 10:06:05 +0200 Subject: xfrm: move xfrm4_extract_header to common helper The function only initializes the XFRM CB in the skb. After previous patch xfrm4_extract_header is only called from net/xfrm/xfrm_{input,output}.c. Because of IPV6=m linker errors the ipv6 equivalent (xfrm6_extract_header) was already placed in xfrm_inout.h because we can't call functions residing in a module from the core. So do the same for the ipv4 helper and place it next to the ipv6 one. Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_state.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'net/ipv4') diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 521fc1bc069c..b23a1711297b 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -8,28 +8,7 @@ * */ -#include #include -#include -#include -#include -#include - -int xfrm4_extract_header(struct sk_buff *skb) -{ - const struct iphdr *iph = ip_hdr(skb); - - XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); - XFRM_MODE_SKB_CB(skb)->id = iph->id; - XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off; - XFRM_MODE_SKB_CB(skb)->tos = iph->tos; - XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl; - XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph); - memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0, - sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); - - return 0; -} static struct xfrm_state_afinfo xfrm4_state_afinfo = { .family = AF_INET, -- cgit From 2ab6096db2f16b3a6adbad252f1be171e649028d Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 4 May 2020 10:06:09 +0200 Subject: xfrm: remove output_finish indirection from xfrm_state_afinfo There are only two implementaions, one for ipv4 and one for ipv6. Both are almost identical, they clear skb->cb[], set the TRANSFORMED flag in IP(6)CB and then call the common xfrm_output() function. By placing the IPCB handling into the common function, we avoid the need for the output_finish indirection as the output functions can simply use xfrm_output(). Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_output.c | 23 +---------------------- net/ipv4/xfrm4_state.c | 1 - 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'net/ipv4') diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 21c8fa0a31ed..502eb189d852 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -14,22 +14,9 @@ #include #include -int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb) -{ - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - -#ifdef CONFIG_NETFILTER - IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; -#endif - - return xfrm_output(sk, skb); -} - static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct xfrm_state *x = skb_dst(skb)->xfrm; - const struct xfrm_state_afinfo *afinfo; - int ret = -EAFNOSUPPORT; #ifdef CONFIG_NETFILTER if (!x) { @@ -38,15 +25,7 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) } #endif - rcu_read_lock(); - afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family); - if (likely(afinfo)) - ret = afinfo->output_finish(sk, skb); - else - kfree_skb(skb); - rcu_read_unlock(); - - return ret; + return xfrm_output(sk, skb); } int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index b23a1711297b..87d4db591488 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -14,7 +14,6 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { .family = AF_INET, .proto = IPPROTO_IPIP, .output = xfrm4_output, - .output_finish = xfrm4_output_finish, .transport_finish = xfrm4_transport_finish, .local_error = xfrm4_local_error, }; -- cgit From 7d4343d501f9b5ddbc92f278adba339d16d010e1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 11 May 2020 10:33:42 +0200 Subject: xfrm: fix unused variable warning if CONFIG_NETFILTER=n After recent change 'x' is only used when CONFIG_NETFILTER is set: net/ipv4/xfrm4_output.c: In function '__xfrm4_output': net/ipv4/xfrm4_output.c:19:21: warning: unused variable 'x' [-Wunused-variable] 19 | struct xfrm_state *x = skb_dst(skb)->xfrm; Expand the CONFIG_NETFILTER scope to avoid this. Fixes: 2ab6096db2f1 ("xfrm: remove output_finish indirection from xfrm_state_afinfo") Reported-by: Stephen Rothwell Signed-off-by: Florian Westphal Signed-off-by: Steffen Klassert --- net/ipv4/xfrm4_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv4') diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 502eb189d852..3cff51ba72bb 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -16,9 +16,9 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) { +#ifdef CONFIG_NETFILTER struct xfrm_state *x = skb_dst(skb)->xfrm; -#ifdef CONFIG_NETFILTER if (!x) { IPCB(skb)->flags |= IPSKB_REROUTED; return dst_output(net, sk, skb); -- cgit