summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAaron Conole <aconole@redhat.com>2019-12-04 00:34:14 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-18 18:08:59 +0300
commit4e57c233915e898678e5654d9b91ab24600fe7e5 (patch)
tree4f92e275210592f678db7bc9759503ff012c5e6a /net
parent411fdb975269ac2d1d746535eadb25dea3813189 (diff)
downloadlinux-4e57c233915e898678e5654d9b91ab24600fe7e5.tar.xz
act_ct: support asymmetric conntrack
[ Upstream commit 95219afbb980f10934de9f23a3e199be69c5ed09 ] The act_ct TC module shares a common conntrack and NAT infrastructure exposed via netfilter. It's possible that a packet needs both SNAT and DNAT manipulation, due to e.g. tuple collision. Netfilter can support this because it runs through the NAT table twice - once on ingress and again after egress. The act_ct action doesn't have such capability. Like netfilter hook infrastructure, we should run through NAT twice to keep the symmetry. Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct") Signed-off-by: Aaron Conole <aconole@redhat.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/sched/act_ct.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index fcc46025e790..f3232a00970f 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
bool commit)
{
#if IS_ENABLED(CONFIG_NF_NAT)
+ int err;
enum nf_nat_manip_type maniptype;
if (!(ct_action & TCA_CT_ACT_NAT))
@@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
return NF_ACCEPT;
}
- return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ if (err == NF_ACCEPT &&
+ ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
+ if (maniptype == NF_NAT_MANIP_SRC)
+ maniptype = NF_NAT_MANIP_DST;
+ else
+ maniptype = NF_NAT_MANIP_SRC;
+
+ err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ }
+ return err;
#else
return NF_ACCEPT;
#endif