#include <linux/netfilter.h>
#include <net/netlink.h>
+#include <net/netns/generic.h>
#include <net/sock.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_cttimeout.h>
+static unsigned int nfct_timeout_id __read_mostly;
+
+struct nfct_timeout_pernet {
+ struct list_head nfct_timeout_list;
+};
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
[CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
};
+static struct nfct_timeout_pernet *nfct_timeout_pernet(struct net *net)
+{
+ return net_generic(net, nfct_timeout_id);
+}
+
static int
ctnl_timeout_parse_policy(void *timeout,
const struct nf_conntrack_l4proto *l4proto,
const struct nlattr * const cda[],
struct netlink_ext_ack *extack)
{
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
__u16 l3num;
__u8 l4num;
const struct nf_conntrack_l4proto *l4proto;
l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
- list_for_each_entry(timeout, &net->nfct_timeout_list, head) {
+ list_for_each_entry(timeout, &pernet->nfct_timeout_list, head) {
if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
continue;
timeout->timeout.l3num = l3num;
timeout->timeout.l4proto = l4proto;
refcount_set(&timeout->refcnt, 1);
- list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
+ list_add_tail_rcu(&timeout->head, &pernet->nfct_timeout_list);
return 0;
err:
static int
ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct nfct_timeout_pernet *pernet;
struct net *net = sock_net(skb->sk);
struct ctnl_timeout *cur, *last;
cb->args[1] = 0;
rcu_read_lock();
- list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) {
+ pernet = nfct_timeout_pernet(net);
+ list_for_each_entry_rcu(cur, &pernet->nfct_timeout_list, head) {
if (last) {
if (cur != last)
continue;
const struct nlattr * const cda[],
struct netlink_ext_ack *extack)
{
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
int ret = -ENOENT;
char *name;
struct ctnl_timeout *cur;
return -EINVAL;
name = nla_data(cda[CTA_TIMEOUT_NAME]);
- list_for_each_entry(cur, &net->nfct_timeout_list, head) {
+ list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
struct sk_buff *skb2;
if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
const struct nlattr * const cda[],
struct netlink_ext_ack *extack)
{
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
struct ctnl_timeout *cur, *tmp;
int ret = -ENOENT;
char *name;
if (!cda[CTA_TIMEOUT_NAME]) {
- list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list,
+ list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list,
head)
ctnl_timeout_try_del(net, cur);
}
name = nla_data(cda[CTA_TIMEOUT_NAME]);
- list_for_each_entry(cur, &net->nfct_timeout_list, head) {
+ list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
continue;
static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
const char *name)
{
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
struct ctnl_timeout *timeout, *matching = NULL;
- list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
+ list_for_each_entry_rcu(timeout, &pernet->nfct_timeout_list, head) {
if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
continue;
static int __net_init cttimeout_net_init(struct net *net)
{
- INIT_LIST_HEAD(&net->nfct_timeout_list);
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
+
+ INIT_LIST_HEAD(&pernet->nfct_timeout_list);
return 0;
}
static void __net_exit cttimeout_net_exit(struct net *net)
{
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
struct ctnl_timeout *cur, *tmp;
nf_ct_unconfirmed_destroy(net);
nf_ct_untimeout(net, NULL);
- list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
+ list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) {
list_del_rcu(&cur->head);
if (refcount_dec_and_test(&cur->refcnt))
static struct pernet_operations cttimeout_ops = {
.init = cttimeout_net_init,
.exit = cttimeout_net_exit,
+ .id = &nfct_timeout_id,
+ .size = sizeof(struct nfct_timeout_pernet),
};
static int __init cttimeout_init(void)