Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 116b7811 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: netfilter: NATTYPE Refresh Timer Changes"

parents 6d922e2c cd7cefac
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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;
};
+4 −0
Original line number Diff line number Diff line
@@ -43,6 +43,10 @@ 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,
			unsigned long timeout_value)
			__rcu __read_mostly;

/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *
+96 −52
Original line number Diff line number Diff line
@@ -13,32 +13,32 @@
#include <linux/tcp.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_nat.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ipt_NATTYPE.h>
#include <linux/atomic.h>

#if !defined(NATTYPE_DEBUG)
#define DEBUGP(type, args...)
#else
static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED",
			"TYPE_ENDPOINT_INDEPENDENT",
			"TYPE_ADDRESS_RESTRICTED"};
static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN",
			"MODE_FORWARD_OUT"};
#define DEBUGP(args...) pr_debug(args)
#endif

struct ipt_nattype {
	struct list_head list;
	struct timer_list timeout;
	unsigned long timeout_value;
	unsigned int nattype_cookie;
	unsigned short proto;		/* Protocol: TCP or UDP */
	struct nf_nat_ipv4_range range;	/* LAN side src info*/
	struct nf_nat_range range;	/* LAN side source information */
	unsigned short nat_port;	/* Routed NAT port */
	unsigned int dest_addr;	/* Original egress packets dst addr */
	unsigned short dest_port;/* Original egress packets destination port */
};

#define NATTYPE_COOKIE 0x11abcdef

static LIST_HEAD(nattype_list);
static DEFINE_SPINLOCK(nattype_lock);

@@ -48,11 +48,13 @@ static DEFINE_SPINLOCK(nattype_lock);
static void nattype_nte_debug_print(const struct ipt_nattype *nte,
				    const char *s)
{
	DEBUGP("%p: %s - proto[%d], src[%pI4:%d], nat[<x>:%d], dest[%pI4:%d]\n",
	DEBUGP("%p:%s-proto[%d],src[%pI4:%d],nat[%d],dest[%pI4:%d]\n",
	       nte, s, nte->proto,
		&nte->range.min_ip, ntohs(nte->range.min.all),
	       &nte->range.min_addr.ip, ntohs(nte->range.min_proto.all),
		ntohs(nte->nat_port),
		&nte->dest_addr, ntohs(nte->dest_port));
	DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value,
	       nte->timeout.expires);
}

/* netfilter NATTYPE nattype_free()
@@ -60,20 +62,31 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte,
 */
static void nattype_free(struct ipt_nattype *nte)
{
	nattype_nte_debug_print(nte, "free");
	kfree(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(unsigned long nat_type, unsigned long timeout_value)
{
	struct ipt_nattype *nte = (struct ipt_nattype *)nat_type;

	if (!nte)
		return false;
	spin_lock_bh(&nattype_lock);
	if (nte->nattype_cookie != NATTYPE_COOKIE) {
		spin_unlock_bh(&nattype_lock);
		return false;
	}
	if (del_timer(&nte->timeout)) {
		nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ;
		nte->timeout.expires = timeout_value;
		add_timer(&nte->timeout);
		spin_unlock_bh(&nattype_lock);
		nattype_nte_debug_print(nte, "refresh");
		return true;
	}
	spin_unlock_bh(&nattype_lock);
	return false;
}

@@ -92,6 +105,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);
}
@@ -171,7 +185,8 @@ static bool nattype_packet_in_match(const struct ipt_nattype *nte,
/* netfilter NATTYPE nattype_compare
 * Compare two entries, return true if relevant fields are the same.
 */
static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2)
static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2,
			    const struct ipt_nattype_info *info)
{
	/* netfilter NATTYPE Protocol
	 * compare.
@@ -186,17 +201,18 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2)
	  * Since we always keep min/max values the same,
	  * just compare the min values.
	  */
	if (n1->range.min_ip != n2->range.min_ip) {
		DEBUGP("%s: r.min_ip mismatch: %pI4:%pI4\n",
		       __func__, &n1->range.min_ip, &n2->range.min_ip);
	if (n1->range.min_addr.ip != n2->range.min_addr.ip) {
		DEBUGP("%s: r.min_addr.ip mismatch: %pI4:%pI4\n",
		       __func__, &n1->range.min_addr.ip,
			   &n2->range.min_addr.ip);
		return false;
	}

	if (n1->range.min.all != n2->range.min.all) {
	if (n1->range.min_proto.all != n2->range.min_proto.all) {
		DEBUGP("%s: r.min mismatch: %d:%d\n",
				__func__,
		       ntohs(n1->range.min.all),
		       ntohs(n2->range.min.all));
				ntohs(n1->range.min_proto.all),
				ntohs(n2->range.min_proto.all));
		return false;
	}

@@ -209,9 +225,6 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2)
		return false;
	}

	/* netfilter NATTYPE
	 * Destination compare
	 */
	if (n1->dest_addr != n2->dest_addr) {
		DEBUGP("%s: dest_addr mismatch: %pI4:%pI4\n",
		       __func__, &n1->dest_addr, &n2->dest_addr);
@@ -223,6 +236,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2)
		       __func__, ntohs(n1->dest_port), ntohs(n2->dest_port));
		return false;
	}
	/* netfilter NATTYPE Destination compare
	 * Destination Comapre for Address Restricted Cone NAT.
	 */
	if (info->type == TYPE_ADDRESS_RESTRICTED &&
	    n1->dest_addr != n2->dest_addr) {
		DEBUGP("%s: dest_addr mismatch: %pI4:%pI4\n",
		       __func__, &n1->dest_addr, &n2->dest_addr);
		return false;
	}

	return true;
}

@@ -242,7 +265,7 @@ static unsigned int nattype_nat(struct sk_buff *skb,
	list_for_each_entry(nte, &nattype_list, list) {
		struct nf_conn *ct;
		enum ip_conntrack_info ctinfo;
		struct nf_nat_ipv4_range newrange;
		struct nf_nat_range newrange;
		unsigned int ret;

		if (!nattype_packet_in_match(nte, skb, par->targinfo))
@@ -263,11 +286,22 @@ static unsigned int nattype_nat(struct sk_buff *skb,
			return XT_CONTINUE;
		}

		/* Expand the ingress conntrack
		 * to include the reply as source
		/* netfilter
		 * Refresh the timer, if we fail, break
		 * out and forward fail as though we never
		 * found the entry.
		 */
		if (!nattype_refresh_timer((unsigned long)nte,
					   jiffies + nte->timeout_value))
			break;

		/* netfilter
		 * Expand the ingress conntrack 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_addr.ip,
			ntohs(newrange.min_proto.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;
@@ -290,12 +324,21 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	enum ip_conntrack_info ctinfo;
	const struct ipt_nattype_info *info = par->targinfo;
	u16 nat_port;
	enum ip_conntrack_dir dir;

	if (par->hooknum != NF_INET_FORWARD)
	if (par->hooknum != NF_INET_POST_ROUTING)
		return XT_CONTINUE;

	/* Ingress packet,
	 * refresh the timer if we find an entry.
	/* netfilter
	 * Egress packet, create a new rule in our list.  If conntrack does
	 * not have an entry, skip this packet.
	 */
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct)
		return XT_CONTINUE;

	/* netfilter
	 * Ingress packet, refresh the timer if we find an entry.
	 */
	if (info->mode == MODE_FORWARD_IN) {
		spin_lock_bh(&nattype_lock);
@@ -307,12 +350,14 @@ 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,
						   ct->timeout.expires))
				break;

			/* netfilter NATTYPE
@@ -320,7 +365,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;
@@ -330,15 +374,9 @@ static unsigned int nattype_forward(struct sk_buff *skb,
		return XT_CONTINUE;
	}

	/* netfilter NATTYPE
	 * Egress packet, create a new rule in our list.  If conntrack does
	 * not have an entry, skip this packet.
	 */
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || (ctinfo == IP_CT_NEW && ctinfo == IP_CT_RELATED))
		return XT_CONTINUE;
	dir = CTINFO2DIR(ctinfo);

	nat_port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all;
	nat_port = ct->tuplehash[!dir].tuple.dst.u.all;

	/* netfilter NATTYPE
	 * Allocate a new entry
@@ -354,16 +392,18 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	nte->proto = iph->protocol;
	nte->nat_port = nat_port;
	nte->dest_addr = iph->daddr;
	nte->range.min_ip = iph->saddr;
	nte->range.max_ip = nte->range.min_ip;
	nte->range.min_addr.ip = iph->saddr;
	nte->range.max_addr.ip = nte->range.min_addr.ip;

	if (iph->protocol == IPPROTO_TCP) {
		nte->range.min.tcp.port = ((struct tcphdr *)protoh)->source;
		nte->range.max.tcp.port = nte->range.min.tcp.port;
		nte->range.min_proto.tcp.port =
					((struct tcphdr *)protoh)->source;
		nte->range.max_proto.tcp.port = nte->range.min_proto.tcp.port;
		nte->dest_port = ((struct tcphdr *)protoh)->dest;
	} else if (iph->protocol == IPPROTO_UDP) {
		nte->range.min.udp.port = ((struct udphdr *)protoh)->source;
		nte->range.max.udp.port = nte->range.min.udp.port;
		nte->range.min_proto.udp.port =
					((struct udphdr *)protoh)->source;
		nte->range.max_proto.udp.port = nte->range.min_proto.udp.port;
		nte->dest_port = ((struct udphdr *)protoh)->dest;
	}
	nte->range.flags = (NF_NAT_RANGE_MAP_IPS |
@@ -384,15 +424,15 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	 */
	spin_lock_bh(&nattype_lock);
	list_for_each_entry(nte2, &nattype_list, list) {
		if (!nattype_compare(nte, nte2))
		if (!nattype_compare(nte, nte2, info))
			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, jiffies + nte2->timeout_value))
			break;

		/* netfilter NATTYPE
@@ -401,7 +441,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;
@@ -410,9 +449,12 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	/* netfilter NATTYPE
	 * Add the new entry to the list.
	 */
	nte->timeout.expires = jiffies + (NATTYPE_TIMEOUT  * HZ);
	nte->timeout_value = ct->timeout.expires;
	nte->timeout.expires = ct->timeout.expires + jiffies;
	add_timer(&nte->timeout);
	list_add(&nte->list, &nattype_list);
	ct->nattype_entry = (unsigned long)nte;
	nte->nattype_cookie = NATTYPE_COOKIE;
	spin_unlock_bh(&nattype_lock);
	nattype_nte_debug_print(nte, "ADD");
	return XT_CONTINUE;
@@ -498,7 +540,7 @@ static int nattype_check(const struct xt_tgchk_param *par)
	       __func__, types[info->type], modes[info->mode]);

	if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) |
		(1 << NF_INET_FORWARD))) {
		(1 << NF_INET_POST_ROUTING))) {
		DEBUGP("%s: bad hooks %x.\n", __func__, par->hook_mask);
		return -EINVAL;
	}
@@ -539,12 +581,14 @@ static struct xt_target nattype = {
	.checkentry	= nattype_check,
	.targetsize	= sizeof(struct ipt_nattype_info),
	.hooks		= ((1 << NF_INET_PRE_ROUTING) |
				(1 << NF_INET_FORWARD)),
				(1 << NF_INET_POST_ROUTING)),
	.me		= THIS_MODULE,
};

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);
}

+27 −0
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ 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,
	unsigned long timeout_value)
	__rcu __read_mostly;
EXPORT_SYMBOL(nattype_refresh_timer);

struct conntrack_gc_work {
	struct delayed_work	dwork;
	u32			last_bucket;
@@ -1387,6 +1393,9 @@ __nf_conntrack_alloc(struct net *net,

	nf_ct_zone_add(ct, zone);

#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
	ct->nattype_entry = 0;
#endif
	/* Because we use RCU lookups, we set ct_general.use to zero before
	 * this is inserted in any list.
	 */
@@ -1495,6 +1504,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 +1797,12 @@ 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,
		unsigned long timeout_value);
#endif

	/* Only update if this is not a fixed timeout */
	if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status))
		goto acct;
@@ -1794,6 +1813,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, ct->timeout.expires);
#endif

acct:
	if (do_acct)
		nf_ct_acct_update(ct, ctinfo, skb->len);
+11 −0
Original line number Diff line number Diff line
@@ -1686,6 +1686,11 @@ static int ctnetlink_change_timeout(struct nf_conn *ct,
				    const struct nlattr * const cda[])
{
	u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
	bool (*nattype_ref_timer)
		(unsigned long nattype,
		unsigned long timeout_value);
#endif

	if (timeout > INT_MAX)
		timeout = INT_MAX;
@@ -1694,6 +1699,12 @@ static int ctnetlink_change_timeout(struct nf_conn *ct,
	if (test_bit(IPS_DYING_BIT, &ct->status))
		return -ETIME;

/* 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, ct->timeout.expires);
#endif
	return 0;
}

Loading