#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_acct.h>
#define NF_CONNTRACK_VERSION "0.5.0"
}
struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
- const struct nf_conntrack_tuple *repl)
+ const struct nf_conntrack_tuple *repl,
+ gfp_t gfp)
{
struct nf_conn *ct = NULL;
}
}
- ct = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC);
+ ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp);
if (ct == NULL) {
pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
atomic_dec(&nf_conntrack_count);
return NULL;
}
- ct = nf_conntrack_alloc(tuple, &repl_tuple);
+ ct = nf_conntrack_alloc(tuple, &repl_tuple, GFP_ATOMIC);
if (ct == NULL || IS_ERR(ct)) {
pr_debug("Can't allocate conntrack.\n");
return (struct nf_conntrack_tuple_hash *)ct;
return NULL;
}
+ nf_ct_acct_ext_add(ct, GFP_ATOMIC);
+
spin_lock_bh(&nf_conntrack_lock);
exp = nf_ct_find_expectation(tuple);
if (exp) {
}
acct:
-#ifdef CONFIG_NF_CT_ACCT
if (do_acct) {
- ct->counters[CTINFO2DIR(ctinfo)].packets++;
- ct->counters[CTINFO2DIR(ctinfo)].bytes +=
- skb->len - skb_network_offset(skb);
+ struct nf_conn_counter *acct;
- if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
- || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
- event |= IPCT_COUNTER_FILLING;
+ acct = nf_conn_acct_find(ct);
+ if (acct) {
+ acct[CTINFO2DIR(ctinfo)].packets++;
+ acct[CTINFO2DIR(ctinfo)].bytes +=
+ skb->len - skb_network_offset(skb);
+ }
}
-#endif
spin_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
+bool __nf_ct_kill_acct(struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ int do_acct)
+{
+ if (do_acct) {
+ struct nf_conn_counter *acct;
+
+ spin_lock_bh(&nf_conntrack_lock);
+ acct = nf_conn_acct_find(ct);
+ if (acct) {
+ acct[CTINFO2DIR(ctinfo)].packets++;
+ acct[CTINFO2DIR(ctinfo)].bytes +=
+ skb->len - skb_network_offset(skb);
+ }
+ spin_unlock_bh(&nf_conntrack_lock);
+ }
+
+ if (del_timer(&ct->timeout)) {
+ ct->timeout.function((unsigned long)ct);
+ return true;
+ }
+ return false;
+}
+EXPORT_SYMBOL_GPL(__nf_ct_kill_acct);
+
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
#include <linux/netfilter/nfnetlink.h>
nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
nf_conntrack_htable_size);
- nf_conntrack_proto_fini();
- nf_conntrack_helper_fini();
+ nf_conntrack_acct_fini();
nf_conntrack_expect_fini();
+ nf_conntrack_helper_fini();
+ nf_conntrack_proto_fini();
}
struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
if (ret < 0)
goto out_fini_expect;
+ ret = nf_conntrack_acct_init();
+ if (ret < 0)
+ goto out_fini_helper;
+
/* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
return ret;
+out_fini_helper:
+ nf_conntrack_helper_fini();
out_fini_expect:
nf_conntrack_expect_fini();
out_fini_proto: