All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Do not drop DNATed 6to4/6rd packets
@ 2013-09-14 10:30 Catalin(ux) M. BOIE
  2013-09-15 13:14 ` Hannes Frederic Sowa
  0 siblings, 1 reply; 14+ messages in thread
From: Catalin(ux) M. BOIE @ 2013-09-14 10:30 UTC (permalink / raw)
  To: netdev; +Cc: hannes, yoshfuji, davem

From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>

When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
patch (218774dc) will drop them because the IPv6 address embedded
does not match the IPv4 destination. This patch will allow them to
pass by testing if we have an address that matches on 6to4/6rd interface.
I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
Also, log the dropped packets (with rate limit).

Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
---
 include/net/addrconf.h |  5 +++++
 net/ipv6/addrconf.c    | 28 ++++++++++++++++++++++++++++
 net/ipv6/sit.c         | 50 +++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 84a6440..49886fc 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -73,6 +73,11 @@ extern int			ipv6_chk_home_addr(struct net *net,
 						   const struct in6_addr *addr);
 #endif
 
+extern bool			ipv6_chk_custom_prefix(
+					const struct in6_addr *addr,
+					const unsigned int prefix_len,
+					struct net_device *dev);
+
 extern int			ipv6_chk_prefix(const struct in6_addr *addr,
 						struct net_device *dev);
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d1ab6ab..70ab1ba 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1527,6 +1527,34 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
 	return false;
 }
 
+/*
+ * Compares an address/prefix_len with addresses on device @dev.
+ * If one is found it returns true.
+ */
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+	const unsigned int prefix_len, struct net_device *dev)
+{
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
+	bool ret = false;
+
+	rcu_read_lock();
+	idev = __in6_dev_get(dev);
+	if (idev) {
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(ifa, &idev->addr_list, if_list) {
+			ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
+			if (ret)
+				break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(ipv6_chk_custom_prefix);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
 {
 	struct inet6_dev *idev;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 3353634..fd2aba9 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -566,6 +566,33 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
 	return false;
 }
 
+/*
+ * Checks if an address matches an address on the tunnel interface.
+ * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
+ * Long story:
+ * This function is called after we considered the packet as spoofed
+ * in is_spoofed_6rd.
+ * We may have a router that is doing NAT for proto 41 packets
+ * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
+ * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
+ * function will return true, dropping the packet.
+ * But, we can still check if is spoofed against the IP
+ * addresses associated with the interface.
+ */
+static bool only_dnatted(const struct ip_tunnel *tunnel,
+	const struct in6_addr *v6dst)
+{
+	int prefix_len;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+	prefix_len = tunnel->ip6rd.prefixlen + 32
+		- tunnel->ip6rd.relay_prefixlen;
+#else
+	prefix_len = 48;
+#endif
+	return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
+}
+
 static int ipip6_rcv(struct sk_buff *skb)
 {
 	const struct iphdr *iph = ip_hdr(skb);
@@ -589,11 +616,20 @@ static int ipip6_rcv(struct sk_buff *skb)
 				tunnel->dev->stats.rx_errors++;
 				goto out;
 			}
-		} else {
-			if (is_spoofed_6rd(tunnel, iph->saddr,
-					   &ipv6_hdr(skb)->saddr) ||
-			    is_spoofed_6rd(tunnel, iph->daddr,
-					   &ipv6_hdr(skb)->daddr)) {
+		} else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
+			if (unlikely(is_spoofed_6rd(tunnel, iph->saddr,
+				&ipv6_hdr(skb)->saddr))) {
+				net_warn_ratelimited("Src spoofed %pI4/%pI6c\n",
+					&iph->saddr, &ipv6_hdr(skb)->saddr);
+				tunnel->dev->stats.rx_errors++;
+				goto out;
+			}
+
+			if (unlikely(is_spoofed_6rd(tunnel, iph->daddr,
+				&ipv6_hdr(skb)->daddr)
+				&& !only_dnatted(tunnel, &ipv6_hdr(skb)->daddr))) {
+				net_warn_ratelimited("Dst spoofed %pI4/%pI6c\n",
+					&iph->daddr, &ipv6_hdr(skb)->daddr);
 				tunnel->dev->stats.rx_errors++;
 				goto out;
 			}
@@ -713,7 +749,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
@@ -742,7 +778,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] Do not drop DNATed 6to4/6rd packets
  2013-09-14 10:30 [PATCH] Do not drop DNATed 6to4/6rd packets Catalin(ux) M. BOIE
@ 2013-09-15 13:14 ` Hannes Frederic Sowa
  2013-09-22 10:58   ` Catalin(ux) M. BOIE
  0 siblings, 1 reply; 14+ messages in thread
From: Hannes Frederic Sowa @ 2013-09-15 13:14 UTC (permalink / raw)
  To: Catalin(ux) M. BOIE; +Cc: netdev, yoshfuji, davem

On Sat, Sep 14, 2013 at 01:30:47PM +0300, Catalin(ux) M. BOIE wrote:
> From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>
> 
> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
> patch (218774dc) will drop them because the IPv6 address embedded
> does not match the IPv4 destination. This patch will allow them to
> pass by testing if we have an address that matches on 6to4/6rd interface.
> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
> Also, log the dropped packets (with rate limit).
> 
> Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>

Pretty neat idea, I think. Could you rebase the patch ontop of net or net-next
and have a look at the warnings when you feed your patch to
./scripts/checkpatch --strict?

Greetings,

  Hannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] Do not drop DNATed 6to4/6rd packets
  2013-09-15 13:14 ` Hannes Frederic Sowa
@ 2013-09-22 10:58   ` Catalin(ux) M. BOIE
  2013-09-22 17:01     ` Joe Perches
  0 siblings, 1 reply; 14+ messages in thread
From: Catalin(ux) M. BOIE @ 2013-09-22 10:58 UTC (permalink / raw)
  To: netdev; +Cc: hannes, yoshfuji, davem

From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>

When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
patch (218774dc) will drop them because the IPv6 address embedded
does not match the IPv4 destination. This patch will allow them to
pass by testing if we have an address that matches on 6to4/6rd interface.
I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
Also, log the dropped packets (with rate limit).

Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
---
 include/net/addrconf.h |  4 +++
 net/ipv6/addrconf.c    | 27 ++++++++++++++++
 net/ipv6/sit.c         | 83 +++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 99 insertions(+), 15 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index fb314de..96966eb 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -67,6 +67,10 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
 #endif
 
+extern bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+				   const unsigned int prefix_len,
+				   struct net_device *dev);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
 
 struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d6ff126..a0c3abe 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
 	return false;
 }
 
+/* Compares an address/prefix_len with addresses on device @dev.
+ * If one is found it returns true.
+ */
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+	const unsigned int prefix_len, struct net_device *dev)
+{
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
+	bool ret = false;
+
+	rcu_read_lock();
+	idev = __in6_dev_get(dev);
+	if (idev) {
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(ifa, &idev->addr_list, if_list) {
+			ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
+			if (ret)
+				break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(ipv6_chk_custom_prefix);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
 {
 	struct inet6_dev *idev;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 7ee5cb9..6b2230d 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -566,6 +566,69 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
 	return false;
 }
 
+/* Checks if an address matches an address on the tunnel interface.
+ * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
+ * Long story:
+ * This function is called after we considered the packet as spoofed
+ * in is_spoofed_6rd.
+ * We may have a router that is doing NAT for proto 41 packets
+ * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
+ * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
+ * function will return true, dropping the packet.
+ * But, we can still check if is spoofed against the IP
+ * addresses associated with the interface.
+ */
+static bool only_dnatted(const struct ip_tunnel *tunnel,
+	const struct in6_addr *v6dst)
+{
+	int prefix_len;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+	prefix_len = tunnel->ip6rd.prefixlen + 32
+		- tunnel->ip6rd.relay_prefixlen;
+#else
+	prefix_len = 48;
+#endif
+	return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
+}
+
+/* Returns true if a packet is spoofed
+ */
+static bool packet_is_spoofed(struct sk_buff *skb,
+			      const struct iphdr *iph,
+			      struct ip_tunnel *tunnel)
+{
+	const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+
+	if (tunnel->dev->priv_flags & IFF_ISATAP) {
+		if (!isatap_chksrc(skb, iph, tunnel))
+			return true;
+
+		return false;
+	}
+
+	if ((tunnel->dev->flags&IFF_POINTOPOINT))
+		return false;
+
+	if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
+		net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+				     &iph->saddr, &ipv6h->saddr,
+				     &iph->daddr, &ipv6h->daddr);
+		return true;
+	}
+
+	if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr)))
+		return false;
+
+	if (only_dnatted(tunnel, &ipv6h->daddr))
+		return false;
+
+	net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+			     &iph->saddr, &ipv6h->saddr,
+			     &iph->daddr, &ipv6h->daddr);
+	return true;
+}
+
 static int ipip6_rcv(struct sk_buff *skb)
 {
 	const struct iphdr *iph = ip_hdr(skb);
@@ -586,19 +649,9 @@ static int ipip6_rcv(struct sk_buff *skb)
 		IPCB(skb)->flags = 0;
 		skb->protocol = htons(ETH_P_IPV6);
 
-		if (tunnel->dev->priv_flags & IFF_ISATAP) {
-			if (!isatap_chksrc(skb, iph, tunnel)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
-		} else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
-			if (is_spoofed_6rd(tunnel, iph->saddr,
-					   &ipv6_hdr(skb)->saddr) ||
-			    is_spoofed_6rd(tunnel, iph->daddr,
-					   &ipv6_hdr(skb)->daddr)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
+		if (packet_is_spoofed(skb, iph, tunnel)) {
+			tunnel->dev->stats.rx_errors++;
+			goto out;
 		}
 
 		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
@@ -748,7 +801,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
@@ -777,7 +830,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] Do not drop DNATed 6to4/6rd packets
  2013-09-22 10:58   ` Catalin(ux) M. BOIE
@ 2013-09-22 17:01     ` Joe Perches
  2013-09-23 18:31       ` catab
                         ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Joe Perches @ 2013-09-22 17:01 UTC (permalink / raw)
  To: Catalin(ux) M. BOIE; +Cc: netdev, hannes, yoshfuji, davem

On Sun, 2013-09-22 at 13:58 +0300, Catalin(ux) M. BOIE wrote:
> From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>
> 
> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
> patch (218774dc) will drop them because the IPv6 address embedded
> does not match the IPv4 destination. This patch will allow them to
> pass by testing if we have an address that matches on 6to4/6rd interface.
> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
> Also, log the dropped packets (with rate limit).

Thanks.  trivial nits which maybe fixed later:

> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
[]
> +/* Returns true if a packet is spoofed
> + */

probably nicer as single line /* Returns true ... */

> +static bool packet_is_spoofed(struct sk_buff *skb,
> +			      const struct iphdr *iph,
> +			      struct ip_tunnel *tunnel)
> +{
> +	const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
> +
> +	if (tunnel->dev->priv_flags & IFF_ISATAP) {
> +		if (!isatap_chksrc(skb, iph, tunnel))
> +			return true;
> +
> +		return false;
> +	}
> +
> +	if ((tunnel->dev->flags&IFF_POINTOPOINT))

It'd be nicer with spaces around the &

> +		return false;

It'd be slightly faster code moving the ipv6_hdr(skb)
assignment below these tests.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Do not drop DNATed 6to4/6rd packets
  2013-09-22 17:01     ` Joe Perches
@ 2013-09-23 18:31       ` catab
  2013-09-23 18:33       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v3) Catalin(ux) M. BOIE
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: catab @ 2013-09-23 18:31 UTC (permalink / raw)
  To: Joe Perches; +Cc: netdev, hannes, yoshfuji, davem

Hello!

On Sun, 22 Sep 2013, Joe Perches wrote:

> On Sun, 2013-09-22 at 13:58 +0300, Catalin(ux) M. BOIE wrote:
>> From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>
>>
>> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
>> patch (218774dc) will drop them because the IPv6 address embedded
>> does not match the IPv4 destination. This patch will allow them to
>> pass by testing if we have an address that matches on 6to4/6rd interface.
>> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
>> Also, log the dropped packets (with rate limit).
>
> Thanks.  trivial nits which maybe fixed later:
>
>> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
> []
>> +/* Returns true if a packet is spoofed
>> + */
>
> probably nicer as single line /* Returns true ... */
>
>> +static bool packet_is_spoofed(struct sk_buff *skb,
>> +			      const struct iphdr *iph,
>> +			      struct ip_tunnel *tunnel)
>> +{
>> +	const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
>> +
>> +	if (tunnel->dev->priv_flags & IFF_ISATAP) {
>> +		if (!isatap_chksrc(skb, iph, tunnel))
>> +			return true;
>> +
>> +		return false;
>> +	}
>> +
>> +	if ((tunnel->dev->flags&IFF_POINTOPOINT))
>
> It'd be nicer with spaces around the &
>
>> +		return false;
>
> It'd be slightly faster code moving the ipv6_hdr(skb)
> assignment below these tests.

Patch (v3) will follow.

Thank you, Hannes!
Thank you, Joe!

--
Catalin(ux) M. BOIE
http://kernel.embedromix.ro/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] Do not drop DNATed 6to4/6rd packets (v3)
  2013-09-22 17:01     ` Joe Perches
  2013-09-23 18:31       ` catab
@ 2013-09-23 18:33       ` Catalin(ux) M. BOIE
  2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets catab
  2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v4) Catalin(ux) M. BOIE
  3 siblings, 0 replies; 14+ messages in thread
From: Catalin(ux) M. BOIE @ 2013-09-23 18:33 UTC (permalink / raw)
  To: netdev; +Cc: hannes, yoshfuji, davem, joe

From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>

When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
patch (218774dc) will drop them because the IPv6 address embedded
does not match the IPv4 destination. This patch will allow them to
pass by testing if we have an address that matches on 6to4/6rd interface.
I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
Also, log the dropped packets (with rate limit).

Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
---
 include/net/addrconf.h |  4 +++
 net/ipv6/addrconf.c    | 27 ++++++++++++++++
 net/ipv6/sit.c         | 83 +++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 99 insertions(+), 15 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index fb314de..96966eb 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -67,6 +67,10 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
 #endif
 
+extern bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+				   const unsigned int prefix_len,
+				   struct net_device *dev);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
 
 struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d6ff126..a0c3abe 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
 	return false;
 }
 
+/* Compares an address/prefix_len with addresses on device @dev.
+ * If one is found it returns true.
+ */
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+	const unsigned int prefix_len, struct net_device *dev)
+{
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
+	bool ret = false;
+
+	rcu_read_lock();
+	idev = __in6_dev_get(dev);
+	if (idev) {
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(ifa, &idev->addr_list, if_list) {
+			ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
+			if (ret)
+				break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(ipv6_chk_custom_prefix);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
 {
 	struct inet6_dev *idev;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 7ee5cb9..6b2230d 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -566,6 +566,69 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
 	return false;
 }
 
+/* Checks if an address matches an address on the tunnel interface.
+ * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
+ * Long story:
+ * This function is called after we considered the packet as spoofed
+ * in is_spoofed_6rd.
+ * We may have a router that is doing NAT for proto 41 packets
+ * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
+ * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
+ * function will return true, dropping the packet.
+ * But, we can still check if is spoofed against the IP
+ * addresses associated with the interface.
+ */
+static bool only_dnatted(const struct ip_tunnel *tunnel,
+	const struct in6_addr *v6dst)
+{
+	int prefix_len;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+	prefix_len = tunnel->ip6rd.prefixlen + 32
+		- tunnel->ip6rd.relay_prefixlen;
+#else
+	prefix_len = 48;
+#endif
+	return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
+}
+
+/* Returns true if a packet is spoofed
+ */
+static bool packet_is_spoofed(struct sk_buff *skb,
+			      const struct iphdr *iph,
+			      struct ip_tunnel *tunnel)
+{
+	const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+
+	if (tunnel->dev->priv_flags & IFF_ISATAP) {
+		if (!isatap_chksrc(skb, iph, tunnel))
+			return true;
+
+		return false;
+	}
+
+	if ((tunnel->dev->flags&IFF_POINTOPOINT))
+		return false;
+
+	if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
+		net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+				     &iph->saddr, &ipv6h->saddr,
+				     &iph->daddr, &ipv6h->daddr);
+		return true;
+	}
+
+	if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr)))
+		return false;
+
+	if (only_dnatted(tunnel, &ipv6h->daddr))
+		return false;
+
+	net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+			     &iph->saddr, &ipv6h->saddr,
+			     &iph->daddr, &ipv6h->daddr);
+	return true;
+}
+
 static int ipip6_rcv(struct sk_buff *skb)
 {
 	const struct iphdr *iph = ip_hdr(skb);
@@ -586,19 +649,9 @@ static int ipip6_rcv(struct sk_buff *skb)
 		IPCB(skb)->flags = 0;
 		skb->protocol = htons(ETH_P_IPV6);
 
-		if (tunnel->dev->priv_flags & IFF_ISATAP) {
-			if (!isatap_chksrc(skb, iph, tunnel)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
-		} else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
-			if (is_spoofed_6rd(tunnel, iph->saddr,
-					   &ipv6_hdr(skb)->saddr) ||
-			    is_spoofed_6rd(tunnel, iph->daddr,
-					   &ipv6_hdr(skb)->daddr)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
+		if (packet_is_spoofed(skb, iph, tunnel)) {
+			tunnel->dev->stats.rx_errors++;
+			goto out;
 		}
 
 		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
@@ -748,7 +801,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
@@ -777,7 +830,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] Do not drop DNATed 6to4/6rd packets
  2013-09-22 17:01     ` Joe Perches
  2013-09-23 18:31       ` catab
  2013-09-23 18:33       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v3) Catalin(ux) M. BOIE
@ 2013-09-23 18:36       ` catab
  2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v4) Catalin(ux) M. BOIE
  3 siblings, 0 replies; 14+ messages in thread
From: catab @ 2013-09-23 18:36 UTC (permalink / raw)
  To: Joe Perches; +Cc: netdev, hannes, yoshfuji, davem

On Sun, 22 Sep 2013, Joe Perches wrote:

> On Sun, 2013-09-22 at 13:58 +0300, Catalin(ux) M. BOIE wrote:
>> From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>
>>
>> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
>> patch (218774dc) will drop them because the IPv6 address embedded
>> does not match the IPv4 destination. This patch will allow them to
>> pass by testing if we have an address that matches on 6to4/6rd interface.
>> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
>> Also, log the dropped packets (with rate limit).
>
> Thanks.  trivial nits which maybe fixed later:
>
>> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
> []
>> +/* Returns true if a packet is spoofed
>> + */
>
> probably nicer as single line /* Returns true ... */
>
>> +static bool packet_is_spoofed(struct sk_buff *skb,
>> +			      const struct iphdr *iph,
>> +			      struct ip_tunnel *tunnel)
>> +{
>> +	const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
>> +
>> +	if (tunnel->dev->priv_flags & IFF_ISATAP) {
>> +		if (!isatap_chksrc(skb, iph, tunnel))
>> +			return true;
>> +
>> +		return false;
>> +	}
>> +
>> +	if ((tunnel->dev->flags&IFF_POINTOPOINT))
>
> It'd be nicer with spaces around the &
>
>> +		return false;
>
> It'd be slightly faster code moving the ipv6_hdr(skb)
> assignment below these tests.

Sorry, v3 was missing the changes suggested.
v4 fill fix it.
Sorry.

--
Catalin(ux) M. BOIE
http://kernel.embedromix.ro/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] Do not drop DNATed 6to4/6rd packets (v4)
  2013-09-22 17:01     ` Joe Perches
                         ` (2 preceding siblings ...)
  2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets catab
@ 2013-09-23 18:36       ` Catalin(ux) M. BOIE
  2013-09-23 19:11         ` Joe Perches
  3 siblings, 1 reply; 14+ messages in thread
From: Catalin(ux) M. BOIE @ 2013-09-23 18:36 UTC (permalink / raw)
  To: netdev; +Cc: hannes, yoshfuji, davem, joe

From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>

When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
patch (218774dc) will drop them because the IPv6 address embedded
does not match the IPv4 destination. This patch will allow them to
pass by testing if we have an address that matches on 6to4/6rd interface.
I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
Also, log the dropped packets (with rate limit).

Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
---
 include/net/addrconf.h |  4 +++
 net/ipv6/addrconf.c    | 27 ++++++++++++++++
 net/ipv6/sit.c         | 84 +++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 100 insertions(+), 15 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index fb314de..96966eb 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -67,6 +67,10 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
 #endif
 
+extern bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+				   const unsigned int prefix_len,
+				   struct net_device *dev);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
 
 struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d6ff126..a0c3abe 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
 	return false;
 }
 
+/* Compares an address/prefix_len with addresses on device @dev.
+ * If one is found it returns true.
+ */
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+	const unsigned int prefix_len, struct net_device *dev)
+{
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
+	bool ret = false;
+
+	rcu_read_lock();
+	idev = __in6_dev_get(dev);
+	if (idev) {
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(ifa, &idev->addr_list, if_list) {
+			ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
+			if (ret)
+				break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(ipv6_chk_custom_prefix);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
 {
 	struct inet6_dev *idev;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 7ee5cb9..3b5219a 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -566,6 +566,70 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
 	return false;
 }
 
+/* Checks if an address matches an address on the tunnel interface.
+ * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
+ * Long story:
+ * This function is called after we considered the packet as spoofed
+ * in is_spoofed_6rd.
+ * We may have a router that is doing NAT for proto 41 packets
+ * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
+ * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
+ * function will return true, dropping the packet.
+ * But, we can still check if is spoofed against the IP
+ * addresses associated with the interface.
+ */
+static bool only_dnatted(const struct ip_tunnel *tunnel,
+	const struct in6_addr *v6dst)
+{
+	int prefix_len;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+	prefix_len = tunnel->ip6rd.prefixlen + 32
+		- tunnel->ip6rd.relay_prefixlen;
+#else
+	prefix_len = 48;
+#endif
+	return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
+}
+
+/* Returns true if a packet is spoofed */
+static bool packet_is_spoofed(struct sk_buff *skb,
+			      const struct iphdr *iph,
+			      struct ip_tunnel *tunnel)
+{
+	const struct ipv6hdr *ipv6h;
+
+	if (tunnel->dev->priv_flags & IFF_ISATAP) {
+		if (!isatap_chksrc(skb, iph, tunnel))
+			return true;
+
+		return false;
+	}
+
+	if ((tunnel->dev->flags & IFF_POINTOPOINT))
+		return false;
+
+	ipv6h = ipv6_hdr(skb);
+
+	if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
+		net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+				     &iph->saddr, &ipv6h->saddr,
+				     &iph->daddr, &ipv6h->daddr);
+		return true;
+	}
+
+	if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr)))
+		return false;
+
+	if (only_dnatted(tunnel, &ipv6h->daddr))
+		return false;
+
+	net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+			     &iph->saddr, &ipv6h->saddr,
+			     &iph->daddr, &ipv6h->daddr);
+	return true;
+}
+
 static int ipip6_rcv(struct sk_buff *skb)
 {
 	const struct iphdr *iph = ip_hdr(skb);
@@ -586,19 +650,9 @@ static int ipip6_rcv(struct sk_buff *skb)
 		IPCB(skb)->flags = 0;
 		skb->protocol = htons(ETH_P_IPV6);
 
-		if (tunnel->dev->priv_flags & IFF_ISATAP) {
-			if (!isatap_chksrc(skb, iph, tunnel)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
-		} else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
-			if (is_spoofed_6rd(tunnel, iph->saddr,
-					   &ipv6_hdr(skb)->saddr) ||
-			    is_spoofed_6rd(tunnel, iph->daddr,
-					   &ipv6_hdr(skb)->daddr)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
+		if (packet_is_spoofed(skb, iph, tunnel)) {
+			tunnel->dev->stats.rx_errors++;
+			goto out;
 		}
 
 		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
@@ -748,7 +802,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
@@ -777,7 +831,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] Do not drop DNATed 6to4/6rd packets (v4)
  2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v4) Catalin(ux) M. BOIE
@ 2013-09-23 19:11         ` Joe Perches
  2013-09-23 20:04           ` [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets Catalin(ux) M. BOIE
  0 siblings, 1 reply; 14+ messages in thread
From: Joe Perches @ 2013-09-23 19:11 UTC (permalink / raw)
  To: Catalin(ux) M. BOIE; +Cc: netdev, hannes, yoshfuji, davem

On Mon, 2013-09-23 at 21:36 +0300, Catalin(ux) M. BOIE wrote:
> From: "Catalin(ux) M. BOIE" <catab@embedromix.ro>
> 
> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
> patch (218774dc) will drop them because the IPv6 address embedded
> does not match the IPv4 destination. This patch will allow them to
> pass by testing if we have an address that matches on 6to4/6rd interface.
> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
> Also, log the dropped packets (with rate limit).

A few more trivialities:

When you send revisions to patches, please put the
revision number inside the brackets like:

[PATCH V4] subject

Also, use a prefix for the patch like:

[PATCH V4] IPv6 NAT: Don't drop DNAT 6to4 or 6RD packets

> diff --git a/include/net/addrconf.h b/include/net/addrconf.h
[]
> @@ -67,6 +67,10 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
>  int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
>  #endif
>  
> +extern bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
> +				   const unsigned int prefix_len,
> +				   struct net_device *dev);
> +

extern isn't required.

> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
[]
> @@ -566,6 +566,70 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
[]
> +/* Returns true if a packet is spoofed */
> +static bool packet_is_spoofed(struct sk_buff *skb,
> +			      const struct iphdr *iph,
> +			      struct ip_tunnel *tunnel)
> +{
[]
> +	if ((tunnel->dev->flags & IFF_POINTOPOINT))
> +		return false;

One too many parentheses

	if (tunnel->dev->flags & IFF_POINTTOPOINT)
		return false;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets
  2013-09-23 19:11         ` Joe Perches
@ 2013-09-23 20:04           ` Catalin(ux) M. BOIE
  2013-09-24 21:36             ` Hannes Frederic Sowa
  0 siblings, 1 reply; 14+ messages in thread
From: Catalin(ux) M. BOIE @ 2013-09-23 20:04 UTC (permalink / raw)
  To: netdev; +Cc: hannes, yoshfuji, davem, joe

When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
patch (218774dc) will drop them because the IPv6 address embedded
does not match the IPv4 destination. This patch will allow them to
pass by testing if we have an address that matches on 6to4/6rd interface.
I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
Also, log the dropped packets (with rate limit).

Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
---
 include/net/addrconf.h |  4 +++
 net/ipv6/addrconf.c    | 27 ++++++++++++++++
 net/ipv6/sit.c         | 84 +++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 100 insertions(+), 15 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index fb314de..86505bf 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -67,6 +67,10 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
 #endif
 
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+				   const unsigned int prefix_len,
+				   struct net_device *dev);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
 
 struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d6ff126..a0c3abe 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
 	return false;
 }
 
+/* Compares an address/prefix_len with addresses on device @dev.
+ * If one is found it returns true.
+ */
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+	const unsigned int prefix_len, struct net_device *dev)
+{
+	struct inet6_dev *idev;
+	struct inet6_ifaddr *ifa;
+	bool ret = false;
+
+	rcu_read_lock();
+	idev = __in6_dev_get(dev);
+	if (idev) {
+		read_lock_bh(&idev->lock);
+		list_for_each_entry(ifa, &idev->addr_list, if_list) {
+			ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
+			if (ret)
+				break;
+		}
+		read_unlock_bh(&idev->lock);
+	}
+	rcu_read_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(ipv6_chk_custom_prefix);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
 {
 	struct inet6_dev *idev;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 7ee5cb9..afd5605 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -566,6 +566,70 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
 	return false;
 }
 
+/* Checks if an address matches an address on the tunnel interface.
+ * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
+ * Long story:
+ * This function is called after we considered the packet as spoofed
+ * in is_spoofed_6rd.
+ * We may have a router that is doing NAT for proto 41 packets
+ * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
+ * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
+ * function will return true, dropping the packet.
+ * But, we can still check if is spoofed against the IP
+ * addresses associated with the interface.
+ */
+static bool only_dnatted(const struct ip_tunnel *tunnel,
+	const struct in6_addr *v6dst)
+{
+	int prefix_len;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+	prefix_len = tunnel->ip6rd.prefixlen + 32
+		- tunnel->ip6rd.relay_prefixlen;
+#else
+	prefix_len = 48;
+#endif
+	return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
+}
+
+/* Returns true if a packet is spoofed */
+static bool packet_is_spoofed(struct sk_buff *skb,
+			      const struct iphdr *iph,
+			      struct ip_tunnel *tunnel)
+{
+	const struct ipv6hdr *ipv6h;
+
+	if (tunnel->dev->priv_flags & IFF_ISATAP) {
+		if (!isatap_chksrc(skb, iph, tunnel))
+			return true;
+
+		return false;
+	}
+
+	if (tunnel->dev->flags & IFF_POINTOPOINT)
+		return false;
+
+	ipv6h = ipv6_hdr(skb);
+
+	if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
+		net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+				     &iph->saddr, &ipv6h->saddr,
+				     &iph->daddr, &ipv6h->daddr);
+		return true;
+	}
+
+	if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr)))
+		return false;
+
+	if (only_dnatted(tunnel, &ipv6h->daddr))
+		return false;
+
+	net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+			     &iph->saddr, &ipv6h->saddr,
+			     &iph->daddr, &ipv6h->daddr);
+	return true;
+}
+
 static int ipip6_rcv(struct sk_buff *skb)
 {
 	const struct iphdr *iph = ip_hdr(skb);
@@ -586,19 +650,9 @@ static int ipip6_rcv(struct sk_buff *skb)
 		IPCB(skb)->flags = 0;
 		skb->protocol = htons(ETH_P_IPV6);
 
-		if (tunnel->dev->priv_flags & IFF_ISATAP) {
-			if (!isatap_chksrc(skb, iph, tunnel)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
-		} else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
-			if (is_spoofed_6rd(tunnel, iph->saddr,
-					   &ipv6_hdr(skb)->saddr) ||
-			    is_spoofed_6rd(tunnel, iph->daddr,
-					   &ipv6_hdr(skb)->daddr)) {
-				tunnel->dev->stats.rx_errors++;
-				goto out;
-			}
+		if (packet_is_spoofed(skb, iph, tunnel)) {
+			tunnel->dev->stats.rx_errors++;
+			goto out;
 		}
 
 		__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
@@ -748,7 +802,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
@@ -777,7 +831,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
 		if (neigh == NULL) {
-			net_dbg_ratelimited("sit: nexthop == NULL\n");
+			net_dbg_ratelimited("nexthop == NULL\n");
 			goto tx_error;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets
  2013-09-23 20:04           ` [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets Catalin(ux) M. BOIE
@ 2013-09-24 21:36             ` Hannes Frederic Sowa
  2013-09-28 19:57               ` David Miller
  0 siblings, 1 reply; 14+ messages in thread
From: Hannes Frederic Sowa @ 2013-09-24 21:36 UTC (permalink / raw)
  To: Catalin(ux) M. BOIE; +Cc: netdev, yoshfuji, davem, joe

On Mon, Sep 23, 2013 at 11:04:19PM +0300, Catalin(ux) M. BOIE wrote:
> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
> patch (218774dc) will drop them because the IPv6 address embedded
> does not match the IPv4 destination. This patch will allow them to
> pass by testing if we have an address that matches on 6to4/6rd interface.
> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
> Also, log the dropped packets (with rate limit).
> 
> Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>

Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>

Thanks,

  Hannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets
  2013-09-24 21:36             ` Hannes Frederic Sowa
@ 2013-09-28 19:57               ` David Miller
  2013-09-29  0:24                 ` Joe Perches
  2013-09-30  3:05                 ` catab
  0 siblings, 2 replies; 14+ messages in thread
From: David Miller @ 2013-09-28 19:57 UTC (permalink / raw)
  To: hannes; +Cc: catab, netdev, yoshfuji, joe

From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Tue, 24 Sep 2013 23:36:06 +0200

> On Mon, Sep 23, 2013 at 11:04:19PM +0300, Catalin(ux) M. BOIE wrote:
>> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
>> patch (218774dc) will drop them because the IPv6 address embedded
>> does not match the IPv4 destination. This patch will allow them to
>> pass by testing if we have an address that matches on 6to4/6rd interface.
>> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
>> Also, log the dropped packets (with rate limit).
>> 
>> Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
> 
> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>

Applied, but Catalin please strictly refer to changes in the following
precise format:

	commit $SHA1_ID ("Commit message header line text")

Because SHA1_IDs are ambiguous, especially when the change in question
is backported into various -stable branches.

The only way to resolve the ambiguity is to provide the commit message
text (in parenthesis and double quotes).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets
  2013-09-28 19:57               ` David Miller
@ 2013-09-29  0:24                 ` Joe Perches
  2013-09-30  3:05                 ` catab
  1 sibling, 0 replies; 14+ messages in thread
From: Joe Perches @ 2013-09-29  0:24 UTC (permalink / raw)
  To: David Miller; +Cc: hannes, catab, netdev, yoshfuji

On Sat, 2013-09-28 at 15:57 -0400, David Miller wrote:
> Applied, but Catalin please strictly refer to changes in the following
> precise format:
> 
>         commit $SHA1_ID ("Commit message header line text")
> 
> Because SHA1_IDs are ambiguous, especially when the change in question
> is backported into various -stable branches.

There are now enough commits that using only
8 byte SHA1 IDs generates some collisions so
please use 12 bytes or so of the SHA1.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets
  2013-09-28 19:57               ` David Miller
  2013-09-29  0:24                 ` Joe Perches
@ 2013-09-30  3:05                 ` catab
  1 sibling, 0 replies; 14+ messages in thread
From: catab @ 2013-09-30  3:05 UTC (permalink / raw)
  To: David Miller; +Cc: hannes, netdev, yoshfuji, joe

On Sat, 28 Sep 2013, David Miller wrote:

> From: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Date: Tue, 24 Sep 2013 23:36:06 +0200
>
>> On Mon, Sep 23, 2013 at 11:04:19PM +0300, Catalin(ux) M. BOIE wrote:
>>> When a router is doing  DNAT for 6to4/6rd packets the latest anti-spoofing
>>> patch (218774dc) will drop them because the IPv6 address embedded
>>> does not match the IPv4 destination. This patch will allow them to
>>> pass by testing if we have an address that matches on 6to4/6rd interface.
>>> I have been hit by this problem using Fedora and IPV6TO4_IPV4ADDR.
>>> Also, log the dropped packets (with rate limit).
>>>
>>> Signed-off-by: Catalin(ux) M. BOIE <catab@embedromix.ro>
>>
>> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
>
> Applied, but Catalin please strictly refer to changes in the following
> precise format:
>
> 	commit $SHA1_ID ("Commit message header line text")
>
> Because SHA1_IDs are ambiguous, especially when the change in question
> is backported into various -stable branches.
>
> The only way to resolve the ambiguity is to provide the commit message
> text (in parenthesis and double quotes).

Roger.
Should I resubmit it?
Should I send it also to 'stable'?
Thank you.

--
Catalin(ux) M. BOIE
http://kernel.embedromix.ro/

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-09-30  3:06 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-14 10:30 [PATCH] Do not drop DNATed 6to4/6rd packets Catalin(ux) M. BOIE
2013-09-15 13:14 ` Hannes Frederic Sowa
2013-09-22 10:58   ` Catalin(ux) M. BOIE
2013-09-22 17:01     ` Joe Perches
2013-09-23 18:31       ` catab
2013-09-23 18:33       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v3) Catalin(ux) M. BOIE
2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets catab
2013-09-23 18:36       ` [PATCH] Do not drop DNATed 6to4/6rd packets (v4) Catalin(ux) M. BOIE
2013-09-23 19:11         ` Joe Perches
2013-09-23 20:04           ` [PATCH v5] IPv6 NAT: Do not drop DNATed 6to4/6rd packets Catalin(ux) M. BOIE
2013-09-24 21:36             ` Hannes Frederic Sowa
2013-09-28 19:57               ` David Miller
2013-09-29  0:24                 ` Joe Perches
2013-09-30  3:05                 ` catab

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.