summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/ip6_tunnel.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 08d944223ec8..6022fc5e557a 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -372,16 +372,16 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw)
}
/**
- * ip6ip6_err - tunnel error handler
+ * ip6_tnl_err - tunnel error handler
*
* Description:
- * ip6ip6_err() should handle errors in the tunnel according
+ * ip6_tnl_err() should handle errors in the tunnel according
* to the specifications in RFC 2473.
**/
static int
-ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __be32 info)
+ip6_tnl_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int *type, int *code, int *msg, __be32 *info, int offset)
{
struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
struct ip6_tnl *t;
@@ -402,7 +402,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
err = 0;
- switch (type) {
+ switch (*type) {
__u32 teli;
struct ipv6_tlv_tnl_enc_lim *tel;
__u32 mtu;
@@ -414,7 +414,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
rel_msg = 1;
break;
case ICMPV6_TIME_EXCEED:
- if (code == ICMPV6_EXC_HOPLIMIT) {
+ if ((*code) == ICMPV6_EXC_HOPLIMIT) {
if (net_ratelimit())
printk(KERN_WARNING
"%s: Too small hop limit or "
@@ -425,10 +425,10 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
break;
case ICMPV6_PARAMPROB:
teli = 0;
- if (code == ICMPV6_HDR_FIELD)
+ if ((*code) == ICMPV6_HDR_FIELD)
teli = parse_tlv_tnl_enc_lim(skb, skb->data);
- if (teli && teli == ntohl(info) - 2) {
+ if (teli && teli == ntohl(*info) - 2) {
tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
if (tel->encap_limit == 0) {
if (net_ratelimit())
@@ -445,7 +445,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
break;
case ICMPV6_PKT_TOOBIG:
- mtu = ntohl(info) - offset;
+ mtu = ntohl(*info) - offset;
if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU;
t->dev->mtu = mtu;
@@ -458,12 +458,38 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
}
break;
}
- if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) {
+
+ *type = rel_type;
+ *code = rel_code;
+ *info = rel_info;
+ *msg = rel_msg;
+
+out:
+ read_unlock(&ip6ip6_lock);
+ return err;
+}
+
+static int
+ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
+{
+ int rel_msg = 0;
+ int rel_type = type;
+ int rel_code = code;
+ __u32 rel_info = info;
+ int err;
+
+ err = ip6_tnl_err(skb, opt, &rel_type, &rel_code, &rel_msg, &rel_info,
+ offset);
+ if (err < 0)
+ return err;
+
+ if (rel_msg && pskb_may_pull(skb, offset + sizeof(struct ipv6hdr))) {
struct rt6_info *rt;
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (!skb2)
- goto out;
+ return 0;
dst_release(skb2->dst);
skb2->dst = NULL;
@@ -483,9 +509,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
kfree_skb(skb2);
}
-out:
- read_unlock(&ip6ip6_lock);
- return err;
+
+ return 0;
}
static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,