[IPV6] IP6TUNNEL: Split out generic routine in ip6ip6_err().
This enables to add IPv4/IPv6 specific error handling later, Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7159039a12
commit
e490d1d85c
1 changed files with 39 additions and 14 deletions
|
@ -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:
|
* 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.
|
* to the specifications in RFC 2473.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
ip6_tnl_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
int type, int code, int offset, __be32 info)
|
int *type, int *code, int *msg, __be32 *info, int offset)
|
||||||
{
|
{
|
||||||
struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
|
struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data;
|
||||||
struct ip6_tnl *t;
|
struct ip6_tnl *t;
|
||||||
|
@ -402,7 +402,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (*type) {
|
||||||
__u32 teli;
|
__u32 teli;
|
||||||
struct ipv6_tlv_tnl_enc_lim *tel;
|
struct ipv6_tlv_tnl_enc_lim *tel;
|
||||||
__u32 mtu;
|
__u32 mtu;
|
||||||
|
@ -414,7 +414,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
rel_msg = 1;
|
rel_msg = 1;
|
||||||
break;
|
break;
|
||||||
case ICMPV6_TIME_EXCEED:
|
case ICMPV6_TIME_EXCEED:
|
||||||
if (code == ICMPV6_EXC_HOPLIMIT) {
|
if ((*code) == ICMPV6_EXC_HOPLIMIT) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"%s: Too small hop limit or "
|
"%s: Too small hop limit or "
|
||||||
|
@ -425,10 +425,10 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
break;
|
break;
|
||||||
case ICMPV6_PARAMPROB:
|
case ICMPV6_PARAMPROB:
|
||||||
teli = 0;
|
teli = 0;
|
||||||
if (code == ICMPV6_HDR_FIELD)
|
if ((*code) == ICMPV6_HDR_FIELD)
|
||||||
teli = parse_tlv_tnl_enc_lim(skb, skb->data);
|
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];
|
tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
|
||||||
if (tel->encap_limit == 0) {
|
if (tel->encap_limit == 0) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
|
@ -445,7 +445,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ICMPV6_PKT_TOOBIG:
|
case ICMPV6_PKT_TOOBIG:
|
||||||
mtu = ntohl(info) - offset;
|
mtu = ntohl(*info) - offset;
|
||||||
if (mtu < IPV6_MIN_MTU)
|
if (mtu < IPV6_MIN_MTU)
|
||||||
mtu = IPV6_MIN_MTU;
|
mtu = IPV6_MIN_MTU;
|
||||||
t->dev->mtu = mtu;
|
t->dev->mtu = mtu;
|
||||||
|
@ -458,12 +458,38 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
}
|
}
|
||||||
break;
|
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 rt6_info *rt;
|
||||||
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||||
|
|
||||||
if (!skb2)
|
if (!skb2)
|
||||||
goto out;
|
return 0;
|
||||||
|
|
||||||
dst_release(skb2->dst);
|
dst_release(skb2->dst);
|
||||||
skb2->dst = NULL;
|
skb2->dst = NULL;
|
||||||
|
@ -483,9 +509,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||||
|
|
||||||
kfree_skb(skb2);
|
kfree_skb(skb2);
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
read_unlock(&ip6ip6_lock);
|
return 0;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
|
static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
|
||||||
|
|
Loading…
Add table
Reference in a new issue