[OpenWrt-Devel] [PATCH] kernel/generic: (try) fixing MAP-E patch misbehaving in 4.0
Daniel Golle
daniel at makrotopia.org
Wed May 23 14:18:46 EDT 2018
Hi Axel,
Hi Steven,
revisiting your patch, I try to understand what we need to fix here
or if the issue has already been resolved in the meantime.
See below:
On Fri, Feb 09, 2018 at 01:20:53PM +0100, Axel Neumann wrote:
> Hello,
>
> the 666 kernel patches [1,2,3] break the possibility for using an ip4ip6
> tunnel interface as a fall back interface accepting ip4-in-ip6 tunneled
> packets from any remote address. This works out of the box with any
> normal (non-666-patched) 4.4 (and earlier) kernel and can be configured
> by setting up an 'ip -6 tunnel' with type 'any' or 'ip4ip6' and a remote
> address of '::'.
>
> The misbehavior comes with line 290 of [3] which discards all packets
> that do not show the expected saddr, even if no single fmr rule was
> defined and despite the validity of the saddr was already approved earlier.
>
> Attached diff would re-enable this fall back capability without
> affecting the behavior in case of any configured FMR rules.
>
> It would be nice if the proposed or a similar fix could be applied asap
> because currently I see no way of recovering the standard kernel
> behavior which breaks certain desired bmx6 and bmx7 tunneling features.
>
> Best regards
> /axel
>
>
> [1]
> https://github.com/openwrt-mirror/openwrt/blob/master/target/linux/generic/patches-3.18/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch
> [2]
> https://github.com/openwrt-mirror/openwrt/blob/master/target/linux/generic/patches-4.1/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch
> [3]
> https://github.com/openwrt-mirror/openwrt/blob/master/target/linux/generic/patches-4.4/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch#L290
>
The patch below is supposedly applied to net/ipv6/ip6_tunnel.c after
666-Add-support-for-MAP-E-FMRs-mesh-mode.patch has been applied, right?
> 1032c1032
> < if (fmr) {
> ---
> > if (fmr)
> 1036,1039c1036,1038
> < if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
> < rcu_read_unlock();
> < goto discard;
> < }
> ---
> > if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
> > rcu_read_unlock();
> > goto discard;
The original hunk in 666-Add-support-for-MAP-E-FMRs-mesh-mode.patch
looks like this
---
@@ -832,6 +950,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl
skb_reset_network_header(skb);
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+ if (tpi->proto == htons(ETH_P_IP) &&
+ !ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) {
+ /* Packet didn't come from BR, so lookup FMR */
+ struct __ip6_tnl_fmr *fmr;
+ struct in6_addr expected = tunnel->parms.raddr;
+ for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next)
+ if (ipv6_prefix_equal(&ipv6h->saddr,
+ &fmr->ip6_prefix, fmr->ip6_prefix_len))
+ break;
+
+ /* Check that IPv6 matches IPv4 source to prevent spoofing */
+ if (fmr)
+ ip4ip6_fmr_calc(&expected, ip_hdr(skb),
+ skb_tail_pointer(skb), fmr, false);
+
+ if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
+ rcu_read_unlock();
+ goto drop;
+ }
+ }
+
__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
err = dscp_ecn_decapsulate(tunnel, ipv6h, skb);
---
Reading this it is obvious that yout patch can be reverse-applied to
ip6_tunnel.c after 666-Add-support-for-MAP-E-FMRs-mesh-mode.patch has
been applied. As the MAP-E patch apparently hasn't been touched for
quite a while I assume that it must have looked the same at the time
when you sent the patch and you just used diff in a slightly
counter-intuitive way...
Just to make things crystal clear:
You are suggesting to change the patch above to rather be like:
---
@@ -832,6 +951,28 @@ static int __ip6_tnl_rcv(struct ip6_tnl
skb_reset_network_header(skb);
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
+ if (tpi->proto == htons(ETH_P_IP) &&
+ !ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) {
+ /* Packet didn't come from BR, so lookup FMR */
+ struct __ip6_tnl_fmr *fmr;
+ struct in6_addr expected = tunnel->parms.raddr;
+ for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next)
+ if (ipv6_prefix_equal(&ipv6h->saddr,
+ &fmr->ip6_prefix, fmr->ip6_prefix_len))
+ break;
+
+ /* Check that IPv6 matches IPv4 source to prevent spoofing */
+ if (fmr) {
+ ip4ip6_fmr_calc(&expected, ip_hdr(skb),
+ skb_tail_pointer(skb), fmr, false);
+
+ if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
+ rcu_read_unlock();
+ goto drop;
+ }
+ }
+ }
+
__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
err = dscp_ecn_decapsulate(tunnel, ipv6h, skb);
---
Please confirm that this was your original intention, so we can move
forward with the discussion and this is an IPv6 show-stopper for
LibreMesh as well...
Cheers
Daniel
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
http://lists.infradead.org/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list