aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2021-03-11 16:09:21 -0800
committerDavid S. Miller <davem@davemloft.net>2021-03-11 16:09:21 -0800
commit1d5d0a078672d36fa958ca3495c66d399c1808b9 (patch)
treecd0cfd847e6d908432daa4b968977f5de9c656bc
parentMerge branch 'hns3-next' (diff)
parentseg6: ignore routing header with segments left equal to 0 (diff)
downloadwireguard-linux-1d5d0a078672d36fa958ca3495c66d399c1808b9.tar.xz
wireguard-linux-1d5d0a078672d36fa958ca3495c66d399c1808b9.zip
Merge branch 'seg6-next'
Julien Massonneau says: ==================== SRv6: SRH processing improvements Add support for IPv4 decapsulation in ipv6_srh_rcv() and ignore routing header with segments left equal to 0 for seg6local actions that doesn't perfom decapsulation. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ipv6.h1
-rw-r--r--net/ipv6/exthdrs.c5
-rw-r--r--net/ipv6/seg6_local.c11
3 files changed, 8 insertions, 9 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index bd1f396cc9c7..448bf2b34759 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -30,6 +30,7 @@
*/
#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */
+#define NEXTHDR_IPV4 4 /* IPv4 in IPv6 */
#define NEXTHDR_TCP 6 /* TCP segment. */
#define NEXTHDR_UDP 17 /* UDP message. */
#define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6126f8bf94b3..56e479d158b7 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -381,7 +381,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
looped_back:
if (hdr->segments_left == 0) {
- if (hdr->nexthdr == NEXTHDR_IPV6) {
+ if (hdr->nexthdr == NEXTHDR_IPV6 || hdr->nexthdr == NEXTHDR_IPV4) {
int offset = (hdr->hdrlen + 1) << 3;
skb_postpull_rcsum(skb, skb_network_header(skb),
@@ -397,7 +397,8 @@ looped_back:
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
skb->encapsulation = 0;
-
+ if (hdr->nexthdr == NEXTHDR_IPV4)
+ skb->protocol = htons(ETH_P_IP);
__skb_tunnel_rx(skb, skb->dev, net);
netif_rx(skb);
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index c2a0c78e84d4..8936f48570fc 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -119,12 +119,12 @@ static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
return (struct seg6_local_lwt *)lwt->data;
}
-static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb)
+static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb, int flags)
{
struct ipv6_sr_hdr *srh;
int len, srhoff = 0;
- if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
+ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, &flags) < 0)
return NULL;
if (!pskb_may_pull(skb, srhoff + sizeof(*srh)))
@@ -152,13 +152,10 @@ static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb)
{
struct ipv6_sr_hdr *srh;
- srh = get_srh(skb);
+ srh = get_srh(skb, IP6_FH_F_SKIP_RH);
if (!srh)
return NULL;
- if (srh->segments_left == 0)
- return NULL;
-
#ifdef CONFIG_IPV6_SEG6_HMAC
if (!seg6_hmac_validate_skb(skb))
return NULL;
@@ -172,7 +169,7 @@ static bool decap_and_validate(struct sk_buff *skb, int proto)
struct ipv6_sr_hdr *srh;
unsigned int off = 0;
- srh = get_srh(skb);
+ srh = get_srh(skb, 0);
if (srh && srh->segments_left > 0)
return false;