ip6_tunnel: Allow rcv/xmit even if remote address is a local address
authorShmulik Ladkani <shmulik.ladkani@gmail.com>
Fri, 20 Oct 2017 21:25:15 +0000 (00:25 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Oct 2017 01:33:27 +0000 (10:33 +0900)
Currently, ip6_tnl_xmit_ctl drops tunneled packets if the remote
address (outer v6 destination) is one of host's locally configured
addresses.
Same applies to ip6_tnl_rcv_ctl: it drops packets if the remote address
(outer v6 source) is a local address.

This prevents using ipxip6 (and ip6_gre) tunnels whose local/remote
endpoints are on same host; OTOH v4 tunnels (ipip or gre) allow such
configurations.

An example where this proves useful is a system where entities are
identified by their unique v6 addresses, and use tunnels to encapsulate
traffic between them. The limitation prevents placing several entities
on same host.

Introduce IP6_TNL_F_ALLOW_LOCAL_REMOTE which allows to bypass this
restriction.

Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/ip6_tunnel.h
net/ipv6/ip6_tunnel.c

index 425926c467d7ac8c30010e4aa3b6f664954d0ad1..ffebbe3654789739ea8cf9f50f05e5bce6bd5286 100644 (file)
@@ -20,6 +20,8 @@
 #define IP6_TNL_F_RCV_DSCP_COPY 0x10
 /* copy fwmark from inner packet */
 #define IP6_TNL_F_USE_ORIG_FWMARK 0x20
+/* allow remote endpoint on the local node */
+#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
 
 struct ip6_tnl_parm {
        char name[IFNAMSIZ];    /* name of tunnel device */
index 4212879ff35e58eedcbb655b3d5f9192abde6055..439d65f7e094322b796d840260190eb001dd9275 100644 (file)
@@ -770,7 +770,8 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t,
 
                if ((ipv6_addr_is_multicast(laddr) ||
                     likely(ipv6_chk_addr(net, laddr, ldev, 0))) &&
-                   likely(!ipv6_chk_addr(net, raddr, NULL, 0)))
+                   ((p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) ||
+                    likely(!ipv6_chk_addr(net, raddr, NULL, 0))))
                        ret = 1;
        }
        return ret;
@@ -1000,7 +1001,8 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t,
                if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0)))
                        pr_warn("%s xmit: Local address not yet configured!\n",
                                p->name);
-               else if (!ipv6_addr_is_multicast(raddr) &&
+               else if (!(p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) &&
+                        !ipv6_addr_is_multicast(raddr) &&
                         unlikely(ipv6_chk_addr(net, raddr, NULL, 0)))
                        pr_warn("%s xmit: Routing loop! Remote address found on this node!\n",
                                p->name);