Index: nf_nat_core.c =================================================================== --- nf_nat_core.c (mainline version) +++ nf_nat_core.c (working copy) @@ -358,7 +358,8 @@ enum nf_nat_manip_type maniptype) { struct net *net = nf_ct_net(ct); - struct nf_conntrack_tuple curr_tuple, new_tuple; + struct nf_conntrack_tuple orig_tuple, new_tuple; + struct nf_conntrack_tuple *curr_tuple = &orig_tuple; struct nf_conn_nat *nat; /* nat helper or nfctnetlink also setup binding */ @@ -378,14 +379,18 @@ /* What we've got will look like inverse of reply. Normally this is what is in the conntrack, except for prior manipulations (future optimization: if num_manips == 0, - orig_tp = - conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */ - nf_ct_invert_tuplepr(&curr_tuple, + curr_tp = orig_tp = + conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) + */ + if (!(ct->status & IPS_DST_NAT)) /* we do the optimization, as mentioned above */ + curr_tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + else + nf_ct_invert_tuplepr(curr_tuple, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); - get_unique_tuple(&new_tuple, &curr_tuple, ranges, ct, maniptype); + get_unique_tuple(&new_tuple, curr_tuple, ranges, ct, maniptype); - if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) { + if (!nf_ct_tuple_equal(&new_tuple, curr_tuple)) { struct nf_conntrack_tuple reply; /* Alter conntrack table so will recognize replies. */ @@ -405,19 +410,20 @@ srchash = nat_hash_by_src(net, 0, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); spin_lock_bh(&nf_nat_lock);