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

Commit d71bf758 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: netfilter: NATTYPE Refresh Timer Changes"

parents 38e410d9 e6d2be8e
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -54,7 +54,9 @@ bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
			const struct nf_conntrack_l3proto *l3proto,
			const struct nf_conntrack_l3proto *l3proto,
			const struct nf_conntrack_l4proto *l4proto);
			const struct nf_conntrack_l4proto *l4proto);
extern void (*delete_sfe_entry)(struct nf_conn *ct);
extern void (*delete_sfe_entry)(struct nf_conn *ct);
extern bool (*nattype_refresh_timer)(unsigned long nattype);
extern bool (*nattype_refresh_timer)
			(unsigned long nattype,
			unsigned long timeout_value);


/* Find a connection corresponding to a tuple. */
/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *
struct nf_conntrack_tuple_hash *
+75 −56
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
 * Ubicom32 implementation derived from
 * Ubicom32 implementation derived from
 * Cameo's implementation(with many thanks):
 * Cameo's implementation(with many thanks):
 */
 */

#include <linux/types.h>
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/udp.h>
@@ -36,21 +37,17 @@
#include <linux/tcp.h>
#include <linux/tcp.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.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/x_tables.h>
#include <linux/netfilter_ipv4/ipt_NATTYPE.h>
#include <linux/netfilter_ipv4/ipt_NATTYPE.h>
#include <linux/atomic.h>
#include <linux/atomic.h>


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


/* netfilter NATTYPE TODO:
/* netfilter NATTYPE TODO:
 * Add magic value checks to data structure.
 * Add magic value checks to data structure.
@@ -58,14 +55,17 @@ static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN",
struct ipt_nattype {
struct ipt_nattype {
	struct list_head list;
	struct list_head list;
	struct timer_list timeout;
	struct timer_list timeout;
	unsigned char is_valid;
	unsigned long timeout_value;
	unsigned int nattype_cookie;
	unsigned short proto;		/* Protocol: TCP or UDP */
	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 short nat_port;	/* Routed NAT port */
	unsigned int dest_addr;	/* Original egress packets dst addr */
	unsigned int dest_addr;	/* Original egress packets dst addr */
	unsigned short dest_port;/* Original egress packets destination port */
	unsigned short dest_port;/* Original egress packets destination port */
};
};


#define NATTYPE_COOKIE 0x11abcdef

/* TODO: It might be better to use a hash table for performance in
/* TODO: It might be better to use a hash table for performance in
 * heavy traffic.
 * heavy traffic.
 */
 */
@@ -78,11 +78,13 @@ static DEFINE_SPINLOCK(nattype_lock);
static void nattype_nte_debug_print(const struct ipt_nattype *nte,
static void nattype_nte_debug_print(const struct ipt_nattype *nte,
				    const char *s)
				    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, 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),
		ntohs(nte->nat_port),
		&nte->dest_addr, ntohs(nte->dest_port));
		&nte->dest_addr, ntohs(nte->dest_port));
	DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value,
	       nte->timeout.expires);
}
}


/* netfilter NATTYPE nattype_free()
/* netfilter NATTYPE nattype_free()
@@ -90,28 +92,28 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte,
 */
 */
static void nattype_free(struct ipt_nattype *nte)
static void nattype_free(struct ipt_nattype *nte)
{
{
	nattype_nte_debug_print(nte, "free");
	kfree(nte);
	kfree(nte);
}
}


/* netfilter NATTYPE nattype_refresh_timer()
/* netfilter NATTYPE nattype_refresh_timer()
 * Refresh the timer for this object.
 * Refresh the timer for this object.
 */
 */
bool nattype_refresh_timer_impl(unsigned long nat_type)
bool nattype_refresh_timer(unsigned long nat_type, unsigned long timeout_value)
{
{
	struct ipt_nattype *nte = (struct ipt_nattype *)nat_type;
	struct ipt_nattype *nte = (struct ipt_nattype *)nat_type;


	if (!nte)
	if (!nte)
		return false;
		return false;
	spin_lock_bh(&nattype_lock);
	spin_lock_bh(&nattype_lock);
	if (!nte->is_valid) {
	if (nte->nattype_cookie != NATTYPE_COOKIE) {
		spin_unlock_bh(&nattype_lock);
		spin_unlock_bh(&nattype_lock);
		return false;
		return false;
	}
	}
	if (del_timer(&nte->timeout)) {
	if (del_timer(&nte->timeout)) {
		nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ;
		nte->timeout.expires = timeout_value;
		add_timer(&nte->timeout);
		add_timer(&nte->timeout);
		spin_unlock_bh(&nattype_lock);
		spin_unlock_bh(&nattype_lock);
		nattype_nte_debug_print(nte, "refresh");
		return true;
		return true;
	}
	}
	spin_unlock_bh(&nattype_lock);
	spin_unlock_bh(&nattype_lock);
@@ -213,7 +215,8 @@ static bool nattype_packet_in_match(const struct ipt_nattype *nte,
/* netfilter NATTYPE nattype_compare
/* netfilter NATTYPE nattype_compare
 * Compare two entries, return true if relevant fields are the same.
 * 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
	/* netfilter NATTYPE Protocol
	 * compare.
	 * compare.
@@ -228,16 +231,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2)
	  * Since we always keep min/max values the same,
	  * Since we always keep min/max values the same,
	  * just compare the min values.
	  * just compare the min values.
	  */
	  */
	if (n1->range.min_ip != n2->range.min_ip) {
	if (n1->range.min_addr.ip != n2->range.min_addr.ip) {
		DEBUGP("nattype_compare: r.min_ip mismatch: %pI4:%pI4\n",
		DEBUGP("nattype_compare: r.min_addr.ip mismatch: %pI4:%pI4\n",
		       &n1->range.min_ip, &n2->range.min_ip);
		       &n1->range.min_addr.ip, &n2->range.min_addr.ip);
		return false;
		return false;
	}
	}


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


@@ -250,20 +253,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2)
		return false;
		return false;
	}
	}


	/* netfilter NATTYPE
	/* netfilter NATTYPE Destination compare
	 * Destination compare
	 * Destination Comapre for Address Restricted Cone NAT.
	 */
	 */
	if (n1->dest_addr != n2->dest_addr) {
	if ((info->type == TYPE_ADDRESS_RESTRICTED) &&
	    (n1->dest_addr != n2->dest_addr)) {
		DEBUGP("nattype_compare: dest_addr mismatch: %pI4:%pI4\n",
		DEBUGP("nattype_compare: dest_addr mismatch: %pI4:%pI4\n",
		       &n1->dest_addr, &n2->dest_addr);
		       &n1->dest_addr, &n2->dest_addr);
		return false;
		return false;
	}
	}


	if (n1->dest_port != n2->dest_port) {
		DEBUGP("nattype_compare: dest_port mismatch: %d:%d\n",
		       ntohs(n1->dest_port), ntohs(n2->dest_port));
		return false;
	}
	return true;
	return true;
}
}


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


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


		/* Expand the ingress conntrack
		/* netfilter
		 * to include the reply as source
		 * 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",
		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;
		ct->nattype_entry = (unsigned long)nte;
		ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
		ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
		DEBUGP("Expand returned: %d\n", ret);
		DEBUGP("Expand returned: %d\n", ret);
@@ -332,12 +341,22 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	enum ip_conntrack_info ctinfo;
	enum ip_conntrack_info ctinfo;
	const struct ipt_nattype_info *info = par->targinfo;
	const struct ipt_nattype_info *info = par->targinfo;
	u16 nat_port;
	u16 nat_port;
	enum ip_conntrack_dir dir;


	if (par->hooknum != NF_INET_FORWARD)

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

	/* 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;
		return XT_CONTINUE;


	/* Ingress packet,
	/* netfilter
	 * refresh the timer if we find an entry.
	 * Ingress packet, refresh the timer if we find an entry.
	 */
	 */
	if (info->mode == MODE_FORWARD_IN) {
	if (info->mode == MODE_FORWARD_IN) {
		spin_lock_bh(&nattype_lock);
		spin_lock_bh(&nattype_lock);
@@ -355,7 +374,8 @@ static unsigned int nattype_forward(struct sk_buff *skb,
			 * out and forward fail as though we never
			 * out and forward fail as though we never
			 * found the entry.
			 * found the entry.
			 */
			 */
			if (!nattype_refresh_timer((unsigned long)nte))
			if (!nattype_refresh_timer((unsigned long)nte,
						   ct->timeout.expires))
				break;
				break;


			/* netfilter NATTYPE
			/* netfilter NATTYPE
@@ -372,15 +392,9 @@ static unsigned int nattype_forward(struct sk_buff *skb,
		return XT_CONTINUE;
		return XT_CONTINUE;
	}
	}


	/* netfilter NATTYPE
	dir = CTINFO2DIR(ctinfo);
	 * 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;


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


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


	/* netfilter NATTYPE
	/* netfilter NATTYPE
	 * TOOD: Would it be better to get this information from the
	 * TOOD: Would it be better to get this information from the
	 * conntrack instead of the headers.
	 * conntrack instead of the headers.
	 */
	 */
	if (iph->protocol == IPPROTO_TCP) {
	if (iph->protocol == IPPROTO_TCP) {
		nte->range.min.tcp.port = ((struct tcphdr *)protoh)->source;
		nte->range.min_proto.tcp.port =
		nte->range.max.tcp.port = nte->range.min.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;
		nte->dest_port = ((struct tcphdr *)protoh)->dest;
	} else if (iph->protocol == IPPROTO_UDP) {
	} else if (iph->protocol == IPPROTO_UDP) {
		nte->range.min.udp.port = ((struct udphdr *)protoh)->source;
		nte->range.min_proto.udp.port =
		nte->range.max.udp.port = nte->range.min.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->dest_port = ((struct udphdr *)protoh)->dest;
	}
	}
	nte->range.flags = (NF_NAT_RANGE_MAP_IPS |
	nte->range.flags = (NF_NAT_RANGE_MAP_IPS |
@@ -430,7 +446,7 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	 */
	 */
	spin_lock_bh(&nattype_lock);
	spin_lock_bh(&nattype_lock);
	list_for_each_entry(nte2, &nattype_list, list) {
	list_for_each_entry(nte2, &nattype_list, list) {
		if (!nattype_compare(nte, nte2))
		if (!nattype_compare(nte, nte2, info))
			continue;
			continue;
		spin_unlock_bh(&nattype_lock);
		spin_unlock_bh(&nattype_lock);
		/* netfilter NATTYPE
		/* netfilter NATTYPE
@@ -438,7 +454,9 @@ static unsigned int nattype_forward(struct sk_buff *skb,
		 * entry as this one is timed out and will be removed
		 * entry as this one is timed out and will be removed
		 * from the list shortly.
		 * from the list shortly.
		 */
		 */
		if (!nattype_refresh_timer((unsigned long)nte2))
		if (!nattype_refresh_timer(
			(unsigned long)nte2,
			jiffies + nte2->timeout_value))
			break;
			break;


		/* netfilter NATTYPE
		/* netfilter NATTYPE
@@ -455,11 +473,12 @@ static unsigned int nattype_forward(struct sk_buff *skb,
	/* netfilter NATTYPE
	/* netfilter NATTYPE
	 * Add the new entry to the list.
	 * 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);
	add_timer(&nte->timeout);
	list_add(&nte->list, &nattype_list);
	list_add(&nte->list, &nattype_list);
	ct->nattype_entry = (unsigned long)nte;
	ct->nattype_entry = (unsigned long)nte;
	nte->is_valid = 1;
	nte->nattype_cookie = NATTYPE_COOKIE;
	spin_unlock_bh(&nattype_lock);
	spin_unlock_bh(&nattype_lock);
	nattype_nte_debug_print(nte, "ADD");
	nattype_nte_debug_print(nte, "ADD");
	return XT_CONTINUE;
	return XT_CONTINUE;
@@ -549,7 +568,7 @@ static int nattype_check(const struct xt_tgchk_param *par)
	       types[info->type], modes[info->mode]);
	       types[info->type], modes[info->mode]);


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


+6 −0
Original line number Original line Diff line number Diff line
@@ -68,7 +68,13 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
	newrange.max_proto   = range->max_proto;
	newrange.max_proto   = range->max_proto;


	/* Hand modified range to generic setup. */
	/* Hand modified range to generic setup. */
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
	nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
	return XT_CONTINUE;
#else
	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
	return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
#endif

}
}
EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4);
EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4);


+11 −3
Original line number Original line Diff line number Diff line
@@ -72,7 +72,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock);
struct hlist_nulls_head *nf_conntrack_hash __read_mostly;
struct hlist_nulls_head *nf_conntrack_hash __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_hash);
EXPORT_SYMBOL_GPL(nf_conntrack_hash);


bool (*nattype_refresh_timer)(unsigned long nattype) __rcu __read_mostly;
bool (*nattype_refresh_timer)
	(unsigned long nattype,
	unsigned long timeout_value)
	__rcu __read_mostly;
EXPORT_SYMBOL(nattype_refresh_timer);
EXPORT_SYMBOL(nattype_refresh_timer);


struct conntrack_gc_work {
struct conntrack_gc_work {
@@ -1110,6 +1113,9 @@ __nf_conntrack_alloc(struct net *net,


	nf_ct_zone_add(ct, zone);
	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
	/* Because we use RCU lookups, we set ct_general.use to zero before
	 * this is inserted in any list.
	 * this is inserted in any list.
	 */
	 */
@@ -1482,7 +1488,9 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
	struct nf_conn_acct *acct;
	struct nf_conn_acct *acct;
	u64 pkts;
	u64 pkts;
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
	bool (*nattype_ref_timer)(unsigned long nattype);
	bool (*nattype_ref_timer)
		(unsigned long nattype,
		unsigned long timeout_value);
#endif
#endif


	NF_CT_ASSERT(skb);
	NF_CT_ASSERT(skb);
@@ -1500,7 +1508,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
	nattype_ref_timer = rcu_dereference(nattype_refresh_timer);
	nattype_ref_timer = rcu_dereference(nattype_refresh_timer);
	if (nattype_ref_timer)
	if (nattype_ref_timer)
		nattype_ref_timer(ct->nattype_entry);
		nattype_ref_timer(ct->nattype_entry, ct->timeout.expires);
#endif
#endif


acct:
acct:
+11 −0
Original line number Original line Diff line number Diff line
@@ -1540,12 +1540,23 @@ static int ctnetlink_change_timeout(struct nf_conn *ct,
				    const struct nlattr * const cda[])
				    const struct nlattr * const cda[])
{
{
	u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
	u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
#if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE)
	bool (*nattype_ref_timer)
		(unsigned long nattype,
		unsigned long timeout_value);
#endif


	ct->timeout = nfct_time_stamp + timeout * HZ;
	ct->timeout = nfct_time_stamp + timeout * HZ;


	if (test_bit(IPS_DYING_BIT, &ct->status))
	if (test_bit(IPS_DYING_BIT, &ct->status))
		return -ETIME;
		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;
	return 0;
}
}