aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig14
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/core.c3
-rw-r--r--net/netfilter/nf_conntrack_core.c33
-rw-r--r--net/netfilter/nf_conntrack_expect.c25
-rw-r--r--net/netfilter/nf_conntrack_netlink.c551
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c5
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c122
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c10
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c10
-rw-r--r--net/netfilter/nf_conntrack_standalone.c31
-rw-r--r--net/netfilter/nf_sockopt.c7
-rw-r--r--net/netfilter/nfnetlink.c141
-rw-r--r--net/netfilter/nfnetlink_log.c251
-rw-r--r--net/netfilter/nfnetlink_queue.c168
-rw-r--r--net/netfilter/x_tables.c17
-rw-r--r--net/netfilter/xt_CLASSIFY.c1
-rw-r--r--net/netfilter/xt_CONNMARK.c1
-rw-r--r--net/netfilter/xt_NOTRACK.c1
-rw-r--r--net/netfilter/xt_connbytes.c1
-rw-r--r--net/netfilter/xt_connmark.c1
-rw-r--r--net/netfilter/xt_dccp.c1
-rw-r--r--net/netfilter/xt_hashlimit.c11
-rw-r--r--net/netfilter/xt_sctp.c1
-rw-r--r--net/netfilter/xt_tcpmss.c1
-rw-r--r--net/netfilter/xt_time.c269
26 files changed, 938 insertions, 739 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 3599770a2473..d7a600a5720a 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -665,6 +665,20 @@ config NETFILTER_XT_MATCH_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_TIME
+ tristate '"time" match support'
+ depends on NETFILTER_XTABLES
+ ---help---
+ This option adds a "time" match, which allows you to match based on
+ the packet arrival time (at the machine which netfilter is running)
+ on) or departure time/date (for locally generated packets).
+
+ If you say Y here, try `iptables -m time --help` for
+ more information.
+
+ If you want to compile it as a module, say M here.
+ If unsure, say N.
+
config NETFILTER_XT_MATCH_U32
tristate '"u32" match support'
depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 0c054bf27973..93c58f973831 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 381a77cf0c9e..a523fa4136ed 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -19,6 +19,7 @@
#include <linux/inetdevice.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
+#include <net/net_namespace.h>
#include <net/sock.h>
#include "nf_internals.h"
@@ -293,7 +294,7 @@ void __init netfilter_init(void)
}
#ifdef CONFIG_PROC_FS
- proc_net_netfilter = proc_mkdir("netfilter", proc_net);
+ proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
if (!proc_net_netfilter)
panic("cannot create netfilter proc entry");
#endif
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0fe11889ce14..83c30b45d170 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -63,7 +63,6 @@ unsigned int nf_ct_log_invalid __read_mostly;
HLIST_HEAD(unconfirmed);
static int nf_conntrack_vmalloc __read_mostly;
static struct kmem_cache *nf_conntrack_cachep __read_mostly;
-static unsigned int nf_conntrack_next_id;
DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
@@ -287,7 +286,6 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
unsigned int hash,
unsigned int repl_hash)
{
- ct->id = ++nf_conntrack_next_id;
hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
&nf_conntrack_hash[hash]);
hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode,
@@ -827,44 +825,41 @@ EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
#include <linux/netfilter/nfnetlink_conntrack.h>
#include <linux/mutex.h>
-
/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
* in ip_conntrack_core, since we don't want the protocols to autoload
* or depend on ctnetlink */
-int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple)
{
- NFA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
+ NLA_PUT(skb, CTA_PROTO_SRC_PORT, sizeof(u_int16_t),
&tuple->src.u.tcp.port);
- NFA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
+ NLA_PUT(skb, CTA_PROTO_DST_PORT, sizeof(u_int16_t),
&tuple->dst.u.tcp.port);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
-EXPORT_SYMBOL_GPL(nf_ct_port_tuple_to_nfattr);
+EXPORT_SYMBOL_GPL(nf_ct_port_tuple_to_nlattr);
-static const size_t cta_min_proto[CTA_PROTO_MAX] = {
- [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t),
- [CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t)
+const struct nla_policy nf_ct_port_nla_policy[CTA_PROTO_MAX+1] = {
+ [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
+ [CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
};
+EXPORT_SYMBOL_GPL(nf_ct_port_nla_policy);
-int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
struct nf_conntrack_tuple *t)
{
- if (!tb[CTA_PROTO_SRC_PORT-1] || !tb[CTA_PROTO_DST_PORT-1])
- return -EINVAL;
-
- if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
+ if (!tb[CTA_PROTO_SRC_PORT] || !tb[CTA_PROTO_DST_PORT])
return -EINVAL;
- t->src.u.tcp.port = *(__be16 *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
- t->dst.u.tcp.port = *(__be16 *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
+ t->src.u.tcp.port = *(__be16 *)nla_data(tb[CTA_PROTO_SRC_PORT]);
+ t->dst.u.tcp.port = *(__be16 *)nla_data(tb[CTA_PROTO_DST_PORT]);
return 0;
}
-EXPORT_SYMBOL_GPL(nf_ct_port_nfattr_to_tuple);
+EXPORT_SYMBOL_GPL(nf_ct_port_nlattr_to_tuple);
#endif
/* Used by ipt_REJECT and ip6t_REJECT. */
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 3ac64e25f10c..175c8d1a1992 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -20,6 +20,7 @@
#include <linux/percpu.h>
#include <linux/kernel.h>
#include <linux/jhash.h>
+#include <net/net_namespace.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -40,7 +41,6 @@ static int nf_ct_expect_hash_rnd_initted __read_mostly;
static int nf_ct_expect_vmalloc;
static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
-static unsigned int nf_ct_expect_next_id;
/* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
@@ -301,7 +301,6 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
add_timer(&exp->timeout);
- exp->id = ++nf_ct_expect_next_id;
atomic_inc(&exp->use);
NF_CT_STAT_INC(expect_create);
}
@@ -473,22 +472,8 @@ static const struct seq_operations exp_seq_ops = {
static int exp_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- struct ct_expect_iter_state *st;
- int ret;
-
- st = kzalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
- if (!st)
- return -ENOMEM;
- ret = seq_open(file, &exp_seq_ops);
- if (ret)
- goto out_free;
- seq = file->private_data;
- seq->private = st;
- return ret;
-out_free:
- kfree(st);
- return ret;
+ return seq_open_private(file, &exp_seq_ops,
+ sizeof(struct ct_expect_iter_state));
}
static const struct file_operations exp_file_ops = {
@@ -505,7 +490,7 @@ static int __init exp_proc_init(void)
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
- proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops);
+ proc = proc_net_fops_create(&init_net, "nf_conntrack_expect", 0440, &exp_file_ops);
if (!proc)
return -ENOMEM;
#endif /* CONFIG_PROC_FS */
@@ -515,7 +500,7 @@ static int __init exp_proc_init(void)
static void exp_proc_remove(void)
{
#ifdef CONFIG_PROC_FS
- proc_net_remove("nf_conntrack_expect");
+ proc_net_remove(&init_net, "nf_conntrack_expect");
#endif /* CONFIG_PROC_FS */
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 2863e72b4091..9be1826e6cdd 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -4,7 +4,7 @@
* (C) 2001 by Jay Schulist <jschlst@samba.org>
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* Initial connection tracking via netlink development funded and
* generally made possible by Network Robots, Inc. (www.networkrobots.com)
@@ -54,18 +54,21 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb,
struct nf_conntrack_l4proto *l4proto)
{
int ret = 0;
- struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
+ struct nlattr *nest_parms;
- NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_PROTO | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
+ NLA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
- if (likely(l4proto->tuple_to_nfattr))
- ret = l4proto->tuple_to_nfattr(skb, tuple);
+ if (likely(l4proto->tuple_to_nlattr))
+ ret = l4proto->tuple_to_nlattr(skb, tuple);
- NFA_NEST_END(skb, nest_parms);
+ nla_nest_end(skb, nest_parms);
return ret;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -75,16 +78,20 @@ ctnetlink_dump_tuples_ip(struct sk_buff *skb,
struct nf_conntrack_l3proto *l3proto)
{
int ret = 0;
- struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+ struct nlattr *nest_parms;
- if (likely(l3proto->tuple_to_nfattr))
- ret = l3proto->tuple_to_nfattr(skb, tuple);
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_IP | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
- NFA_NEST_END(skb, nest_parms);
+ if (likely(l3proto->tuple_to_nlattr))
+ ret = l3proto->tuple_to_nlattr(skb, tuple);
+
+ nla_nest_end(skb, nest_parms);
return ret;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -114,10 +121,10 @@ static inline int
ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
{
__be32 status = htonl((u_int32_t) ct->status);
- NFA_PUT(skb, CTA_STATUS, sizeof(status), &status);
+ NLA_PUT(skb, CTA_STATUS, sizeof(status), &status);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -132,10 +139,10 @@ ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct)
else
timeout = htonl(timeout_l / HZ);
- NFA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
+ NLA_PUT(skb, CTA_TIMEOUT, sizeof(timeout), &timeout);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -143,25 +150,27 @@ static inline int
ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
struct nf_conntrack_l4proto *l4proto = nf_ct_l4proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
- struct nfattr *nest_proto;
+ struct nlattr *nest_proto;
int ret;
- if (!l4proto->to_nfattr) {
+ if (!l4proto->to_nlattr) {
nf_ct_l4proto_put(l4proto);
return 0;
}
- nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
+ nest_proto = nla_nest_start(skb, CTA_PROTOINFO | NLA_F_NESTED);
+ if (!nest_proto)
+ goto nla_put_failure;
- ret = l4proto->to_nfattr(skb, nest_proto, ct);
+ ret = l4proto->to_nlattr(skb, nest_proto, ct);
nf_ct_l4proto_put(l4proto);
- NFA_NEST_END(skb, nest_proto);
+ nla_nest_end(skb, nest_proto);
return ret;
-nfattr_failure:
+nla_put_failure:
nf_ct_l4proto_put(l4proto);
return -1;
}
@@ -169,7 +178,7 @@ nfattr_failure:
static inline int
ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
- struct nfattr *nest_helper;
+ struct nlattr *nest_helper;
const struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_helper *helper;
@@ -181,18 +190,20 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
if (!helper)
goto out;
- nest_helper = NFA_NEST(skb, CTA_HELP);
- NFA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
+ nest_helper = nla_nest_start(skb, CTA_HELP | NLA_F_NESTED);
+ if (!nest_helper)
+ goto nla_put_failure;
+ NLA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
- if (helper->to_nfattr)
- helper->to_nfattr(skb, ct);
+ if (helper->to_nlattr)
+ helper->to_nlattr(skb, ct);
- NFA_NEST_END(skb, nest_helper);
+ nla_nest_end(skb, nest_helper);
out:
rcu_read_unlock();
return 0;
-nfattr_failure:
+nla_put_failure:
rcu_read_unlock();
return -1;
}
@@ -203,20 +214,24 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
enum ip_conntrack_dir dir)
{
enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
- struct nfattr *nest_count = NFA_NEST(skb, type);
+ struct nlattr *nest_count;
__be32 tmp;
+ nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
+ if (!nest_count)
+ goto nla_put_failure;
+
tmp = htonl(ct->counters[dir].packets);
- NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
+ NLA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
tmp = htonl(ct->counters[dir].bytes);
- NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
+ NLA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_t), &tmp);
- NFA_NEST_END(skb, nest_count);
+ nla_nest_end(skb, nest_count);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
#else
@@ -229,10 +244,10 @@ ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
{
__be32 mark = htonl(ct->mark);
- NFA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
+ NLA_PUT(skb, CTA_MARK, sizeof(u_int32_t), &mark);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
#else
@@ -242,11 +257,11 @@ nfattr_failure:
static inline int
ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
{
- __be32 id = htonl(ct->id);
- NFA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
+ __be32 id = htonl((unsigned long)ct);
+ NLA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -255,10 +270,10 @@ ctnetlink_dump_use(struct sk_buff *skb, const struct nf_conn *ct)
{
__be32 use = htonl(atomic_read(&ct->ct_general.use));
- NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
+ NLA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -271,7 +286,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
- struct nfattr *nest_parms;
+ struct nlattr *nest_parms;
unsigned char *b = skb_tail_pointer(skb);
event |= NFNL_SUBSYS_CTNETLINK << 8;
@@ -284,15 +299,19 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = 0;
- nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
- goto nfattr_failure;
- NFA_NEST_END(skb, nest_parms);
+ goto nla_put_failure;
+ nla_nest_end(skb, nest_parms);
- nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
- goto nfattr_failure;
- NFA_NEST_END(skb, nest_parms);
+ goto nla_put_failure;
+ nla_nest_end(skb, nest_parms);
if (ctnetlink_dump_status(skb, ct) < 0 ||
ctnetlink_dump_timeout(skb, ct) < 0 ||
@@ -303,13 +322,13 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
ctnetlink_dump_mark(skb, ct) < 0 ||
ctnetlink_dump_id(skb, ct) < 0 ||
ctnetlink_dump_use(skb, ct) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
return skb->len;
nlmsg_failure:
-nfattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -320,7 +339,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
- struct nfattr *nest_parms;
+ struct nlattr *nest_parms;
struct nf_conn *ct = (struct nf_conn *)ptr;
struct sk_buff *skb;
unsigned int type;
@@ -362,45 +381,49 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = 0;
- nest_parms = NFA_NEST(skb, CTA_TUPLE_ORIG);
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_ORIGINAL)) < 0)
- goto nfattr_failure;
- NFA_NEST_END(skb, nest_parms);
+ goto nla_put_failure;
+ nla_nest_end(skb, nest_parms);
- nest_parms = NFA_NEST(skb, CTA_TUPLE_REPLY);
+ nest_parms = nla_nest_start(skb, CTA_TUPLE_REPLY | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
- goto nfattr_failure;
- NFA_NEST_END(skb, nest_parms);
+ goto nla_put_failure;
+ nla_nest_end(skb, nest_parms);
if (events & IPCT_DESTROY) {
if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
} else {
if (ctnetlink_dump_status(skb, ct) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
if (ctnetlink_dump_timeout(skb, ct) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
if (events & IPCT_PROTOINFO
&& ctnetlink_dump_protoinfo(skb, ct) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
if ((events & IPCT_HELPER || nfct_help(ct))
&& ctnetlink_dump_helpinfo(skb, ct) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
#ifdef CONFIG_NF_CONNTRACK_MARK
if ((events & IPCT_MARK || ct->mark)
&& ctnetlink_dump_mark(skb, ct) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
#endif
if (events & IPCT_COUNTER_FILLING &&
(ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
- goto nfattr_failure;
+ goto nla_put_failure;
}
nlh->nlmsg_len = skb->tail - b;
@@ -408,7 +431,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
return NOTIFY_DONE;
nlmsg_failure:
-nfattr_failure:
+nla_put_failure:
kfree_skb(skb);
return NOTIFY_DONE;
}
@@ -479,49 +502,56 @@ out:
}
static inline int
-ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple)
+ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple)
{
- struct nfattr *tb[CTA_IP_MAX];
+ struct nlattr *tb[CTA_IP_MAX+1];
struct nf_conntrack_l3proto *l3proto;
int ret = 0;
- nfattr_parse_nested(tb, CTA_IP_MAX, attr);
+ nla_parse_nested(tb, CTA_IP_MAX, attr, NULL);
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
- if (likely(l3proto->nfattr_to_tuple))
- ret = l3proto->nfattr_to_tuple(tb, tuple);
+ if (likely(l3proto->nlattr_to_tuple)) {
+ ret = nla_validate_nested(attr, CTA_IP_MAX,
+ l3proto->nla_policy);
+ if (ret == 0)
+ ret = l3proto->nlattr_to_tuple(tb, tuple);
+ }
nf_ct_l3proto_put(l3proto);
return ret;
}
-static const size_t cta_min_proto[CTA_PROTO_MAX] = {
- [CTA_PROTO_NUM-1] = sizeof(u_int8_t),
+static const struct nla_policy proto_nla_policy[CTA_PROTO_MAX+1] = {
+ [CTA_PROTO_NUM] = { .type = NLA_U8 },
};
static inline int
-ctnetlink_parse_tuple_proto(struct nfattr *attr,
+ctnetlink_parse_tuple_proto(struct nlattr *attr,
struct nf_conntrack_tuple *tuple)
{
- struct nfattr *tb[CTA_PROTO_MAX];
+ struct nlattr *tb[CTA_PROTO_MAX+1];
struct nf_conntrack_l4proto *l4proto;
int ret = 0;
- nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
-
- if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
- return -EINVAL;
+ ret = nla_parse_nested(tb, CTA_PROTO_MAX, attr, proto_nla_policy);
+ if (ret < 0)
+ return ret;
- if (!tb[CTA_PROTO_NUM-1])
+ if (!tb[CTA_PROTO_NUM])
return -EINVAL;
- tuple->dst.protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
+ tuple->dst.protonum = *(u_int8_t *)nla_data(tb[CTA_PROTO_NUM]);
l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
- if (likely(l4proto->nfattr_to_tuple))
- ret = l4proto->nfattr_to_tuple(tb, tuple);
+ if (likely(l4proto->nlattr_to_tuple)) {
+ ret = nla_validate_nested(attr, CTA_PROTO_MAX,
+ l4proto->nla_policy);
+ if (ret == 0)
+ ret = l4proto->nlattr_to_tuple(tb, tuple);
+ }
nf_ct_l4proto_put(l4proto);
@@ -529,29 +559,29 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
}
static inline int
-ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
+ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
enum ctattr_tuple type, u_int8_t l3num)
{
- struct nfattr *tb[CTA_TUPLE_MAX];
+ struct nlattr *tb[CTA_TUPLE_MAX+1];
int err;
memset(tuple, 0, sizeof(*tuple));
- nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
+ nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], NULL);
- if (!tb[CTA_TUPLE_IP-1])
+ if (!tb[CTA_TUPLE_IP])
return -EINVAL;
tuple->src.l3num = l3num;
- err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP-1], tuple);
+ err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple);
if (err < 0)
return err;
- if (!tb[CTA_TUPLE_PROTO-1])
+ if (!tb[CTA_TUPLE_PROTO])
return -EINVAL;
- err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO-1], tuple);
+ err = ctnetlink_parse_tuple_proto(tb[CTA_TUPLE_PROTO], tuple);
if (err < 0)
return err;
@@ -565,32 +595,32 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
}
#ifdef CONFIG_NF_NAT_NEEDED
-static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = {
- [CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t),
- [CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t),
+static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
+ [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
+ [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
};
-static int nfnetlink_parse_nat_proto(struct nfattr *attr,
+static int nfnetlink_parse_nat_proto(struct nlattr *attr,
const struct nf_conn *ct,
struct nf_nat_range *range)
{
- struct nfattr *tb[CTA_PROTONAT_MAX];
+ struct nlattr *tb[CTA_PROTONAT_MAX+1];
struct nf_nat_protocol *npt;
+ int err;
- nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
-
- if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
- return -EINVAL;
+ err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
+ if (err < 0)
+ return err;
npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
- if (!npt->nfattr_to_range) {
+ if (!npt->nlattr_to_range) {
nf_nat_proto_put(npt);
return 0;
}
- /* nfattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
- if (npt->nfattr_to_range(tb, range) > 0)
+ /* nlattr_to_range returns 1 if it parsed, 0 if not, neg. on error */
+ if (npt->nlattr_to_range(tb, range) > 0)
range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
nf_nat_proto_put(npt);
@@ -598,40 +628,39 @@ static int nfnetlink_parse_nat_proto(struct nfattr *attr,
return 0;
}
-static const size_t cta_min_nat[CTA_NAT_MAX] = {
- [CTA_NAT_MINIP-1] = sizeof(u_int32_t),
- [CTA_NAT_MAXIP-1] = sizeof(u_int32_t),
+static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
+ [CTA_NAT_MINIP] = { .type = NLA_U32 },
+ [CTA_NAT_MAXIP] = { .type = NLA_U32 },
};
static inline int
-nfnetlink_parse_nat(struct nfattr *nat,
+nfnetlink_parse_nat(struct nlattr *nat,
const struct nf_conn *ct, struct nf_nat_range *range)
{
- struct nfattr *tb[CTA_NAT_MAX];
+ struct nlattr *tb[CTA_NAT_MAX+1];
int err;
memset(range, 0, sizeof(*range));
- nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
-
- if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
- return -EINVAL;
+ err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy);
+ if (err < 0)
+ return err;
- if (tb[CTA_NAT_MINIP-1])
- range->min_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
+ if (tb[CTA_NAT_MINIP])
+ range->min_ip = *(__be32 *)nla_data(tb[CTA_NAT_MINIP]);
- if (!tb[CTA_NAT_MAXIP-1])
+ if (!tb[CTA_NAT_MAXIP])
range->max_ip = range->min_ip;
else
- range->max_ip = *(__be32 *)NFA_DATA(tb[CTA_NAT_MAXIP-1]);
+ range->max_ip = *(__be32 *)nla_data(tb[CTA_NAT_MAXIP]);
if (range->min_ip)
range->flags |= IP_NAT_RANGE_MAP_IPS;
- if (!tb[CTA_NAT_PROTO-1])
+ if (!tb[CTA_NAT_PROTO])
return 0;
- err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
+ err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
if (err < 0)
return err;
@@ -640,31 +669,31 @@ nfnetlink_parse_nat(struct nfattr *nat,
#endif
static inline int
-ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
+ctnetlink_parse_help(struct nlattr *attr, char **helper_name)
{
- struct nfattr *tb[CTA_HELP_MAX];
+ struct nlattr *tb[CTA_HELP_MAX+1];
- nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
+ nla_parse_nested(tb, CTA_HELP_MAX, attr, NULL);
- if (!tb[CTA_HELP_NAME-1])
+ if (!tb[CTA_HELP_NAME])
return -EINVAL;
- *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]);
+ *helper_name = nla_data(tb[CTA_HELP_NAME]);
return 0;
}
-static const size_t cta_min[CTA_MAX] = {
- [CTA_STATUS-1] = sizeof(u_int32_t),
- [CTA_TIMEOUT-1] = sizeof(u_int32_t),
- [CTA_MARK-1] = sizeof(u_int32_t),
- [CTA_USE-1] = sizeof(u_int32_t),
- [CTA_ID-1] = sizeof(u_int32_t)
+static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
+ [CTA_STATUS] = { .type = NLA_U32 },
+ [CTA_TIMEOUT] = { .type = NLA_U32 },
+ [CTA_MARK] = { .type = NLA_U32 },
+ [CTA_USE] = { .type = NLA_U32 },
+ [CTA_ID] = { .type = NLA_U32 },
};
static int
ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *cda[])
+ struct nlmsghdr *nlh, struct nlattr *cda[])
{
struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_tuple tuple;
@@ -673,12 +702,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- if (nfattr_bad_size(cda, CTA_MAX, cta_min))
- return -EINVAL;
-
- if (cda[CTA_TUPLE_ORIG-1])
+ if (cda[CTA_TUPLE_ORIG])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
- else if (cda[CTA_TUPLE_REPLY-1])
+ else if (cda[CTA_TUPLE_REPLY])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else {
/* Flush the whole table */
@@ -695,9 +721,9 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
ct = nf_ct_tuplehash_to_ctrack(h);
- if (cda[CTA_ID-1]) {
- u_int32_t id = ntohl(*(__be32 *)NFA_DATA(cda[CTA_ID-1]));
- if (ct->id != id) {
+ if (cda[CTA_ID]) {
+ u_int32_t id = ntohl(*(__be32 *)nla_data(cda[CTA_ID]));
+ if (id != (u32)(unsigned long)ct) {
nf_ct_put(ct);
return -ENOENT;
}
@@ -712,7 +738,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
static int
ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *cda[])
+ struct nlmsghdr *nlh, struct nlattr *cda[])
{
struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_tuple tuple;
@@ -731,12 +757,9 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
ctnetlink_done);
}
- if (nfattr_bad_size(cda, CTA_MAX, cta_min))
- return -EINVAL;
-
- if (cda[CTA_TUPLE_ORIG-1])
+ if (cda[CTA_TUPLE_ORIG])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
- else if (cda[CTA_TUPLE_REPLY-1])
+ else if (cda[CTA_TUPLE_REPLY])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
else
return -EINVAL;
@@ -776,10 +799,10 @@ out:
}
static inline int
-ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
+ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
{
unsigned long d;
- unsigned int status = ntohl(*(__be32 *)NFA_DATA(cda[CTA_STATUS-1]));
+ unsigned int status = ntohl(*(__be32 *)nla_data(cda[CTA_STATUS]));
d = ct->status ^ status;
if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
@@ -795,14 +818,14 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
/* ASSURED bit can only be set */
return -EINVAL;
- if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
+ if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
#ifndef CONFIG_NF_NAT_NEEDED
return -EINVAL;
#else
struct nf_nat_range range;
- if (cda[CTA_NAT_DST-1]) {
- if (nfnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+ if (cda[CTA_NAT_DST]) {
+ if (nfnetlink_parse_nat(cda[CTA_NAT_DST], ct,
&range) < 0)
return -EINVAL;
if (nf_nat_initialized(ct,
@@ -810,8 +833,8 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
return -EEXIST;
nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
}
- if (cda[CTA_NAT_SRC-1]) {
- if (nfnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+ if (cda[CTA_NAT_SRC]) {
+ if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct,
&range) < 0)
return -EINVAL;
if (nf_nat_initialized(ct,
@@ -831,7 +854,7 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
static inline int
-ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
+ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
{
struct nf_conntrack_helper *helper;
struct nf_conn_help *help = nfct_help(ct);
@@ -842,7 +865,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
if (ct->master)
return -EINVAL;
- err = ctnetlink_parse_help(cda[CTA_HELP-1], &helpname);
+ err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
if (err < 0)
return err;
@@ -879,9 +902,9 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
}
static inline int
-ctnetlink_change_timeout(struct nf_conn *ct, struct nfattr *cda[])
+ctnetlink_change_timeout(struct nf_conn *ct, struct nlattr *cda[])
{
- u_int32_t timeout = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+ u_int32_t timeout = ntohl(*(__be32 *)nla_data(cda[CTA_TIMEOUT]));
if (!del_timer(&ct->timeout))
return -ETIME;
@@ -893,66 +916,67 @@ ctnetlink_change_timeout(struct nf_conn *ct, struct nfattr *cda[])
}
static inline int
-ctnetlink_change_protoinfo(struct nf_conn *ct, struct nfattr *cda[])
+ctnetlink_change_protoinfo(struct nf_conn *ct, struct nlattr *cda[])
{
- struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
+ struct nlattr *tb[CTA_PROTOINFO_MAX+1], *attr = cda[CTA_PROTOINFO];
struct nf_conntrack_l4proto *l4proto;
u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
int err = 0;
- nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
+ nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL);
l4proto = nf_ct_l4proto_find_get(l3num, npt);
- if (l4proto->from_nfattr)
- err = l4proto->from_nfattr(tb, ct);
+ if (l4proto->from_nlattr)
+ err = l4proto->from_nlattr(tb, ct);
nf_ct_l4proto_put(l4proto);
return err;
}
static int
-ctnetlink_change_conntrack(struct nf_conn *ct, struct nfattr *cda[])
+ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
{
int err;
- if (cda[CTA_HELP-1]) {
+ if (cda[CTA_HELP]) {
err = ctnetlink_change_helper(ct, cda);
if (err < 0)
return err;
}
- if (cda[CTA_TIMEOUT-1]) {
+ if (cda[CTA_TIMEOUT]) {
err = ctnetlink_change_timeout(ct, cda);
if (err < 0)
return err;
}
- if (cda[CTA_STATUS-1]) {
+ if (cda[CTA_STATUS]) {
err = ctnetlink_change_status(ct, cda);
if (err < 0)
return err;
}
- if (cda[CTA_PROTOINFO-1]) {
+ if (cda[CTA_PROTOINFO]) {
err = ctnetlink_change_protoinfo(ct, cda);
if (err < 0)
return err;
}
#if defined(CONFIG_NF_CONNTRACK_MARK)
- if (cda[CTA_MARK-1])
- ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
+ if (cda[CTA_MARK])
+ ct->mark = ntohl(*(__be32 *)nla_data(cda[CTA_MARK]));
#endif
return 0;
}
static int
-ctnetlink_create_conntrack(struct nfattr *cda[],
+ctnetlink_create_conntrack(struct nlattr *cda[],
struct nf_conntrack_tuple *otuple,
- struct nf_conntrack_tuple *rtuple)
+ struct nf_conntrack_tuple *rtuple,
+ struct nf_conn *master_ct)
{
struct nf_conn *ct;
int err = -EINVAL;
@@ -963,28 +987,28 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
if (ct == NULL || IS_ERR(ct))
return -ENOMEM;
- if (!cda[CTA_TIMEOUT-1])
+ if (!cda[CTA_TIMEOUT])
goto err;
- ct->timeout.expires = ntohl(*(__be32 *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+ ct->timeout.expires = ntohl(*(__be32 *)nla_data(cda[CTA_TIMEOUT]));
ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
ct->status |= IPS_CONFIRMED;
- if (cda[CTA_STATUS-1]) {
+ if (cda[CTA_STATUS]) {
err = ctnetlink_change_status(ct, cda);
if (err < 0)
goto err;
}
- if (cda[CTA_PROTOINFO-1]) {
+ if (cda[CTA_PROTOINFO]) {
err = ctnetlink_change_protoinfo(ct, cda);
if (err < 0)
goto err;
}
#if defined(CONFIG_NF_CONNTRACK_MARK)
- if (cda[CTA_MARK-1])
- ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
+ if (cda[CTA_MARK])
+ ct->mark = ntohl(*(__be32 *)nla_data(cda[CTA_MARK]));
#endif
helper = nf_ct_helper_find_get(rtuple);
@@ -999,6 +1023,10 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
rcu_assign_pointer(help->helper, helper);
}
+ /* setup master conntrack: this is a confirmed expectation */
+ if (master_ct)
+ ct->master = master_ct;
+
add_timer(&ct->timeout);
nf_conntrack_hash_insert(ct);
@@ -1014,7 +1042,7 @@ err:
static int
ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *cda[])
+ struct nlmsghdr *nlh, struct nlattr *cda[])
{
struct nf_conntrack_tuple otuple, rtuple;
struct nf_conntrack_tuple_hash *h = NULL;
@@ -1022,32 +1050,56 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- if (nfattr_bad_size(cda, CTA_MAX, cta_min))
- return -EINVAL;
-
- if (cda[CTA_TUPLE_ORIG-1]) {
+ if (cda[CTA_TUPLE_ORIG]) {
err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
if (err < 0)
return err;
}
- if (cda[CTA_TUPLE_REPLY-1]) {
+ if (cda[CTA_TUPLE_REPLY]) {
err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3);
if (err < 0)
return err;
}
write_lock_bh(&nf_conntrack_lock);
- if (cda[CTA_TUPLE_ORIG-1])
+ if (cda[CTA_TUPLE_ORIG])
h = __nf_conntrack_find(&otuple, NULL);
- else if (cda[CTA_TUPLE_REPLY-1])
+ else if (cda[CTA_TUPLE_REPLY])
h = __nf_conntrack_find(&rtuple, NULL);
if (h == NULL) {
+ struct nf_conntrack_tuple master;
+ struct nf_conntrack_tuple_hash *master_h = NULL;
+ struct nf_conn *master_ct = NULL;
+
+ if (cda[CTA_TUPLE_MASTER]) {
+ err = ctnetlink_parse_tuple(cda,
+ &master,
+ CTA_TUPLE_MASTER,
+ u3);
+ if (err < 0)
+ return err;
+
+ master_h = __nf_conntrack_find(&master, NULL);
+ if (master_h == NULL) {
+ err = -ENOENT;
+ goto out_unlock;
+ }
+ master_ct = nf_ct_tuplehash_to_ctrack(master_h);
+ atomic_inc(&master_ct->ct_general.use);
+ }
+
write_unlock_bh(&nf_conntrack_lock);
err = -ENOENT;
if (nlh->nlmsg_flags & NLM_F_CREATE)
- err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
+ err = ctnetlink_create_conntrack(cda,
+ &otuple,
+ &rtuple,
+ master_ct);
+ if (err < 0 && master_ct)
+ nf_ct_put(master_ct);
+
return err;
}
/* implicit 'else' */
@@ -1057,7 +1109,12 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
err = -EEXIST;
if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
/* we only allow nat config for new conntracks */
- if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
+ if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
+ err = -EINVAL;
+ goto out_unlock;
+ }
+ /* can't link an existing conntrack to a master */
+ if (cda[CTA_TUPLE_MASTER]) {
err = -EINVAL;
goto out_unlock;
}
@@ -1079,16 +1136,18 @@ ctnetlink_exp_dump_tuple(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple,
enum ctattr_expect type)
{
- struct nfattr *nest_parms = NFA_NEST(skb, type);
+ struct nlattr *nest_parms;
+ nest_parms = nla_nest_start(skb, type | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
if (ctnetlink_dump_tuples(skb, tuple) < 0)
- goto nfattr_failure;
-
- NFA_NEST_END(skb, nest_parms);
+ goto nla_put_failure;
+ nla_nest_end(skb, nest_parms);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -1101,32 +1160,34 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb,
struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto;
struct nf_conntrack_tuple m;
- struct nfattr *nest_parms;
+ struct nlattr *nest_parms;
memset(&m, 0xFF, sizeof(m));
m.src.u.all = mask->src.u.all;
memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
- nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+ nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
nf_ct_l3proto_put(l3proto);
if (unlikely(ret < 0))
- goto nfattr_failure;
+ goto nla_put_failure;
l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
nf_ct_l4proto_put(l4proto);
if (unlikely(ret < 0))
- goto nfattr_failure;
+ goto nla_put_failure;
- NFA_NEST_END(skb, nest_parms);
+ nla_nest_end(skb, nest_parms);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -1136,23 +1197,23 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
{
struct nf_conn *master = exp->master;
__be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
- __be32 id = htonl(exp->id);
+ __be32 id = htonl((unsigned long)exp);
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
if (ctnetlink_exp_dump_tuple(skb,
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
CTA_EXPECT_MASTER) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
- NFA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
- NFA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
+ NLA_PUT(skb, CTA_EXPECT_TIMEOUT, sizeof(timeout), &timeout);
+ NLA_PUT(skb, CTA_EXPECT_ID, sizeof(u_int32_t), &id);
return 0;
-nfattr_failure:
+nla_put_failure:
return -1;
}
@@ -1176,13 +1237,13 @@ ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
nfmsg->res_id = 0;
if (ctnetlink_exp_dump_expect(skb, exp) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
nlh->nlmsg_len = skb_tail_pointer(skb) - b;
return skb->len;
nlmsg_failure:
-nfattr_failure:
+nla_put_failure:
nlmsg_trim(skb, b);
return -1;
}
@@ -1224,14 +1285,14 @@ static int ctnetlink_expect_event(struct notifier_block *this,
nfmsg->res_id = 0;
if (ctnetlink_exp_dump_expect(skb, exp) < 0)
- goto nfattr_failure;
+ goto nla_put_failure;
nlh->nlmsg_len = skb->tail - b;
nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
return NOTIFY_DONE;
nlmsg_failure:
-nfattr_failure:
+nla_put_failure:
kfree_skb(skb);
return NOTIFY_DONE;
}
@@ -1286,14 +1347,14 @@ out:
return skb->len;
}
-static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
- [CTA_EXPECT_TIMEOUT-1] = sizeof(u_int32_t),
- [CTA_EXPECT_ID-1] = sizeof(u_int32_t)
+static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
+ [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
+ [CTA_EXPECT_ID] = { .type = NLA_U32 },
};
static int
ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *cda[])
+ struct nlmsghdr *nlh, struct nlattr *cda[])
{
struct nf_conntrack_tuple tuple;
struct nf_conntrack_expect *exp;
@@ -1302,16 +1363,13 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
- return -EINVAL;
-
if (nlh->nlmsg_flags & NLM_F_DUMP) {
return netlink_dump_start(ctnl, skb, nlh,
ctnetlink_exp_dump_table,
ctnetlink_exp_done);
}
- if (cda[CTA_EXPECT_MASTER-1])
+ if (cda[CTA_EXPECT_MASTER])
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
else
return -EINVAL;
@@ -1323,9 +1381,9 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (!exp)
return -ENOENT;
- if (cda[CTA_EXPECT_ID-1]) {
- __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
- if (exp->id != ntohl(id)) {
+ if (cda[CTA_EXPECT_ID]) {
+ __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
+ if (ntohl(id) != (u32)(unsigned long)exp) {
nf_ct_expect_put(exp);
return -ENOENT;
}
@@ -1355,7 +1413,7 @@ out:
static int
ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *cda[])
+ struct nlmsghdr *nlh, struct nlattr *cda[])
{
struct nf_conntrack_expect *exp;
struct nf_conntrack_tuple tuple;
@@ -1366,10 +1424,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
unsigned int i;
int err;
- if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
- return -EINVAL;
-
- if (cda[CTA_EXPECT_TUPLE-1]) {
+ if (cda[CTA_EXPECT_TUPLE]) {
/* delete a single expect by tuple */
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
if (err < 0)
@@ -1380,9 +1435,9 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
if (!exp)
return -ENOENT;
- if (cda[CTA_EXPECT_ID-1]) {
- __be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
- if (exp->id != ntohl(id)) {
+ if (cda[CTA_EXPECT_ID]) {
+ __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
+ if (ntohl(id) != (u32)(unsigned long)exp) {
nf_ct_expect_put(exp);
return -ENOENT;
}
@@ -1393,8 +1448,8 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
/* have to put what we 'get' above.
* after this line usage count == 0 */
nf_ct_expect_put(exp);
- } else if (cda[CTA_EXPECT_HELP_NAME-1]) {
- char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
+ } else if (cda[CTA_EXPECT_HELP_NAME]) {
+ char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);
struct nf_conn_help *m_help;
/* delete all expectations for this helper */
@@ -1436,13 +1491,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return 0;
}
static int
-ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nfattr *cda[])
+ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nlattr *cda[])
{
return -EOPNOTSUPP;
}
static int
-ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
+ctnetlink_create_expect(struct nlattr *cda[], u_int8_t u3)
{
struct nf_conntrack_tuple tuple, mask, master_tuple;
struct nf_conntrack_tuple_hash *h = NULL;
@@ -1499,7 +1554,7 @@ out:
static int
ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *cda[])
+ struct nlmsghdr *nlh, struct nlattr *cda[])
{
struct nf_conntrack_tuple tuple;
struct nf_conntrack_expect *exp;
@@ -1507,12 +1562,9 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
u_int8_t u3 = nfmsg->nfgen_family;
int err = 0;
- if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
- return -EINVAL;
-
- if (!cda[CTA_EXPECT_TUPLE-1]
- || !cda[CTA_EXPECT_MASK-1]
- || !cda[CTA_EXPECT_MASTER-1])
+ if (!cda[CTA_EXPECT_TUPLE]
+ || !cda[CTA_EXPECT_MASK]
+ || !cda[CTA_EXPECT_MASTER])
return -EINVAL;
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
@@ -1548,34 +1600,41 @@ static struct notifier_block ctnl_notifier_exp = {
};
#endif
-static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
+static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
[IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack,
- .attr_count = CTA_MAX, },
+ .attr_count = CTA_MAX,
+ .policy = ct_nla_policy },
[IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack,
- .attr_count = CTA_MAX, },
+ .attr_count = CTA_MAX,
+ .policy = ct_nla_policy },
[IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack,
- .attr_count = CTA_MAX, },
+ .attr_count = CTA_MAX,
+ .policy = ct_nla_policy },
[IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack,
- .attr_count = CTA_MAX, },
+ .attr_count = CTA_MAX,
+ .policy = ct_nla_policy },
};
-static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
+static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
[IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect,
- .attr_count = CTA_EXPECT_MAX, },
+ .attr_count = CTA_EXPECT_MAX,
+ .policy = exp_nla_policy },
[IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect,
- .attr_count = CTA_EXPECT_MAX, },
+ .attr_count = CTA_EXPECT_MAX,
+ .policy = exp_nla_policy },
[IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect,
- .attr_count = CTA_EXPECT_MAX, },
+ .attr_count = CTA_EXPECT_MAX,
+ .policy = exp_nla_policy },
};
-static struct nfnetlink_subsystem ctnl_subsys = {
+static const struct nfnetlink_subsystem ctnl_subsys = {
.name = "conntrack",
.subsys_id = NFNL_SUBSYS_CTNETLINK,
.cb_count = IPCTNL_MSG_MAX,
.cb = ctnl_cb,
};
-static struct nfnetlink_subsystem ctnl_exp_subsys = {
+static const struct nfnetlink_subsystem ctnl_exp_subsys = {
.name = "conntrack_expect",
.subsys_id = NFNL_SUBSYS_CTNETLINK_EXP,
.cb_count = IPCTNL_MSG_EXP_MAX,
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index bdbead8a7a83..4a185f6aa65a 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -274,8 +274,9 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
.destroy = gre_destroy,
.me = THIS_MODULE,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
};
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index eb3fe7401466..c7075345971b 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -831,6 +831,20 @@ static int tcp_packet(struct nf_conn *conntrack,
tuple = &conntrack->tuplehash[dir].tuple;
switch (new_state) {
+ case TCP_CONNTRACK_SYN_SENT:
+ if (old_state < TCP_CONNTRACK_TIME_WAIT)
+ break;
+ if (conntrack->proto.tcp.seen[!dir].flags &
+ IP_CT_TCP_FLAG_CLOSE_INIT) {
+ /* Attempt to reopen a closed connection.
+ * Delete this connection and look up again. */
+ write_unlock_bh(&tcp_lock);
+ if (del_timer(&conntrack->timeout))
+ conntrack->timeout.function((unsigned long)
+ conntrack);
+ return -NF_REPEAT;
+ }
+ /* Fall through */
case TCP_CONNTRACK_IGNORE:
/* Ignored packets:
*
@@ -879,27 +893,6 @@ static int tcp_packet(struct nf_conn *conntrack,
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: invalid state ");
return -NF_ACCEPT;
- case TCP_CONNTRACK_SYN_SENT:
- if (old_state < TCP_CONNTRACK_TIME_WAIT)
- break;
- if ((conntrack->proto.tcp.seen[dir].flags &
- IP_CT_TCP_FLAG_CLOSE_INIT)
- || after(ntohl(th->seq),
- conntrack->proto.tcp.seen[dir].td_end)) {
- /* Attempt to reopen a closed connection.
- * Delete this connection and look up again. */
- write_unlock_bh(&tcp_lock);
- if (del_timer(&conntrack->timeout))
- conntrack->timeout.function((unsigned long)
- conntrack);
- return -NF_REPEAT;
- } else {
- write_unlock_bh(&tcp_lock);
- if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(pf, 0, skb, NULL, NULL,
- NULL, "nf_ct_tcp: invalid SYN");
- return -NF_ACCEPT;
- }
case TCP_CONNTRACK_CLOSE:
if (index == TCP_RST_SET
&& ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
@@ -1067,93 +1060,96 @@ static int tcp_new(struct nf_conn *conntrack,
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
-static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
+static int tcp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
const struct nf_conn *ct)
{
- struct nfattr *nest_parms;
+ struct nlattr *nest_parms;
struct nf_ct_tcp_flags tmp = {};
read_lock_bh(&tcp_lock);
- nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
- NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
+ nest_parms = nla_nest_start(skb, CTA_PROTOINFO_TCP | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
+
+ NLA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
&ct->proto.tcp.state);
- NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, sizeof(u_int8_t),
+ NLA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, sizeof(u_int8_t),
&ct->proto.tcp.seen[0].td_scale);
- NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, sizeof(u_int8_t),
+ NLA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, sizeof(u_int8_t),
&ct->proto.tcp.seen[1].td_scale);
tmp.flags = ct->proto.tcp.seen[0].flags;
- NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
+ NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
sizeof(struct nf_ct_tcp_flags), &tmp);
tmp.flags = ct->proto.tcp.seen[1].flags;
- NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
+ NLA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
sizeof(struct nf_ct_tcp_flags), &tmp);
read_unlock_bh(&tcp_lock);
- NFA_NEST_END(skb, nest_parms);
+ nla_nest_end(skb, nest_parms);
return 0;
-nfattr_failure:
+nla_put_failure:
read_unlock_bh(&tcp_lock);
return -1;
}
-static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
- [CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
- [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] = sizeof(u_int8_t),
- [CTA_PROTOINFO_TCP_WSCALE_REPLY-1] = sizeof(u_int8_t),
- [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1] = sizeof(struct nf_ct_tcp_flags),
- [CTA_PROTOINFO_TCP_FLAGS_REPLY-1] = sizeof(struct nf_ct_tcp_flags)
+static const struct nla_policy tcp_nla_policy[CTA_PROTOINFO_TCP_MAX+1] = {
+ [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 },
+ [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 },
+ [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 },
+ [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .len = sizeof(struct nf_ct_tcp_flags) },
+ [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .len = sizeof(struct nf_ct_tcp_flags) },
};
-static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
+static int nlattr_to_tcp(struct nlattr *cda[], struct nf_conn *ct)
{
- struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
- struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
+ struct nlattr *attr = cda[CTA_PROTOINFO_TCP];
+ struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
+ int err;
/* updates could not contain anything about the private
* protocol info, in that case skip the parsing */
if (!attr)
return 0;
- nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
-
- if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))
- return -EINVAL;
+ err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, tcp_nla_policy);
+ if (err < 0)
+ return err;
- if (!tb[CTA_PROTOINFO_TCP_STATE-1])
+ if (!tb[CTA_PROTOINFO_TCP_STATE])
return -EINVAL;
write_lock_bh(&tcp_lock);
ct->proto.tcp.state =
- *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
+ *(u_int8_t *)nla_data(tb[CTA_PROTOINFO_TCP_STATE]);
- if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]) {
+ if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) {
struct nf_ct_tcp_flags *attr =
- NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]);
+ nla_data(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]);
ct->proto.tcp.seen[0].flags &= ~attr->mask;
ct->proto.tcp.seen[0].flags |= attr->flags & attr->mask;
}
- if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]) {
+ if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]) {
struct nf_ct_tcp_flags *attr =
- NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]);
+ nla_data(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]);
ct->proto.tcp.seen[1].flags &= ~attr->mask;
ct->proto.tcp.seen[1].flags |= attr->flags & attr->mask;
}
- if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] &&
- tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1] &&
+ if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] &&
+ tb[CTA_PROTOINFO_TCP_WSCALE_REPLY] &&
ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
ct->proto.tcp.seen[0].td_scale = *(u_int8_t *)
- NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1]);
+ nla_data(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]);
ct->proto.tcp.seen[1].td_scale = *(u_int8_t *)
- NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]);
+ nla_data(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]);
}
write_unlock_bh(&tcp_lock);
@@ -1384,10 +1380,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
.new = tcp_new,
.error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .to_nfattr = tcp_to_nfattr,
- .from_nfattr = nfattr_to_tcp,
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .to_nlattr = tcp_to_nlattr,
+ .from_nlattr = nlattr_to_tcp,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &tcp_sysctl_table_users,
@@ -1413,10 +1410,11 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly =
.new = tcp_new,
.error = tcp_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .to_nfattr = tcp_to_nfattr,
- .from_nfattr = nfattr_to_tcp,
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .to_nlattr = tcp_to_nlattr,
+ .from_nlattr = nlattr_to_tcp,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &tcp_sysctl_table_users,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 2a2fd1a764ea..ba80e1a1ea17 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -203,8 +203,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
.new = udp_new,
.error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &udp_sysctl_table_users,
@@ -230,8 +231,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
.new = udp_new,
.error = udp_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &udp_sysctl_table_users,
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index b906b413997c..b8981dd922be 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -203,8 +203,9 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
.new = udplite_new,
.error = udplite_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &udplite_sysctl_table_users,
@@ -226,8 +227,9 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.new = udplite_new,
.error = udplite_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
- .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
- .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+ .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
+ .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
+ .nla_policy = nf_ct_port_nla_policy,
#endif
#ifdef CONFIG_SYSCTL
.ctl_table_users = &udplite_sysctl_table_users,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index a4ce5e887997..9efdd37fc195 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -14,6 +14,7 @@
#include <linux/seq_file.h>
#include <linux/percpu.h>
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
@@ -194,22 +195,8 @@ static const struct seq_operations ct_seq_ops = {
static int ct_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- struct ct_iter_state *st;
- int ret;
-
- st = kzalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
- if (st == NULL)
- return -ENOMEM;
- ret = seq_open(file, &ct_seq_ops);
- if (ret)
- goto out_free;
- seq = file->private_data;
- seq->private = st;
- return ret;
-out_free:
- kfree(st);
- return ret;
+ return seq_open_private(file, &ct_seq_ops,
+ sizeof(struct ct_iter_state));
}
static const struct file_operations ct_file_ops = {
@@ -420,10 +407,10 @@ static int __init nf_conntrack_standalone_init(void)
return ret;
#ifdef CONFIG_PROC_FS
- proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
+ proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
- proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
+ proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat);
if (!proc_stat)
goto cleanup_proc;
@@ -444,9 +431,9 @@ static int __init nf_conntrack_standalone_init(void)
cleanup_proc_stat:
#endif
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", proc_net_stat);
+ remove_proc_entry("nf_conntrack", init_net. proc_net_stat);
cleanup_proc:
- proc_net_remove("nf_conntrack");
+ proc_net_remove(&init_net, "nf_conntrack");
cleanup_init:
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
@@ -459,8 +446,8 @@ static void __exit nf_conntrack_standalone_fini(void)
unregister_sysctl_table(nf_ct_sysctl_header);
#endif
#ifdef CONFIG_PROC_FS
- remove_proc_entry("nf_conntrack", proc_net_stat);
- proc_net_remove("nf_conntrack");
+ remove_proc_entry("nf_conntrack", init_net.proc_net_stat);
+ proc_net_remove(&init_net, "nf_conntrack");
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
}
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index e32761ce260c..aa2831587b82 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -69,6 +69,9 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
struct nf_sockopt_ops *ops;
int ret;
+ if (sk->sk_net != &init_net)
+ return -ENOPROTOOPT;
+
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
@@ -125,6 +128,10 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
struct nf_sockopt_ops *ops;
int ret;
+ if (sk->sk_net != &init_net)
+ return -ENOPROTOOPT;
+
+
if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 8797e6953ef2..2128542995f7 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -41,32 +41,20 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
static char __initdata nfversion[] = "0.30";
static struct sock *nfnl = NULL;
-static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
+static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
static DEFINE_MUTEX(nfnl_mutex);
-static void nfnl_lock(void)
+static inline void nfnl_lock(void)
{
mutex_lock(&nfnl_mutex);
}
-static int nfnl_trylock(void)
-{
- return !mutex_trylock(&nfnl_mutex);
-}
-
-static void __nfnl_unlock(void)
-{
- mutex_unlock(&nfnl_mutex);
-}
-
-static void nfnl_unlock(void)
+static inline void nfnl_unlock(void)
{
mutex_unlock(&nfnl_mutex);
- if (nfnl->sk_receive_queue.qlen)
- nfnl->sk_data_ready(nfnl, 0);
}
-int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
+int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
{
nfnl_lock();
if (subsys_table[n->subsys_id]) {
@@ -80,7 +68,7 @@ int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
}
EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
-int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
+int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
{
nfnl_lock();
subsys_table[n->subsys_id] = NULL;
@@ -90,7 +78,7 @@ int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
}
EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
-static inline struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type)
+static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type)
{
u_int8_t subsys_id = NFNL_SUBSYS_ID(type);
@@ -100,8 +88,8 @@ static inline struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type)
return subsys_table[subsys_id];
}
-static inline struct nfnl_callback *
-nfnetlink_find_client(u_int16_t type, struct nfnetlink_subsystem *ss)
+static inline const struct nfnl_callback *
+nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss)
{
u_int8_t cb_id = NFNL_MSG_TYPE(type);
@@ -111,62 +99,6 @@ nfnetlink_find_client(u_int16_t type, struct nfnetlink_subsystem *ss)
return &ss->cb[cb_id];
}
-void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
- const void *data)
-{
- struct nfattr *nfa;
- int size = NFA_LENGTH(attrlen);
-
- nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
- nfa->nfa_type = attrtype;
- nfa->nfa_len = size;
- memcpy(NFA_DATA(nfa), data, attrlen);
- memset(NFA_DATA(nfa) + attrlen, 0, NFA_ALIGN(size) - size);
-}
-EXPORT_SYMBOL_GPL(__nfa_fill);
-
-void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
-{
- memset(tb, 0, sizeof(struct nfattr *) * maxattr);
-
- while (NFA_OK(nfa, len)) {
- unsigned flavor = NFA_TYPE(nfa);
- if (flavor && flavor <= maxattr)
- tb[flavor-1] = nfa;
- nfa = NFA_NEXT(nfa, len);
- }
-}
-EXPORT_SYMBOL_GPL(nfattr_parse);
-
-/**
- * nfnetlink_check_attributes - check and parse nfnetlink attributes
- *
- * subsys: nfnl subsystem for which this message is to be parsed
- * nlmsghdr: netlink message to be checked/parsed
- * cda: array of pointers, needs to be at least subsys->attr_count big
- *
- */
-static int
-nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
- struct nlmsghdr *nlh, struct nfattr *cda[])
-{
- int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
- u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
- u_int16_t attr_count = subsys->cb[cb_id].attr_count;
-
- /* check attribute lengths. */
- if (likely(nlh->nlmsg_len > min_len)) {
- struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
- int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
- nfattr_parse(cda, attr_count, attr, attrlen);
- }
-
- /* implicit: if nlmsg_len == min_len, we return 0, and an empty
- * (zeroed) cda[] array. The message is valid, but empty. */
-
- return 0;
-}
-
int nfnetlink_has_listeners(unsigned int group)
{
return netlink_has_listeners(nfnl, group);
@@ -175,16 +107,7 @@ EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
{
- int err = 0;
-
- NETLINK_CB(skb).dst_group = group;
- if (echo)
- atomic_inc(&skb->users);
- netlink_broadcast(nfnl, skb, pid, group, gfp_any());
- if (echo)
- err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
-
- return err;
+ return nlmsg_notify(nfnl, skb, pid, group, echo, gfp_any());
}
EXPORT_SYMBOL_GPL(nfnetlink_send);
@@ -197,8 +120,8 @@ EXPORT_SYMBOL_GPL(nfnetlink_unicast);
/* Process one complete nfnetlink message. */
static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
- struct nfnl_callback *nc;
- struct nfnetlink_subsystem *ss;
+ const struct nfnl_callback *nc;
+ const struct nfnetlink_subsystem *ss;
int type, err;
if (security_netlink_recv(skb, CAP_NET_ADMIN))
@@ -212,9 +135,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
ss = nfnetlink_get_subsys(type);
if (!ss) {
#ifdef CONFIG_KMOD
- /* don't call nfnl_unlock, since it would reenter
- * with further packet processing */
- __nfnl_unlock();
+ nfnl_unlock();
request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
nfnl_lock();
ss = nfnetlink_get_subsys(type);
@@ -228,29 +149,31 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
{
- u_int16_t attr_count =
- ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
- struct nfattr *cda[attr_count];
-
- memset(cda, 0, sizeof(struct nfattr *) * attr_count);
+ int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+ u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
+ u_int16_t attr_count = ss->cb[cb_id].attr_count;
+ struct nlattr *cda[attr_count+1];
+
+ if (likely(nlh->nlmsg_len >= min_len)) {
+ struct nlattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);
+ int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
+
+ err = nla_parse(cda, attr_count, attr, attrlen,
+ ss->cb[cb_id].policy);
+ if (err < 0)
+ return err;
+ } else
+ return -EINVAL;
- err = nfnetlink_check_attributes(ss, nlh, cda);
- if (err < 0)
- return err;
return nc->call(nfnl, skb, nlh, cda);
}
}
-static void nfnetlink_rcv(struct sock *sk, int len)
+static void nfnetlink_rcv(struct sk_buff *skb)
{
- unsigned int qlen = 0;
-
- do {
- if (nfnl_trylock())
- return;
- netlink_run_queue(sk, &qlen, nfnetlink_rcv_msg);
- __nfnl_unlock();
- } while (qlen);
+ nfnl_lock();
+ netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
+ nfnl_unlock();
}
static void __exit nfnetlink_exit(void)
@@ -264,7 +187,7 @@ static int __init nfnetlink_init(void)
{
printk("Netfilter messages via NETLINK v%s.\n", nfversion);
- nfnl = netlink_kernel_create(NETLINK_NETFILTER, NFNLGRP_MAX,
+ nfnl = netlink_kernel_create(&init_net, NETLINK_NETFILTER, NFNLGRP_MAX,
nfnetlink_rcv, NULL, THIS_MODULE);
if (!nfnl) {
printk(KERN_ERR "cannot initialize nfnetlink!\n");
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 2351533a8507..2c7bd2eb0294 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -37,8 +37,9 @@
#endif
#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
-#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
+#define NFULNL_TIMEOUT_DEFAULT HZ /* every second */
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
+#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */
#define PRINTR(x, args...) do { if (net_ratelimit()) \
printk(x, ## args); } while (0);
@@ -152,6 +153,11 @@ instance_create(u_int16_t group_num, int pid)
if (!inst)
goto out_unlock;
+ if (!try_module_get(THIS_MODULE)) {
+ kfree(inst);
+ goto out_unlock;
+ }
+
INIT_HLIST_NODE(&inst->hlist);
spin_lock_init(&inst->lock);
/* needs to be two, since we _put() after creation */
@@ -166,10 +172,7 @@ instance_create(u_int16_t group_num, int pid)
inst->flushtimeout = NFULNL_TIMEOUT_DEFAULT;
inst->nlbufsiz = NFULNL_NLBUFSIZ_DEFAULT;
inst->copy_mode = NFULNL_COPY_PACKET;
- inst->copy_range = 0xffff;
-
- if (!try_module_get(THIS_MODULE))
- goto out_free;
+ inst->copy_range = NFULNL_COPY_RANGE_MAX;
hlist_add_head(&inst->hlist,
&instance_table[instance_hashfn(group_num)]);
@@ -181,14 +184,12 @@ instance_create(u_int16_t group_num, int pid)
return inst;
-out_free:
- instance_put(inst);
out_unlock:
write_unlock_bh(&instances_lock);
return NULL;
}
-static int __nfulnl_send(struct nfulnl_instance *inst);
+static void __nfulnl_flush(struct nfulnl_instance *inst);
static void
__instance_destroy(struct nfulnl_instance *inst)
@@ -202,17 +203,8 @@ __instance_destroy(struct nfulnl_instance *inst)
/* then flush all pending packets from skb */
spin_lock_bh(&inst->lock);
- if (inst->skb) {
- /* timer "holds" one reference (we have one more) */
- if (del_timer(&inst->timer))
- instance_put(inst);
- if (inst->qlen)
- __nfulnl_send(inst);
- if (inst->skb) {
- kfree_skb(inst->skb);
- inst->skb = NULL;
- }
- }
+ if (inst->skb)
+ __nfulnl_flush(inst);
spin_unlock_bh(&inst->lock);
/* and finally put the refcount */
@@ -244,11 +236,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
case NFULNL_COPY_PACKET:
inst->copy_mode = mode;
- /* we're using struct nfattr which has 16bit nfa_len */
- if (range > 0xffff)
- inst->copy_range = 0xffff;
- else
- inst->copy_range = range;
+ inst->copy_range = min_t(unsigned int,
+ range, NFULNL_COPY_RANGE_MAX);
break;
default:
@@ -310,8 +299,8 @@ nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
return 0;
}
-static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size,
- unsigned int pkt_size)
+static struct sk_buff *
+nfulnl_alloc_skb(unsigned int inst_size, unsigned int pkt_size)
{
struct sk_buff *skb;
unsigned int n;
@@ -364,7 +353,18 @@ nlmsg_failure:
return status;
}
-static void nfulnl_timer(unsigned long data)
+static void
+__nfulnl_flush(struct nfulnl_instance *inst)
+{
+ /* timer holds a reference */
+ if (del_timer(&inst->timer))
+ instance_put(inst);
+ if (inst->skb)
+ __nfulnl_send(inst);
+}
+
+static void
+nfulnl_timer(unsigned long data)
{
struct nfulnl_instance *inst = (struct nfulnl_instance *)data;
@@ -409,36 +409,36 @@ __build_packet_message(struct nfulnl_instance *inst,
pmsg.hw_protocol = skb->protocol;
pmsg.hook = hooknum;
- NFA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
+ NLA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
if (prefix)
- NFA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
+ NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
if (indev) {
tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV, sizeof(tmp_uint),
+ NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV, sizeof(tmp_uint),
&tmp_uint);
#else
if (pf == PF_BRIDGE) {
/* Case 1: outdev is physical input device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
sizeof(tmp_uint), &tmp_uint);
/* this is the bridge group "brX" */
tmp_uint = htonl(indev->br_port->br->dev->ifindex);
- NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
sizeof(tmp_uint), &tmp_uint);
} else {
/* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */
- NFA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
sizeof(tmp_uint), &tmp_uint);
if (skb->nf_bridge && skb->nf_bridge->physindev) {
tmp_uint =
htonl(skb->nf_bridge->physindev->ifindex);
- NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
sizeof(tmp_uint), &tmp_uint);
}
}
@@ -448,28 +448,28 @@ __build_packet_message(struct nfulnl_instance *inst,
if (outdev) {
tmp_uint = htonl(outdev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint),
&tmp_uint);
#else
if (pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
sizeof(tmp_uint), &tmp_uint);
/* this is the bridge group "brX" */
tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
- NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
sizeof(tmp_uint), &tmp_uint);
} else {
/* Case 2: indev is a bridge group, we need to look
* for physical device (when called from ipv4) */
- NFA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
sizeof(tmp_uint), &tmp_uint);
if (skb->nf_bridge && skb->nf_bridge->physoutdev) {
tmp_uint =
htonl(skb->nf_bridge->physoutdev->ifindex);
- NFA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+ NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
sizeof(tmp_uint), &tmp_uint);
}
}
@@ -478,15 +478,16 @@ __build_packet_message(struct nfulnl_instance *inst,
if (skb->mark) {
tmp_uint = htonl(skb->mark);
- NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
}
- if (indev && skb->dev && skb->dev->hard_header_parse) {
+ if (indev && skb->dev) {
struct nfulnl_msg_packet_hw phw;
- int len = skb->dev->hard_header_parse((struct sk_buff *)skb,
- phw.hw_addr);
- phw.hw_addrlen = htons(len);
- NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+ int len = dev_parse_header(skb, phw.hw_addr);
+ if (len > 0) {
+ phw.hw_addrlen = htons(len);
+ NLA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+ }
}
if (skb->tstamp.tv64) {
@@ -495,7 +496,7 @@ __build_packet_message(struct nfulnl_instance *inst,
ts.sec = cpu_to_be64(tv.tv_sec);
ts.usec = cpu_to_be64(tv.tv_usec);
- NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
+ NLA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
}
/* UID */
@@ -503,9 +504,9 @@ __build_packet_message(struct nfulnl_instance *inst,
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
__be32 uid = htonl(skb->sk->sk_socket->file->f_uid);
- /* need to unlock here since NFA_PUT may goto */
+ /* need to unlock here since NLA_PUT may goto */
read_unlock_bh(&skb->sk->sk_callback_lock);
- NFA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
+ NLA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
} else
read_unlock_bh(&skb->sk->sk_callback_lock);
}
@@ -513,28 +514,28 @@ __build_packet_message(struct nfulnl_instance *inst,
/* local sequence number */
if (inst->flags & NFULNL_CFG_F_SEQ) {
tmp_uint = htonl(inst->seq++);
- NFA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint);
}
/* global sequence number */
if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) {
tmp_uint = htonl(atomic_inc_return(&global_seq));
- NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
}
if (data_len) {
- struct nfattr *nfa;
- int size = NFA_LENGTH(data_len);
+ struct nlattr *nla;
+ int size = nla_attr_size(data_len);
- if (skb_tailroom(inst->skb) < (int)NFA_SPACE(data_len)) {
+ if (skb_tailroom(inst->skb) < nla_total_size(data_len)) {
printk(KERN_WARNING "nfnetlink_log: no tailroom!\n");
goto nlmsg_failure;
}
- nfa = (struct nfattr *)skb_put(inst->skb, NFA_ALIGN(size));
- nfa->nfa_type = NFULA_PAYLOAD;
- nfa->nfa_len = size;
+ nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len));
+ nla->nla_type = NFULA_PAYLOAD;
+ nla->nla_len = size;
- if (skb_copy_bits(skb, 0, NFA_DATA(nfa), data_len))
+ if (skb_copy_bits(skb, 0, nla_data(nla), data_len))
BUG();
}
@@ -543,7 +544,7 @@ __build_packet_message(struct nfulnl_instance *inst,
nlmsg_failure:
UDEBUG("nlmsg_failure\n");
-nfattr_failure:
+nla_put_failure:
PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n");
return -1;
}
@@ -590,32 +591,31 @@ nfulnl_log_packet(unsigned int pf,
if (prefix)
plen = strlen(prefix) + 1;
- /* all macros expand to constant values at compile time */
/* FIXME: do we want to make the size calculation conditional based on
* what is actually present? way more branches and checks, but more
* memory efficient... */
- size = NLMSG_SPACE(sizeof(struct nfgenmsg))
- + NFA_SPACE(sizeof(struct nfulnl_msg_packet_hdr))
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
#ifdef CONFIG_BRIDGE_NETFILTER
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
#endif
- + NFA_SPACE(sizeof(u_int32_t)) /* mark */
- + NFA_SPACE(sizeof(u_int32_t)) /* uid */
- + NFA_SPACE(plen) /* prefix */
- + NFA_SPACE(sizeof(struct nfulnl_msg_packet_hw))
- + NFA_SPACE(sizeof(struct nfulnl_msg_packet_timestamp));
+ + nla_total_size(sizeof(u_int32_t)) /* mark */
+ + nla_total_size(sizeof(u_int32_t)) /* uid */
+ + nla_total_size(plen) /* prefix */
+ + nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
+ + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
UDEBUG("initial size=%u\n", size);
spin_lock_bh(&inst->lock);
if (inst->flags & NFULNL_CFG_F_SEQ)
- size += NFA_SPACE(sizeof(u_int32_t));
+ size += nla_total_size(sizeof(u_int32_t));
if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
- size += NFA_SPACE(sizeof(u_int32_t));
+ size += nla_total_size(sizeof(u_int32_t));
qthreshold = inst->qthreshold;
/* per-rule qthreshold overrides per-instance */
@@ -635,7 +635,7 @@ nfulnl_log_packet(unsigned int pf,
else
data_len = inst->copy_range;
- size += NFA_SPACE(data_len);
+ size += nla_total_size(data_len);
UDEBUG("copy_packet, therefore size now %u\n", size);
break;
@@ -643,17 +643,13 @@ nfulnl_log_packet(unsigned int pf,
goto unlock_and_release;
}
- if (inst->qlen >= qthreshold ||
- (inst->skb && size >
- skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) {
+ if (inst->skb &&
+ size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
/* either the queue len is too high or we don't have
* enough room in the skb left. flush to userspace. */
UDEBUG("flushing old skb\n");
- /* timer "holds" one reference (we have another one) */
- if (del_timer(&inst->timer))
- instance_put(inst);
- __nfulnl_send(inst);
+ __nfulnl_flush(inst);
}
if (!inst->skb) {
@@ -668,9 +664,11 @@ nfulnl_log_packet(unsigned int pf,
__build_packet_message(inst, skb, data_len, pf,
hooknum, in, out, li, prefix, plen);
+ if (inst->qlen >= qthreshold)
+ __nfulnl_flush(inst);
/* timer_pending always called within inst->lock, so there
* is no chance of a race here */
- if (!timer_pending(&inst->timer)) {
+ else if (!timer_pending(&inst->timer)) {
instance_get(inst);
inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100);
add_timer(&inst->timer);
@@ -706,7 +704,8 @@ nfulnl_rcv_nl_event(struct notifier_block *this,
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
UDEBUG("node = %p\n", inst);
- if (n->pid == inst->peer_pid)
+ if ((n->net == &init_net) &&
+ (n->pid == inst->peer_pid))
__instance_destroy(inst);
}
}
@@ -721,7 +720,7 @@ static struct notifier_block nfulnl_rtnl_notifier = {
static int
nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
return -ENOTSUPP;
}
@@ -732,34 +731,18 @@ static struct nf_logger nfulnl_logger = {
.me = THIS_MODULE,
};
-static const int nfula_min[NFULA_MAX] = {
- [NFULA_PACKET_HDR-1] = sizeof(struct nfulnl_msg_packet_hdr),
- [NFULA_MARK-1] = sizeof(u_int32_t),
- [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp),
- [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t),
- [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t),
- [NFULA_IFINDEX_PHYSINDEV-1] = sizeof(u_int32_t),
- [NFULA_IFINDEX_PHYSOUTDEV-1] = sizeof(u_int32_t),
- [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw),
- [NFULA_PAYLOAD-1] = 0,
- [NFULA_PREFIX-1] = 0,
- [NFULA_UID-1] = sizeof(u_int32_t),
- [NFULA_SEQ-1] = sizeof(u_int32_t),
- [NFULA_SEQ_GLOBAL-1] = sizeof(u_int32_t),
-};
-
-static const int nfula_cfg_min[NFULA_CFG_MAX] = {
- [NFULA_CFG_CMD-1] = sizeof(struct nfulnl_msg_config_cmd),
- [NFULA_CFG_MODE-1] = sizeof(struct nfulnl_msg_config_mode),
- [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t),
- [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t),
- [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t),
- [NFULA_CFG_FLAGS-1] = sizeof(u_int16_t),
+static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = {
+ [NFULA_CFG_CMD] = { .len = sizeof(struct nfulnl_msg_config_cmd) },
+ [NFULA_CFG_MODE] = { .len = sizeof(struct nfulnl_msg_config_mode) },
+ [NFULA_CFG_TIMEOUT] = { .type = NLA_U32 },
+ [NFULA_CFG_QTHRESH] = { .type = NLA_U32 },
+ [NFULA_CFG_NLBUFSIZ] = { .type = NLA_U32 },
+ [NFULA_CFG_FLAGS] = { .type = NLA_U16 },
};
static int
nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfula[])
+ struct nlmsghdr *nlh, struct nlattr *nfula[])
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t group_num = ntohs(nfmsg->res_id);
@@ -768,16 +751,11 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
UDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
- if (nfattr_bad_size(nfula, NFULA_CFG_MAX, nfula_cfg_min)) {
- UDEBUG("bad attribute size\n");
- return -EINVAL;
- }
-
inst = instance_lookup_get(group_num);
- if (nfula[NFULA_CFG_CMD-1]) {
+ if (nfula[NFULA_CFG_CMD]) {
u_int8_t pf = nfmsg->nfgen_family;
struct nfulnl_msg_config_cmd *cmd;
- cmd = NFA_DATA(nfula[NFULA_CFG_CMD-1]);
+ cmd = nla_data(nfula[NFULA_CFG_CMD]);
UDEBUG("found CFG_CMD for\n");
switch (cmd->command) {
@@ -840,38 +818,38 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
}
}
- if (nfula[NFULA_CFG_MODE-1]) {
+ if (nfula[NFULA_CFG_MODE]) {
struct nfulnl_msg_config_mode *params;
- params = NFA_DATA(nfula[NFULA_CFG_MODE-1]);
+ params = nla_data(nfula[NFULA_CFG_MODE]);
nfulnl_set_mode(inst, params->copy_mode,
ntohl(params->copy_range));
}
- if (nfula[NFULA_CFG_TIMEOUT-1]) {
+ if (nfula[NFULA_CFG_TIMEOUT]) {
__be32 timeout =
- *(__be32 *)NFA_DATA(nfula[NFULA_CFG_TIMEOUT-1]);
+ *(__be32 *)nla_data(nfula[NFULA_CFG_TIMEOUT]);
nfulnl_set_timeout(inst, ntohl(timeout));
}
- if (nfula[NFULA_CFG_NLBUFSIZ-1]) {
+ if (nfula[NFULA_CFG_NLBUFSIZ]) {
__be32 nlbufsiz =
- *(__be32 *)NFA_DATA(nfula[NFULA_CFG_NLBUFSIZ-1]);
+ *(__be32 *)nla_data(nfula[NFULA_CFG_NLBUFSIZ]);
nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz));
}
- if (nfula[NFULA_CFG_QTHRESH-1]) {
+ if (nfula[NFULA_CFG_QTHRESH]) {
__be32 qthresh =
- *(__be32 *)NFA_DATA(nfula[NFULA_CFG_QTHRESH-1]);
+ *(__be32 *)nla_data(nfula[NFULA_CFG_QTHRESH]);
nfulnl_set_qthresh(inst, ntohl(qthresh));
}
- if (nfula[NFULA_CFG_FLAGS-1]) {
+ if (nfula[NFULA_CFG_FLAGS]) {
__be16 flags =
- *(__be16 *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
+ *(__be16 *)nla_data(nfula[NFULA_CFG_FLAGS]);
nfulnl_set_flags(inst, ntohs(flags));
}
@@ -881,14 +859,15 @@ out:
return ret;
}
-static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
+static const struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
[NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp,
.attr_count = NFULA_MAX, },
[NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config,
- .attr_count = NFULA_CFG_MAX, },
+ .attr_count = NFULA_CFG_MAX,
+ .policy = nfula_cfg_policy },
};
-static struct nfnetlink_subsystem nfulnl_subsys = {
+static const struct nfnetlink_subsystem nfulnl_subsys = {
.name = "log",
.subsys_id = NFNL_SUBSYS_ULOG,
.cb_count = NFULNL_MSG_MAX,
@@ -972,22 +951,8 @@ static const struct seq_operations nful_seq_ops = {
static int nful_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- struct iter_state *is;
- int ret;
-
- is = kzalloc(sizeof(*is), GFP_KERNEL);
- if (!is)
- return -ENOMEM;
- ret = seq_open(file, &nful_seq_ops);
- if (ret < 0)
- goto out_free;
- seq = file->private_data;
- seq->private = is;
- return ret;
-out_free:
- kfree(is);
- return ret;
+ return seq_open_private(file, &nful_seq_ops,
+ sizeof(struct iter_state));
}
static const struct file_operations nful_file_ops = {
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index bb65a38c816c..49f0480afe09 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -299,7 +299,7 @@ __nfqnl_set_mode(struct nfqnl_instance *queue,
case NFQNL_COPY_PACKET:
queue->copy_mode = mode;
- /* we're using struct nfattr which has 16bit nfa_len */
+ /* we're using struct nlattr which has 16bit nla_len */
if (range > 0xffff)
queue->copy_range = 0xffff;
else
@@ -353,18 +353,17 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
QDEBUG("entered\n");
- /* all macros expand to constant values at compile time */
- size = NLMSG_SPACE(sizeof(struct nfgenmsg)) +
- + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hdr))
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
#ifdef CONFIG_BRIDGE_NETFILTER
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
#endif
- + NFA_SPACE(sizeof(u_int32_t)) /* mark */
- + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hw))
- + NFA_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
+ + nla_total_size(sizeof(u_int32_t)) /* mark */
+ + nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
+ + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
outdev = entinf->outdev;
@@ -389,7 +388,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
else
data_len = queue->copy_range;
- size += NFA_SPACE(data_len);
+ size += nla_total_size(data_len);
break;
default:
@@ -417,33 +416,33 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
pmsg.hw_protocol = entskb->protocol;
pmsg.hook = entinf->hook;
- NFA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
+ NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
indev = entinf->indev;
if (indev) {
tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
#else
if (entinf->pf == PF_BRIDGE) {
/* Case 1: indev is physical input device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
&tmp_uint);
/* this is the bridge group "brX" */
tmp_uint = htonl(indev->br_port->br->dev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
&tmp_uint);
} else {
/* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */
- NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
&tmp_uint);
if (entskb->nf_bridge
&& entskb->nf_bridge->physindev) {
tmp_uint = htonl(entskb->nf_bridge->physindev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
sizeof(tmp_uint), &tmp_uint);
}
}
@@ -453,27 +452,27 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
if (outdev) {
tmp_uint = htonl(outdev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
#else
if (entinf->pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
&tmp_uint);
/* this is the bridge group "brX" */
tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
&tmp_uint);
} else {
/* Case 2: outdev is bridge group, we need to look for
* physical output device (when called from ipv4) */
- NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
&tmp_uint);
if (entskb->nf_bridge
&& entskb->nf_bridge->physoutdev) {
tmp_uint = htonl(entskb->nf_bridge->physoutdev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
sizeof(tmp_uint), &tmp_uint);
}
}
@@ -482,17 +481,16 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
if (entskb->mark) {
tmp_uint = htonl(entskb->mark);
- NFA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
+ NLA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
}
- if (indev && entskb->dev
- && entskb->dev->hard_header_parse) {
+ if (indev && entskb->dev) {
struct nfqnl_msg_packet_hw phw;
-
- int len = entskb->dev->hard_header_parse(entskb,
- phw.hw_addr);
- phw.hw_addrlen = htons(len);
- NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
+ int len = dev_parse_header(entskb, phw.hw_addr);
+ if (len) {
+ phw.hw_addrlen = htons(len);
+ NLA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
+ }
}
if (entskb->tstamp.tv64) {
@@ -501,23 +499,23 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
ts.sec = cpu_to_be64(tv.tv_sec);
ts.usec = cpu_to_be64(tv.tv_usec);
- NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
+ NLA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
}
if (data_len) {
- struct nfattr *nfa;
- int size = NFA_LENGTH(data_len);
+ struct nlattr *nla;
+ int size = nla_attr_size(data_len);
- if (skb_tailroom(skb) < (int)NFA_SPACE(data_len)) {
+ if (skb_tailroom(skb) < nla_total_size(data_len)) {
printk(KERN_WARNING "nf_queue: no tailroom!\n");
goto nlmsg_failure;
}
- nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
- nfa->nfa_type = NFQA_PAYLOAD;
- nfa->nfa_len = size;
+ nla = (struct nlattr *)skb_put(skb, nla_total_size(data_len));
+ nla->nla_type = NFQA_PAYLOAD;
+ nla->nla_len = size;
- if (skb_copy_bits(entskb, 0, NFA_DATA(nfa), data_len))
+ if (skb_copy_bits(entskb, 0, nla_data(nla), data_len))
BUG();
}
@@ -525,7 +523,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
return skb;
nlmsg_failure:
-nfattr_failure:
+nla_put_failure:
if (skb)
kfree_skb(skb);
*errp = -EINVAL;
@@ -734,6 +732,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
{
struct net_device *dev = ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
/* Drop any packets associated with the downed device */
if (event == NETDEV_DOWN)
nfqnl_dev_drop(dev->ifindex);
@@ -762,7 +763,8 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
struct hlist_head *head = &instance_table[i];
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
- if (n->pid == inst->peer_pid)
+ if ((n->net == &init_net) &&
+ (n->pid == inst->peer_pid))
__instance_destroy(inst);
}
}
@@ -775,15 +777,15 @@ static struct notifier_block nfqnl_rtnl_notifier = {
.notifier_call = nfqnl_rcv_nl_event,
};
-static const int nfqa_verdict_min[NFQA_MAX] = {
- [NFQA_VERDICT_HDR-1] = sizeof(struct nfqnl_msg_verdict_hdr),
- [NFQA_MARK-1] = sizeof(u_int32_t),
- [NFQA_PAYLOAD-1] = 0,
+static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
+ [NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
+ [NFQA_MARK] = { .type = NLA_U32 },
+ [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
};
static int
nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t queue_num = ntohs(nfmsg->res_id);
@@ -794,11 +796,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
struct nfqnl_queue_entry *entry;
int err;
- if (nfattr_bad_size(nfqa, NFQA_MAX, nfqa_verdict_min)) {
- QDEBUG("bad attribute size\n");
- return -EINVAL;
- }
-
queue = instance_lookup_get(queue_num);
if (!queue)
return -ENODEV;
@@ -808,12 +805,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
goto err_out_put;
}
- if (!nfqa[NFQA_VERDICT_HDR-1]) {
+ if (!nfqa[NFQA_VERDICT_HDR]) {
err = -EINVAL;
goto err_out_put;
}
- vhdr = NFA_DATA(nfqa[NFQA_VERDICT_HDR-1]);
+ vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
verdict = ntohl(vhdr->verdict);
if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
@@ -827,15 +824,15 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
goto err_out_put;
}
- if (nfqa[NFQA_PAYLOAD-1]) {
- if (nfqnl_mangle(NFA_DATA(nfqa[NFQA_PAYLOAD-1]),
- NFA_PAYLOAD(nfqa[NFQA_PAYLOAD-1]), entry) < 0)
+ if (nfqa[NFQA_PAYLOAD]) {
+ if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
+ nla_len(nfqa[NFQA_PAYLOAD]), entry) < 0)
verdict = NF_DROP;
}
- if (nfqa[NFQA_MARK-1])
+ if (nfqa[NFQA_MARK])
entry->skb->mark = ntohl(*(__be32 *)
- NFA_DATA(nfqa[NFQA_MARK-1]));
+ nla_data(nfqa[NFQA_MARK]));
issue_verdict(entry, verdict);
instance_put(queue);
@@ -848,14 +845,14 @@ err_out_put:
static int
nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
return -ENOTSUPP;
}
-static const int nfqa_cfg_min[NFQA_CFG_MAX] = {
- [NFQA_CFG_CMD-1] = sizeof(struct nfqnl_msg_config_cmd),
- [NFQA_CFG_PARAMS-1] = sizeof(struct nfqnl_msg_config_params),
+static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = {
+ [NFQA_CFG_CMD] = { .len = sizeof(struct nfqnl_msg_config_cmd) },
+ [NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) },
};
static struct nf_queue_handler nfqh = {
@@ -865,7 +862,7 @@ static struct nf_queue_handler nfqh = {
static int
nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t queue_num = ntohs(nfmsg->res_id);
@@ -874,15 +871,10 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
QDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
- if (nfattr_bad_size(nfqa, NFQA_CFG_MAX, nfqa_cfg_min)) {
- QDEBUG("bad attribute size\n");
- return -EINVAL;
- }
-
queue = instance_lookup_get(queue_num);
- if (nfqa[NFQA_CFG_CMD-1]) {
+ if (nfqa[NFQA_CFG_CMD]) {
struct nfqnl_msg_config_cmd *cmd;
- cmd = NFA_DATA(nfqa[NFQA_CFG_CMD-1]);
+ cmd = nla_data(nfqa[NFQA_CFG_CMD]);
QDEBUG("found CFG_CMD\n");
switch (cmd->command) {
@@ -933,21 +925,21 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
}
}
- if (nfqa[NFQA_CFG_PARAMS-1]) {
+ if (nfqa[NFQA_CFG_PARAMS]) {
struct nfqnl_msg_config_params *params;
if (!queue) {
ret = -ENOENT;
goto out_put;
}
- params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]);
+ params = nla_data(nfqa[NFQA_CFG_PARAMS]);
nfqnl_set_mode(queue, params->copy_mode,
ntohl(params->copy_range));
}
- if (nfqa[NFQA_CFG_QUEUE_MAXLEN-1]) {
+ if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) {
__be32 *queue_maxlen;
- queue_maxlen = NFA_DATA(nfqa[NFQA_CFG_QUEUE_MAXLEN-1]);
+ queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
spin_lock_bh(&queue->lock);
queue->queue_maxlen = ntohl(*queue_maxlen);
spin_unlock_bh(&queue->lock);
@@ -958,16 +950,18 @@ out_put:
return ret;
}
-static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
+static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
[NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp,
.attr_count = NFQA_MAX, },
[NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict,
- .attr_count = NFQA_MAX, },
+ .attr_count = NFQA_MAX,
+ .policy = nfqa_verdict_policy },
[NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
- .attr_count = NFQA_CFG_MAX, },
+ .attr_count = NFQA_CFG_MAX,
+ .policy = nfqa_cfg_policy },
};
-static struct nfnetlink_subsystem nfqnl_subsys = {
+static const struct nfnetlink_subsystem nfqnl_subsys = {
.name = "nf_queue",
.subsys_id = NFNL_SUBSYS_QUEUE,
.cb_count = NFQNL_MSG_MAX,
@@ -1057,22 +1051,8 @@ static const struct seq_operations nfqnl_seq_ops = {
static int nfqnl_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- struct iter_state *is;
- int ret;
-
- is = kzalloc(sizeof(*is), GFP_KERNEL);
- if (!is)
- return -ENOMEM;
- ret = seq_open(file, &nfqnl_seq_ops);
- if (ret < 0)
- goto out_free;
- seq = file->private_data;
- seq->private = is;
- return ret;
-out_free:
- kfree(is);
- return ret;
+ return seq_open_private(file, &nfqnl_seq_ops,
+ sizeof(struct iter_state));
}
static const struct file_operations nfqnl_file_ops = {
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index cc2baa6d5a7a..d9a3bded0d00 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/mutex.h>
#include <linux/mm.h>
+#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp.h>
@@ -795,7 +796,7 @@ int xt_proto_init(int af)
#ifdef CONFIG_PROC_FS
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TABLES, sizeof(buf));
- proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
if (!proc)
goto out;
proc->data = (void *) ((unsigned long) af | (TABLE << 16));
@@ -803,14 +804,14 @@ int xt_proto_init(int af)
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_MATCHES, sizeof(buf));
- proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
if (!proc)
goto out_remove_tables;
proc->data = (void *) ((unsigned long) af | (MATCH << 16));
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TARGETS, sizeof(buf));
- proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ proc = proc_net_fops_create(&init_net, buf, 0440, &xt_file_ops);
if (!proc)
goto out_remove_matches;
proc->data = (void *) ((unsigned long) af | (TARGET << 16));
@@ -822,12 +823,12 @@ int xt_proto_init(int af)
out_remove_matches:
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_MATCHES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
out_remove_tables:
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TABLES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
out:
return -1;
#endif
@@ -841,15 +842,15 @@ void xt_proto_fini(int af)
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TABLES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_TARGETS, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
strlcpy(buf, xt_prefix[af], sizeof(buf));
strlcat(buf, FORMAT_MATCHES, sizeof(buf));
- proc_net_remove(buf);
+ proc_net_remove(&init_net, buf);
#endif /*CONFIG_PROC_FS*/
}
EXPORT_SYMBOL_GPL(xt_proto_fini);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 519428566829..07a1b9665005 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -24,6 +24,7 @@ MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("iptables qdisc classification target module");
MODULE_ALIAS("ipt_CLASSIFY");
+MODULE_ALIAS("ip6t_CLASSIFY");
static unsigned int
target(struct sk_buff **pskb,
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 5a00c5444334..7043c2757e09 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -27,6 +27,7 @@ MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
MODULE_DESCRIPTION("IP tables CONNMARK matching module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_CONNMARK");
+MODULE_ALIAS("ip6t_CONNMARK");
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_CONNMARK.h>
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index b7d6312fccc7..fec1aefb1c32 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -9,6 +9,7 @@
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_NOTRACK");
+MODULE_ALIAS("ip6t_NOTRACK");
static unsigned int
target(struct sk_buff **pskb,
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index dd4d79b8fc9d..af79423bc8e8 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -14,6 +14,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
MODULE_ALIAS("ipt_connbytes");
+MODULE_ALIAS("ip6t_connbytes");
static bool
match(const struct sk_buff *skb,
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index e73fa9b46cf7..1071fc54d6d3 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -29,6 +29,7 @@ MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
MODULE_DESCRIPTION("IP tables connmark match module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connmark");
+MODULE_ALIAS("ip6t_connmark");
static bool
match(const struct sk_buff *skb,
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 83224ec89cc0..c2b1b24ee335 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -24,6 +24,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("Match for DCCP protocol packets");
MODULE_ALIAS("ipt_dccp");
+MODULE_ALIAS("ip6t_dccp");
#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
|| (!!((invflag) & (option)) ^ (cond)))
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index bd45f9d3f7d0..19103678bf20 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -21,6 +21,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
@@ -743,13 +744,13 @@ static int __init xt_hashlimit_init(void)
printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
goto err2;
}
- hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", proc_net);
+ hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net);
if (!hashlimit_procdir4) {
printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
"entry\n");
goto err3;
}
- hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", proc_net);
+ hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
if (!hashlimit_procdir6) {
printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
"entry\n");
@@ -757,7 +758,7 @@ static int __init xt_hashlimit_init(void)
}
return 0;
err4:
- remove_proc_entry("ipt_hashlimit", proc_net);
+ remove_proc_entry("ipt_hashlimit", init_net.proc_net);
err3:
kmem_cache_destroy(hashlimit_cachep);
err2:
@@ -769,8 +770,8 @@ err1:
static void __exit xt_hashlimit_fini(void)
{
- remove_proc_entry("ipt_hashlimit", proc_net);
- remove_proc_entry("ip6t_hashlimit", proc_net);
+ remove_proc_entry("ipt_hashlimit", init_net.proc_net);
+ remove_proc_entry("ip6t_hashlimit", init_net.proc_net);
kmem_cache_destroy(hashlimit_cachep);
xt_unregister_matches(xt_hashlimit, ARRAY_SIZE(xt_hashlimit));
}
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index c002153b80ab..f907770fd4e9 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -13,6 +13,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
MODULE_DESCRIPTION("Match for SCTP protocol packets");
MODULE_ALIAS("ipt_sctp");
+MODULE_ALIAS("ip6t_sctp");
#ifdef DEBUG_SCTP
#define duprintf(format, args...) printk(format , ## args)
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index cd5f6d758c68..84d401bfafad 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -22,6 +22,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables TCP MSS match module");
MODULE_ALIAS("ipt_tcpmss");
+MODULE_ALIAS("ip6t_tcpmss");
static bool
match(const struct sk_buff *skb,
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
new file mode 100644
index 000000000000..ef48bbd93573
--- /dev/null
+++ b/net/netfilter/xt_time.c
@@ -0,0 +1,269 @@
+/*
+ * xt_time
+ * Copyright © Jan Engelhardt <jengelh@computergmbh.de>, 2007
+ *
+ * based on ipt_time by Fabrice MARIE <fabrice@netfilter.org>
+ * This is a module which is used for time matching
+ * It is using some modified code from dietlibc (localtime() function)
+ * that you can find at http://www.fefe.de/dietlibc/
+ * This file is distributed under the terms of the GNU General Public
+ * License (GPL). Copies of the GPL can be obtained from gnu.org/gpl.
+ */
+#include <linux/ktime.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_time.h>
+
+struct xtm {
+ u_int8_t month; /* (1-12) */
+ u_int8_t monthday; /* (1-31) */
+ u_int8_t weekday; /* (1-7) */
+ u_int8_t hour; /* (0-23) */
+ u_int8_t minute; /* (0-59) */
+ u_int8_t second; /* (0-59) */
+ unsigned int dse;
+};
+
+extern struct timezone sys_tz; /* ouch */
+
+static const u_int16_t days_since_year[] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
+};
+
+static const u_int16_t days_since_leapyear[] = {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
+};
+
+/*
+ * Since time progresses forward, it is best to organize this array in reverse,
+ * to minimize lookup time.
+ */
+enum {
+ DSE_FIRST = 2039,
+};
+static const u_int16_t days_since_epoch[] = {
+ /* 2039 - 2030 */
+ 25202, 24837, 24472, 24106, 23741, 23376, 23011, 22645, 22280, 21915,
+ /* 2029 - 2020 */
+ 21550, 21184, 20819, 20454, 20089, 19723, 19358, 18993, 18628, 18262,
+ /* 2019 - 2010 */
+ 17897, 17532, 17167, 16801, 16436, 16071, 15706, 15340, 14975, 14610,
+ /* 2009 - 2000 */
+ 14245, 13879, 13514, 13149, 12784, 12418, 12053, 11688, 11323, 10957,
+ /* 1999 - 1990 */
+ 10592, 10227, 9862, 9496, 9131, 8766, 8401, 8035, 7670, 7305,
+ /* 1989 - 1980 */
+ 6940, 6574, 6209, 5844, 5479, 5113, 4748, 4383, 4018, 3652,
+ /* 1979 - 1970 */
+ 3287, 2922, 2557, 2191, 1826, 1461, 1096, 730, 365, 0,
+};
+
+static inline bool is_leap(unsigned int y)
+{
+ return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
+}
+
+/*
+ * Each network packet has a (nano)seconds-since-the-epoch (SSTE) timestamp.
+ * Since we match against days and daytime, the SSTE value needs to be
+ * computed back into human-readable dates.
+ *
+ * This is done in three separate functions so that the most expensive
+ * calculations are done last, in case a "simple match" can be found earlier.
+ */
+static inline unsigned int localtime_1(struct xtm *r, time_t time)
+{
+ unsigned int v, w;
+
+ /* Each day has 86400s, so finding the hour/minute is actually easy. */
+ v = time % 86400;
+ r->second = v % 60;
+ w = v / 60;
+ r->minute = w % 60;
+ r->hour = w / 60;
+ return v;
+}
+
+static inline void localtime_2(struct xtm *r, time_t time)
+{
+ /*
+ * Here comes the rest (weekday, monthday). First, divide the SSTE
+ * by seconds-per-day to get the number of _days_ since the epoch.
+ */
+ r->dse = time / 86400;
+
+ /* 1970-01-01 (w=0) was a Thursday (4). */
+ r->weekday = (4 + r->dse) % 7;
+}
+
+static void localtime_3(struct xtm *r, time_t time)
+{
+ unsigned int year, i, w = r->dse;
+
+ /*
+ * In each year, a certain number of days-since-the-epoch have passed.
+ * Find the year that is closest to said days.
+ *
+ * Consider, for example, w=21612 (2029-03-04). Loop will abort on
+ * dse[i] <= w, which happens when dse[i] == 21550. This implies
+ * year == 2009. w will then be 62.
+ */
+ for (i = 0, year = DSE_FIRST; days_since_epoch[i] > w;
+ ++i, --year)
+ /* just loop */;
+
+ w -= days_since_epoch[i];
+
+ /*
+ * By now we have the current year, and the day of the year.
+ * r->yearday = w;
+ *
+ * On to finding the month (like above). In each month, a certain
+ * number of days-since-New Year have passed, and find the closest
+ * one.
+ *
+ * Consider w=62 (in a non-leap year). Loop will abort on
+ * dsy[i] < w, which happens when dsy[i] == 31+28 (i == 2).
+ * Concludes i == 2, i.e. 3rd month => March.
+ *
+ * (A different approach to use would be to subtract a monthlength
+ * from w repeatedly while counting.)
+ */
+ if (is_leap(year)) {
+ for (i = ARRAY_SIZE(days_since_leapyear) - 1;
+ i > 0 && days_since_year[i] > w; --i)
+ /* just loop */;
+ } else {
+ for (i = ARRAY_SIZE(days_since_year) - 1;
+ i > 0 && days_since_year[i] > w; --i)
+ /* just loop */;
+ }
+
+ r->month = i + 1;
+ r->monthday = w - days_since_year[i] + 1;
+ return;
+}
+
+static bool xt_time_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
+{
+ const struct xt_time_info *info = matchinfo;
+ unsigned int packet_time;
+ struct xtm current_time;
+ s64 stamp;
+
+ /*
+ * We cannot use get_seconds() instead of __net_timestamp() here.
+ * Suppose you have two rules:
+ * 1. match before 13:00
+ * 2. match after 13:00
+ * If you match against processing time (get_seconds) it
+ * may happen that the same packet matches both rules if
+ * it arrived at the right moment before 13:00.
+ */
+ if (skb->tstamp.tv64 == 0)
+ __net_timestamp((struct sk_buff *)skb);
+
+ stamp = skb->tstamp.tv64;
+ do_div(stamp, NSEC_PER_SEC);
+
+ if (info->flags & XT_TIME_LOCAL_TZ)
+ /* Adjust for local timezone */
+ stamp -= 60 * sys_tz.tz_minuteswest;
+
+ /*
+ * xt_time will match when _all_ of the following hold:
+ * - 'now' is in the global time range date_start..date_end
+ * - 'now' is in the monthday mask
+ * - 'now' is in the weekday mask
+ * - 'now' is in the daytime range time_start..time_end
+ * (and by default, libxt_time will set these so as to match)
+ */
+
+ if (stamp < info->date_start || stamp > info->date_stop)
+ return false;
+
+ packet_time = localtime_1(&current_time, stamp);
+
+ if (info->daytime_start < info->daytime_stop) {
+ if (packet_time < info->daytime_start ||
+ packet_time > info->daytime_stop)
+ return false;
+ } else {
+ if (packet_time < info->daytime_start &&
+ packet_time > info->daytime_stop)
+ return false;
+ }
+
+ localtime_2(&current_time, stamp);
+
+ if (!(info->weekdays_match & (1 << current_time.weekday)))
+ return false;
+
+ /* Do not spend time computing monthday if all days match anyway */
+ if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) {
+ localtime_3(&current_time, stamp);
+ if (!(info->monthdays_match & (1 << current_time.monthday)))
+ return false;
+ }
+
+ return true;
+}
+
+static bool xt_time_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
+{
+ struct xt_time_info *info = matchinfo;
+
+ if (info->daytime_start > XT_TIME_MAX_DAYTIME ||
+ info->daytime_stop > XT_TIME_MAX_DAYTIME) {
+ printk(KERN_WARNING "xt_time: invalid argument - start or "
+ "stop time greater than 23:59:59\n");
+ return false;
+ }
+
+ return true;
+}
+
+static struct xt_match xt_time_reg[] __read_mostly = {
+ {
+ .name = "time",
+ .family = AF_INET,
+ .match = xt_time_match,
+ .matchsize = sizeof(struct xt_time_info),
+ .checkentry = xt_time_check,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "time",
+ .family = AF_INET6,
+ .match = xt_time_match,
+ .matchsize = sizeof(struct xt_time_info),
+ .checkentry = xt_time_check,
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_time_init(void)
+{
+ return xt_register_matches(xt_time_reg, ARRAY_SIZE(xt_time_reg));
+}
+
+static void __exit xt_time_exit(void)
+{
+ xt_unregister_matches(xt_time_reg, ARRAY_SIZE(xt_time_reg));
+}
+
+module_init(xt_time_init);
+module_exit(xt_time_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
+MODULE_DESCRIPTION("netfilter time match");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_time");
+MODULE_ALIAS("ip6t_time");