netfilter: nat: propagate errors from xfrm_me_harder()
Propagate errors from ip_xfrm_me_harder() instead of returning EPERM in all cases. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
58e35d1471
commit
aaa795ad25
|
@ -176,6 +176,7 @@ nf_nat_ipv4_out(unsigned int hooknum,
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
const struct nf_conn *ct;
|
const struct nf_conn *ct;
|
||||||
enum ip_conntrack_info ctinfo;
|
enum ip_conntrack_info ctinfo;
|
||||||
|
int err;
|
||||||
#endif
|
#endif
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
|
|
||||||
|
@ -195,9 +196,11 @@ nf_nat_ipv4_out(unsigned int hooknum,
|
||||||
ct->tuplehash[!dir].tuple.dst.u3.ip) ||
|
ct->tuplehash[!dir].tuple.dst.u3.ip) ||
|
||||||
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
|
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
|
||||||
ct->tuplehash[dir].tuple.src.u.all !=
|
ct->tuplehash[dir].tuple.src.u.all !=
|
||||||
ct->tuplehash[!dir].tuple.dst.u.all))
|
ct->tuplehash[!dir].tuple.dst.u.all)) {
|
||||||
if (nf_xfrm_me_harder(skb, AF_INET) < 0)
|
err = nf_xfrm_me_harder(skb, AF_INET);
|
||||||
ret = NF_DROP;
|
if (err < 0)
|
||||||
|
ret = NF_DROP_ERR(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -235,9 +238,11 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
|
||||||
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
||||||
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
|
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
|
||||||
ct->tuplehash[dir].tuple.dst.u.all !=
|
ct->tuplehash[dir].tuple.dst.u.all !=
|
||||||
ct->tuplehash[!dir].tuple.src.u.all)
|
ct->tuplehash[!dir].tuple.src.u.all) {
|
||||||
if (nf_xfrm_me_harder(skb, AF_INET) < 0)
|
err = nf_xfrm_me_harder(skb, AF_INET);
|
||||||
ret = NF_DROP;
|
if (err < 0)
|
||||||
|
ret = NF_DROP_ERR(err);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -179,6 +179,7 @@ nf_nat_ipv6_out(unsigned int hooknum,
|
||||||
#ifdef CONFIG_XFRM
|
#ifdef CONFIG_XFRM
|
||||||
const struct nf_conn *ct;
|
const struct nf_conn *ct;
|
||||||
enum ip_conntrack_info ctinfo;
|
enum ip_conntrack_info ctinfo;
|
||||||
|
int err;
|
||||||
#endif
|
#endif
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
|
|
||||||
|
@ -197,9 +198,11 @@ nf_nat_ipv6_out(unsigned int hooknum,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3) ||
|
&ct->tuplehash[!dir].tuple.dst.u3) ||
|
||||||
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
|
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
|
||||||
ct->tuplehash[dir].tuple.src.u.all !=
|
ct->tuplehash[dir].tuple.src.u.all !=
|
||||||
ct->tuplehash[!dir].tuple.dst.u.all))
|
ct->tuplehash[!dir].tuple.dst.u.all)) {
|
||||||
if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
|
err = nf_xfrm_me_harder(skb, AF_INET6);
|
||||||
ret = NF_DROP;
|
if (err < 0)
|
||||||
|
ret = NF_DROP_ERR(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -236,9 +239,11 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
|
||||||
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
|
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
|
||||||
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
|
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
|
||||||
ct->tuplehash[dir].tuple.dst.u.all !=
|
ct->tuplehash[dir].tuple.dst.u.all !=
|
||||||
ct->tuplehash[!dir].tuple.src.u.all)
|
ct->tuplehash[!dir].tuple.src.u.all) {
|
||||||
if (nf_xfrm_me_harder(skb, AF_INET6))
|
err = nf_xfrm_me_harder(skb, AF_INET6);
|
||||||
ret = NF_DROP;
|
if (err < 0)
|
||||||
|
ret = NF_DROP_ERR(err);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -87,9 +87,10 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
|
||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
unsigned int hh_len;
|
unsigned int hh_len;
|
||||||
struct dst_entry *dst;
|
struct dst_entry *dst;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (xfrm_decode_session(skb, &fl, family) < 0)
|
err = xfrm_decode_session(skb, &fl, family);
|
||||||
return -1;
|
return err;
|
||||||
|
|
||||||
dst = skb_dst(skb);
|
dst = skb_dst(skb);
|
||||||
if (dst->xfrm)
|
if (dst->xfrm)
|
||||||
|
@ -98,7 +99,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
|
||||||
|
|
||||||
dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
|
dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
|
||||||
if (IS_ERR(dst))
|
if (IS_ERR(dst))
|
||||||
return -1;
|
return PTR_ERR(dst);
|
||||||
|
|
||||||
skb_dst_drop(skb);
|
skb_dst_drop(skb);
|
||||||
skb_dst_set(skb, dst);
|
skb_dst_set(skb, dst);
|
||||||
|
@ -107,7 +108,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
|
||||||
hh_len = skb_dst(skb)->dev->hard_header_len;
|
hh_len = skb_dst(skb)->dev->hard_header_len;
|
||||||
if (skb_headroom(skb) < hh_len &&
|
if (skb_headroom(skb) < hh_len &&
|
||||||
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
|
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nf_xfrm_me_harder);
|
EXPORT_SYMBOL(nf_xfrm_me_harder);
|
||||||
|
|
Loading…
Reference in New Issue