summaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-04-04 13:50:45 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2006-04-09 22:25:25 -0700
commit50fba2aa7cefa6b0e1768cb350c9e69042320c03 (patch)
treed9d229be1cc489759994e3860e3d2c60e6e6239f /net/ipv6
parent2e2f7aefa8a8ba4adb6ecee8cbb43fbe9ca4cc89 (diff)
[INET]: Move no-tunnel ICMP error to tunnel4/tunnel6
This patch moves the sending of ICMP messages when there are no IPv4/IPv6 tunnels present to tunnel4/tunnel6 respectively. Please note that for now if xfrm4_tunnel/xfrm6_tunnel is loaded then no ICMP messages will ever be sent. This is similar to how we handle AH/ESP/IPCOMP. This move fixes the bug where we always send an ICMP message when there is no ip6_tunnel device present for a given packet even if it is later handled by IPsec. It also causes ICMP messages to be sent when no IPIP tunnel is present. I've decided to use the "port unreachable" ICMP message over the current value of "address unreachable" (and "protocol unreachable" by GRE) because it is not ambiguous unlike the other ones which can be triggered by other conditions. There seems to be no standard specifying what value must be used so this change should be OK. In fact we should change GRE to use this value as well. Incidentally, this patch also fixes a fairly serious bug in xfrm6_tunnel where we don't check whether the embedded IPv6 header is present before dereferencing it for the inside source address. This patch is inspired by a previous patch by Hugo Santos <hsantos@av.it.pt>. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/tunnel6.c8
2 files changed, 13 insertions, 7 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index ff9040c9255..a995796b5a5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -519,9 +519,6 @@ ip6ip6_rcv(struct sk_buff *skb)
struct ipv6hdr *ipv6h;
struct ip6_tnl *t;
- if (!pskb_may_pull(skb, sizeof (*ipv6h)))
- goto discard;
-
ipv6h = skb->nh.ipv6h;
read_lock(&ip6ip6_lock);
@@ -529,8 +526,7 @@ ip6ip6_rcv(struct sk_buff *skb)
if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
read_unlock(&ip6ip6_lock);
- kfree_skb(skb);
- return 0;
+ goto discard;
}
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@@ -557,9 +553,11 @@ ip6ip6_rcv(struct sk_buff *skb)
return 0;
}
read_unlock(&ip6ip6_lock);
- icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
-discard:
return 1;
+
+discard:
+ kfree_skb(skb);
+ return 0;
}
static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 5659b52284b..0ef9a35798d 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -19,11 +19,13 @@
* YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
*/
+#include <linux/icmpv6.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>
@@ -87,10 +89,16 @@ static int tunnel6_rcv(struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler;
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ goto drop;
+
for (handler = tunnel6_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
+
+drop:
kfree_skb(skb);
return 0;
}