diff options
Diffstat (limited to 'net/openvswitch/conntrack.c')
| -rw-r--r-- | net/openvswitch/conntrack.c | 32 | 
1 files changed, 24 insertions, 8 deletions
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 05249eb45082..e726159cfcfa 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -903,6 +903,17 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,  	}  	err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->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 = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, +					 maniptype); +	} +  	/* Mark NAT done if successful and update the flow key. */  	if (err == NF_ACCEPT)  		ovs_nat_update_key(key, skb, maniptype); @@ -971,6 +982,8 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,  	ct = nf_ct_get(skb, &ctinfo);  	if (ct) { +		bool add_helper = false; +  		/* Packets starting a new connection must be NATted before the  		 * helper, so that the helper knows about the NAT.  We enforce  		 * this by delaying both NAT and helper calls for unconfirmed @@ -988,16 +1001,17 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,  		}  		/* Userspace may decide to perform a ct lookup without a helper -		 * specified followed by a (recirculate and) commit with one. -		 * Therefore, for unconfirmed connections which we will commit, -		 * we need to attach the helper here. +		 * specified followed by a (recirculate and) commit with one, +		 * or attach a helper in a later commit.  Therefore, for +		 * connections which we will commit, we may need to attach +		 * the helper here.  		 */ -		if (!nf_ct_is_confirmed(ct) && info->commit && -		    info->helper && !nfct_help(ct)) { +		if (info->commit && info->helper && !nfct_help(ct)) {  			int err = __nf_ct_try_assign_helper(ct, info->ct,  							    GFP_ATOMIC);  			if (err)  				return err; +			add_helper = true;  			/* helper installed, add seqadj if NAT is required */  			if (info->nat && !nfct_seqadj(ct)) { @@ -1007,11 +1021,13 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,  		}  		/* Call the helper only if: -		 * - nf_conntrack_in() was executed above ("!cached") for a -		 *   confirmed connection, or +		 * - nf_conntrack_in() was executed above ("!cached") or a +		 *   helper was just attached ("add_helper") for a confirmed +		 *   connection, or  		 * - When committing an unconfirmed connection.  		 */ -		if ((nf_ct_is_confirmed(ct) ? !cached : info->commit) && +		if ((nf_ct_is_confirmed(ct) ? !cached || add_helper : +					      info->commit) &&  		    ovs_ct_helper(skb, info->family) != NF_ACCEPT) {  			return -EINVAL;  		}  |