#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_acct.h>
#include <net/netfilter/nf_nat.h>
+#include <net/netfilter/nf_nat_core.h>
#define NF_CONNTRACK_VERSION "0.5.0"
-unsigned int
-(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
- enum nf_nat_manip_type manip,
- struct nlattr *attr) __read_mostly;
+int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+ enum nf_nat_manip_type manip,
+ struct nlattr *attr) __read_mostly;
EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook);
DEFINE_SPINLOCK(nf_conntrack_lock);
NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
NF_CT_ASSERT(!timer_pending(&ct->timeout));
- nf_conntrack_event(IPCT_DESTROY, ct);
+ if (!test_bit(IPS_DYING_BIT, &ct->status))
+ nf_conntrack_event(IPCT_DESTROY, ct);
set_bit(IPS_DYING_BIT, &ct->status);
/* To make sure we don't get any weird locking issues here:
hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- spin_lock_bh(&nf_conntrack_lock);
__nf_conntrack_hash_insert(ct, hash, repl_hash);
- spin_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
const struct nf_conntrack_tuple *repl,
gfp_t gfp)
{
- struct nf_conn *ct = NULL;
+ struct nf_conn *ct;
if (unlikely(!nf_conntrack_hash_rnd_initted)) {
get_random_bytes(&nf_conntrack_hash_rnd, 4);
}
ct = nf_conntrack_alloc(net, tuple, &repl_tuple, GFP_ATOMIC);
- if (ct == NULL || IS_ERR(ct)) {
+ if (IS_ERR(ct)) {
pr_debug("Can't allocate conntrack.\n");
return (struct nf_conntrack_tuple_hash *)ct;
}
nf_conntrack_get(&ct->master->ct_general);
NF_CT_STAT_INC(net, expect_new);
} else {
- struct nf_conntrack_helper *helper;
-
- helper = __nf_ct_helper_find(&repl_tuple);
- if (helper) {
- help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
- if (help)
- rcu_assign_pointer(help->helper, helper);
- }
+ __nf_ct_try_assign_helper(ct, GFP_ATOMIC);
NF_CT_STAT_INC(net, new);
}
const struct nf_conntrack_tuple *newreply)
{
struct nf_conn_help *help = nfct_help(ct);
- struct nf_conntrack_helper *helper;
/* Should be unconfirmed, so not in hash table yet */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
return;
rcu_read_lock();
- helper = __nf_ct_helper_find(newreply);
- if (helper == NULL) {
- if (help)
- rcu_assign_pointer(help->helper, NULL);
- goto out;
- }
-
- if (help == NULL) {
- help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
- if (help == NULL)
- goto out;
- } else {
- memset(&help->help, 0, sizeof(help->help));
- }
-
- rcu_assign_pointer(help->helper, helper);
-out:
+ __nf_ct_try_assign_helper(ct, GFP_ATOMIC);
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
}
EXPORT_SYMBOL_GPL(nf_ct_iterate_cleanup);
+struct __nf_ct_flush_report {
+ u32 pid;
+ int report;
+};
+
static int kill_all(struct nf_conn *i, void *data)
{
+ struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data;
+
+ /* get_next_corpse sets the dying bit for us */
+ nf_conntrack_event_report(IPCT_DESTROY,
+ i,
+ fr->pid,
+ fr->report);
return 1;
}
}
EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
-void nf_conntrack_flush(struct net *net)
+void nf_conntrack_flush(struct net *net, u32 pid, int report)
{
- nf_ct_iterate_cleanup(net, kill_all, NULL);
+ struct __nf_ct_flush_report fr = {
+ .pid = pid,
+ .report = report,
+ };
+ nf_ct_iterate_cleanup(net, kill_all, &fr);
}
EXPORT_SYMBOL_GPL(nf_conntrack_flush);
nf_ct_event_cache_flush(net);
nf_conntrack_ecache_fini(net);
i_see_dead_people:
- nf_conntrack_flush(net);
+ nf_conntrack_flush(net, 0, 0);
if (atomic_read(&net->ct.count) != 0) {
schedule();
goto i_see_dead_people;