msm: netfilter: NATTYPE Refresh Timer Changes

When IPA is present, all the data packets go through IPA
and as a result NATTYPE entry timeout will not be refreshed
and eventually it times out. IPA periodically refreshes
the connection tracking entry timeout. So making changes to refresh
the NATTYPE entry timeout from the connection tracking module.

Change-Id: I5861427990af4bfd6046d21809a778409d0d8d5f
Signed-off-by: Paras Singh Jain <parassin@codeaurora.org>
This commit is contained in:
Paras Singh Jain 2020-09-03 19:15:02 +05:30
commit 87581bec40
4 changed files with 53 additions and 7 deletions

View file

@ -55,6 +55,11 @@ struct nf_conntrack_net {
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
/* Handle NATTYPE Stuff,only if NATTYPE module was defined */
#ifdef CONFIG_IP_NF_TARGET_NATTYPE_MODULE
#include <linux/netfilter_ipv4/ipt_NATTYPE.h>
#endif
struct nf_conn {
/* Usage count in here is 1 for hash table, 1 per skb,
* plus 1 for any connection(s) we are `master' for
@ -103,6 +108,10 @@ struct nf_conn {
/* Extensions */
struct nf_ct_ext *ext;
#ifdef CONFIG_IP_NF_TARGET_NATTYPE_MODULE
unsigned long nattype_entry;
#endif
/* Storage reserved for other modules, must be the last member */
union nf_conntrack_proto proto;
};

View file

@ -43,6 +43,7 @@ void nf_conntrack_cleanup_end(void);
bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
extern bool (*nattype_refresh_timer)(unsigned long nattype) __rcu __read_mostly;
/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *

View file

@ -32,6 +32,7 @@ static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN",
struct ipt_nattype {
struct list_head list;
struct timer_list timeout;
unsigned char is_valid;
unsigned short proto; /* Protocol: TCP or UDP */
struct nf_nat_ipv4_range range; /* LAN side src info*/
unsigned short nat_port; /* Routed NAT port */
@ -67,13 +68,24 @@ static void nattype_free(struct ipt_nattype *nte)
/* netfilter NATTYPE nattype_refresh_timer()
* Refresh the timer for this object.
*/
static bool nattype_refresh_timer(struct ipt_nattype *nte)
bool nattype_refresh_timer_impl(unsigned long nat_type)
{
struct ipt_nattype *nte = (struct ipt_nattype *)nat_type;
if (!nte)
return false;
spin_lock_bh(&nattype_lock);
if (!nte->is_valid) {
spin_unlock_bh(&nattype_lock);
return false;
}
if (del_timer(&nte->timeout)) {
nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ;
add_timer(&nte->timeout);
spin_unlock_bh(&nattype_lock);
return true;
}
spin_unlock_bh(&nattype_lock);
return false;
}
@ -92,6 +104,7 @@ static void nattype_timer_timeout(unsigned long in_nattype)
nattype_nte_debug_print(nte, "timeout");
spin_lock_bh(&nattype_lock);
list_del(&nte->list);
memset(nte, 0, sizeof(struct ipt_nattype));
spin_unlock_bh(&nattype_lock);
nattype_free(nte);
}
@ -267,7 +280,8 @@ static unsigned int nattype_nat(struct sk_buff *skb,
* to include the reply as source
*/
DEBUGP("Expand ingress conntrack=%p, type=%d, src[%pI4:%d]\n",
ct, ctinfo, &newrange.min_ip, ntohs(newrange.min.all));
ct, ctinfo, &newrange.min_ip, ntohs(newrange.min.all));
ct->nattype_entry = (unsigned long)nte;
ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
DEBUGP("Expand returned: %d\n", ret);
return ret;
@ -307,12 +321,13 @@ static unsigned int nattype_forward(struct sk_buff *skb,
if (!nattype_packet_in_match(nte, skb, info))
continue;
spin_unlock_bh(&nattype_lock);
/* netfilter NATTYPE
* Refresh the timer, if we fail, break
* out and forward fail as though we never
* found the entry.
*/
if (!nattype_refresh_timer(nte))
if (!nattype_refresh_timer((unsigned long)nte))
break;
/* netfilter NATTYPE
@ -320,7 +335,6 @@ static unsigned int nattype_forward(struct sk_buff *skb,
* entry values should not change so print
* them outside the lock.
*/
spin_unlock_bh(&nattype_lock);
nattype_nte_debug_print(nte, "refresh");
DEBUGP("FORWARD_IN_ACCEPT\n");
return NF_ACCEPT;
@ -386,13 +400,13 @@ static unsigned int nattype_forward(struct sk_buff *skb,
list_for_each_entry(nte2, &nattype_list, list) {
if (!nattype_compare(nte, nte2))
continue;
spin_unlock_bh(&nattype_lock);
/* netfilter NATTYPE
* If we can not refresh this entry, insert our new
* entry as this one is timed out and will be removed
* from the list shortly.
*/
if (!nattype_refresh_timer(nte2))
if (!nattype_refresh_timer((unsigned long)nte2))
break;
/* netfilter NATTYPE
@ -401,7 +415,6 @@ static unsigned int nattype_forward(struct sk_buff *skb,
*
* Free up the new entry.
*/
spin_unlock_bh(&nattype_lock);
nattype_nte_debug_print(nte2, "refresh");
nattype_free(nte);
return XT_CONTINUE;
@ -413,6 +426,8 @@ static unsigned int nattype_forward(struct sk_buff *skb,
nte->timeout.expires = jiffies + (NATTYPE_TIMEOUT * HZ);
add_timer(&nte->timeout);
list_add(&nte->list, &nattype_list);
ct->nattype_entry = (unsigned long)nte;
nte->is_valid = 1;
spin_unlock_bh(&nattype_lock);
nattype_nte_debug_print(nte, "ADD");
return XT_CONTINUE;
@ -545,6 +560,8 @@ static struct xt_target nattype = {
static int __init init(void)
{
WARN_ON(nattype_refresh_timer);
RCU_INIT_POINTER(nattype_refresh_timer, nattype_refresh_timer_impl);
return xt_register_target(&nattype);
}

View file

@ -64,6 +64,9 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock);
struct hlist_nulls_head *nf_conntrack_hash __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_hash);
bool (*nattype_refresh_timer)(unsigned long nattype) __rcu __read_mostly;
EXPORT_SYMBOL(nattype_refresh_timer);
struct conntrack_gc_work {
struct delayed_work dwork;
u32 last_bucket;
@ -1495,6 +1498,10 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
#endif
#ifdef CONFIG_NF_CONNTRACK_SECMARK
ct->secmark = exp->master->secmark;
#endif
/* Initialize the NAT type entry. */
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
ct->nattype_entry = 0;
#endif
NF_CT_STAT_INC(net, expect_new);
}
@ -1784,6 +1791,10 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
u32 extra_jiffies,
bool do_acct)
{
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
bool (*nattype_ref_timer)(unsigned long nattype);
#endif
/* Only update if this is not a fixed timeout */
if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status))
goto acct;
@ -1794,6 +1805,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
if (READ_ONCE(ct->timeout) != extra_jiffies)
WRITE_ONCE(ct->timeout, extra_jiffies);
/* Refresh the NAT type entry. */
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
nattype_ref_timer = rcu_dereference(nattype_refresh_timer);
if (nattype_ref_timer)
nattype_ref_timer(ct->nattype_entry);
#endif
acct:
if (do_acct)
nf_ct_acct_update(ct, ctinfo, skb->len);