summaryrefslogtreecommitdiff
path: root/net/netfilter
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig23
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/core.c24
-rw-r--r--net/netfilter/nf_conntrack_core.c211
-rw-r--r--net/netfilter/nf_conntrack_ftp.c98
-rw-r--r--net/netfilter/nf_conntrack_netlink.c80
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c14
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c31
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c7
-rw-r--r--net/netfilter/nf_conntrack_standalone.c3
-rw-r--r--net/netfilter/nf_internals.h2
-rw-r--r--net/netfilter/nf_queue.c80
-rw-r--r--net/netfilter/nfnetlink_queue.c10
-rw-r--r--net/netfilter/x_tables.c269
-rw-r--r--net/netfilter/xt_CLASSIFY.c63
-rw-r--r--net/netfilter/xt_CONNMARK.c148
-rw-r--r--net/netfilter/xt_CONNSECMARK.c61
-rw-r--r--net/netfilter/xt_DSCP.c118
-rw-r--r--net/netfilter/xt_MARK.c120
-rw-r--r--net/netfilter/xt_NFQUEUE.c71
-rw-r--r--net/netfilter/xt_NOTRACK.c50
-rw-r--r--net/netfilter/xt_SECMARK.c59
-rw-r--r--net/netfilter/xt_comment.c45
-rw-r--r--net/netfilter/xt_connbytes.c48
-rw-r--r--net/netfilter/xt_connmark.c88
-rw-r--r--net/netfilter/xt_conntrack.c185
-rw-r--r--net/netfilter/xt_dccp.c52
-rw-r--r--net/netfilter/xt_dscp.c103
-rw-r--r--net/netfilter/xt_esp.c52
-rw-r--r--net/netfilter/xt_helper.c55
-rw-r--r--net/netfilter/xt_length.c43
-rw-r--r--net/netfilter/xt_limit.c111
-rw-r--r--net/netfilter/xt_mac.c52
-rw-r--r--net/netfilter/xt_mark.c80
-rw-r--r--net/netfilter/xt_multiport.c115
-rw-r--r--net/netfilter/xt_physdev.c50
-rw-r--r--net/netfilter/xt_pkttype.c44
-rw-r--r--net/netfilter/xt_policy.c52
-rw-r--r--net/netfilter/xt_quota.c53
-rw-r--r--net/netfilter/xt_sctp.c52
-rw-r--r--net/netfilter/xt_state.c56
-rw-r--r--net/netfilter/xt_statistic.c55
-rw-r--r--net/netfilter/xt_string.c54
-rw-r--r--net/netfilter/xt_tcpmss.c97
-rw-r--r--net/netfilter/xt_tcpudp.c109
46 files changed, 1663 insertions, 1534 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index a9894ddfd72..0a28d2c5c44 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -148,6 +148,18 @@ config NETFILTER_XT_TARGET_CONNMARK
<file:Documentation/modules.txt>. The module will be called
ipt_CONNMARK.o. If unsure, say `N'.
+config NETFILTER_XT_TARGET_DSCP
+ tristate '"DSCP" target support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_MANGLE || IP6_NF_MANGLE
+ help
+ This option adds a `DSCP' target, which allows you to manipulate
+ the IPv4/IPv6 header DSCP field (differentiated services codepoint).
+
+ The DSCP field can have any value between 0x0 and 0x3f inclusive.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_MARK
tristate '"MARK" target support'
depends on NETFILTER_XTABLES
@@ -263,6 +275,17 @@ config NETFILTER_XT_MATCH_DCCP
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_DSCP
+ tristate '"DSCP" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `DSCP' match, which allows you to match against
+ the IPv4/IPv6 header DSCP field (differentiated services codepoint).
+
+ The DSCP field can have any value between 0x0 and 0x3f inclusive.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_ESP
tristate '"ESP" match support'
depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 6fa4b758045..a74be492fd0 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
# targets
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
@@ -37,6 +38,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 5d29d5e2362..d80b935b3a9 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -182,7 +182,7 @@ next_hook:
ret = -EPERM;
} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
NFDEBUG("nf_hook: Verdict = QUEUE.\n");
- if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn,
+ if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn,
verdict >> NF_VERDICT_BITS))
goto next_hook;
}
@@ -222,6 +222,28 @@ copy_skb:
}
EXPORT_SYMBOL(skb_make_writable);
+u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum)
+{
+ u_int32_t diff[] = { oldval, newval };
+
+ return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum));
+}
+EXPORT_SYMBOL(nf_csum_update);
+
+u_int16_t nf_proto_csum_update(struct sk_buff *skb,
+ u_int32_t oldval, u_int32_t newval,
+ u_int16_t csum, int pseudohdr)
+{
+ if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ csum = nf_csum_update(oldval, newval, csum);
+ if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
+ skb->csum = nf_csum_update(oldval, newval, skb->csum);
+ } else if (pseudohdr)
+ csum = ~nf_csum_update(oldval, newval, ~csum);
+
+ return csum;
+}
+EXPORT_SYMBOL(nf_proto_csum_update);
/* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, and hence
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8f2261965a6..093b3ddc513 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -57,7 +57,6 @@
#include <net/netfilter/nf_conntrack_protocol.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h>
-#include <linux/netfilter_ipv4/listhelp.h>
#define NF_CONNTRACK_VERSION "0.5.0"
@@ -74,17 +73,17 @@ atomic_t nf_conntrack_count = ATOMIC_INIT(0);
void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
LIST_HEAD(nf_conntrack_expect_list);
-struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
-struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX];
+struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
+struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
static LIST_HEAD(helpers);
-unsigned int nf_conntrack_htable_size = 0;
-int nf_conntrack_max;
-struct list_head *nf_conntrack_hash;
-static kmem_cache_t *nf_conntrack_expect_cachep;
+unsigned int nf_conntrack_htable_size __read_mostly = 0;
+int nf_conntrack_max __read_mostly;
+struct list_head *nf_conntrack_hash __read_mostly;
+static kmem_cache_t *nf_conntrack_expect_cachep __read_mostly;
struct nf_conn nf_conntrack_untracked;
-unsigned int nf_ct_log_invalid;
+unsigned int nf_ct_log_invalid __read_mostly;
static LIST_HEAD(unconfirmed);
-static int nf_conntrack_vmalloc;
+static int nf_conntrack_vmalloc __read_mostly;
static unsigned int nf_conntrack_next_id;
static unsigned int nf_conntrack_expect_next_id;
@@ -539,15 +538,10 @@ void nf_ct_remove_expectations(struct nf_conn *ct)
static void
clean_from_lists(struct nf_conn *ct)
{
- unsigned int ho, hr;
-
DEBUGP("clean_from_lists(%p)\n", ct);
ASSERT_WRITE_LOCK(&nf_conntrack_lock);
-
- ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
- hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- LIST_DELETE(&nf_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
- LIST_DELETE(&nf_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
+ list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+ list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
/* Destroy all pending expectations */
nf_ct_remove_expectations(ct);
@@ -617,16 +611,6 @@ static void death_by_timeout(unsigned long ul_conntrack)
nf_ct_put(ct);
}
-static inline int
-conntrack_tuple_cmp(const struct nf_conntrack_tuple_hash *i,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conn *ignored_conntrack)
-{
- ASSERT_READ_LOCK(&nf_conntrack_lock);
- return nf_ct_tuplehash_to_ctrack(i) != ignored_conntrack
- && nf_ct_tuple_equal(tuple, &i->tuple);
-}
-
struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack)
@@ -636,7 +620,8 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
ASSERT_READ_LOCK(&nf_conntrack_lock);
list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
- if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
+ if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
+ nf_ct_tuple_equal(tuple, &h->tuple)) {
NF_CT_STAT_INC(found);
return h;
}
@@ -667,10 +652,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
unsigned int repl_hash)
{
ct->id = ++nf_conntrack_next_id;
- list_prepend(&nf_conntrack_hash[hash],
- &ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
- list_prepend(&nf_conntrack_hash[repl_hash],
- &ct->tuplehash[IP_CT_DIR_REPLY].list);
+ list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
+ &nf_conntrack_hash[hash]);
+ list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
+ &nf_conntrack_hash[repl_hash]);
}
void nf_conntrack_hash_insert(struct nf_conn *ct)
@@ -690,7 +675,9 @@ int
__nf_conntrack_confirm(struct sk_buff **pskb)
{
unsigned int hash, repl_hash;
+ struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
+ struct nf_conn_help *help;
enum ip_conntrack_info ctinfo;
ct = nf_ct_get(*pskb, &ctinfo);
@@ -720,41 +707,41 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
/* See if there's one in the list already, including reverse:
NAT could have grabbed it without realizing, since we're
not in the hash. If there is, we lost race. */
- if (!LIST_FIND(&nf_conntrack_hash[hash],
- conntrack_tuple_cmp,
- struct nf_conntrack_tuple_hash *,
- &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL)
- && !LIST_FIND(&nf_conntrack_hash[repl_hash],
- conntrack_tuple_cmp,
- struct nf_conntrack_tuple_hash *,
- &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) {
- struct nf_conn_help *help;
- /* Remove from unconfirmed list */
- list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+ list_for_each_entry(h, &nf_conntrack_hash[hash], list)
+ if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+ &h->tuple))
+ goto out;
+ list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list)
+ if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
+ &h->tuple))
+ goto out;
- __nf_conntrack_hash_insert(ct, hash, repl_hash);
- /* Timer relative to confirmation time, not original
- setting time, otherwise we'd get timer wrap in
- weird delay cases. */
- ct->timeout.expires += jiffies;
- add_timer(&ct->timeout);
- atomic_inc(&ct->ct_general.use);
- set_bit(IPS_CONFIRMED_BIT, &ct->status);
- NF_CT_STAT_INC(insert);
- write_unlock_bh(&nf_conntrack_lock);
- help = nfct_help(ct);
- if (help && help->helper)
- nf_conntrack_event_cache(IPCT_HELPER, *pskb);
+ /* Remove from unconfirmed list */
+ list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+
+ __nf_conntrack_hash_insert(ct, hash, repl_hash);
+ /* Timer relative to confirmation time, not original
+ setting time, otherwise we'd get timer wrap in
+ weird delay cases. */
+ ct->timeout.expires += jiffies;
+ add_timer(&ct->timeout);
+ atomic_inc(&ct->ct_general.use);
+ set_bit(IPS_CONFIRMED_BIT, &ct->status);
+ NF_CT_STAT_INC(insert);
+ write_unlock_bh(&nf_conntrack_lock);
+ help = nfct_help(ct);
+ if (help && help->helper)
+ nf_conntrack_event_cache(IPCT_HELPER, *pskb);
#ifdef CONFIG_NF_NAT_NEEDED
- if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
- test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
- nf_conntrack_event_cache(IPCT_NATINFO, *pskb);
+ if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
+ test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
+ nf_conntrack_event_cache(IPCT_NATINFO, *pskb);
#endif
- nf_conntrack_event_cache(master_ct(ct) ?
- IPCT_RELATED : IPCT_NEW, *pskb);
- return NF_ACCEPT;
- }
+ nf_conntrack_event_cache(master_ct(ct) ?
+ IPCT_RELATED : IPCT_NEW, *pskb);
+ return NF_ACCEPT;
+out:
NF_CT_STAT_INC(insert_failed);
write_unlock_bh(&nf_conntrack_lock);
return NF_DROP;
@@ -777,24 +764,21 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
/* There's a small race here where we may free a just-assured
connection. Too bad: we're in trouble anyway. */
-static inline int unreplied(const struct nf_conntrack_tuple_hash *i)
-{
- return !(test_bit(IPS_ASSURED_BIT,
- &nf_ct_tuplehash_to_ctrack(i)->status));
-}
-
static int early_drop(struct list_head *chain)
{
/* Traverse backwards: gives us oldest, which is roughly LRU */
struct nf_conntrack_tuple_hash *h;
- struct nf_conn *ct = NULL;
+ struct nf_conn *ct = NULL, *tmp;
int dropped = 0;
read_lock_bh(&nf_conntrack_lock);
- h = LIST_FIND_B(chain, unreplied, struct nf_conntrack_tuple_hash *);
- if (h) {
- ct = nf_ct_tuplehash_to_ctrack(h);
- atomic_inc(&ct->ct_general.use);
+ list_for_each_entry_reverse(h, chain, list) {
+ tmp = nf_ct_tuplehash_to_ctrack(h);
+ if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
+ ct = tmp;
+ atomic_inc(&ct->ct_general.use);
+ break;
+ }
}
read_unlock_bh(&nf_conntrack_lock);
@@ -810,18 +794,16 @@ static int early_drop(struct list_head *chain)
return dropped;
}
-static inline int helper_cmp(const struct nf_conntrack_helper *i,
- const struct nf_conntrack_tuple *rtuple)
-{
- return nf_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
-}
-
static struct nf_conntrack_helper *
__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
{
- return LIST_FIND(&helpers, helper_cmp,
- struct nf_conntrack_helper *,
- tuple);
+ struct nf_conntrack_helper *h;
+
+ list_for_each_entry(h, &helpers, list) {
+ if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
+ return h;
+ }
+ return NULL;
}
struct nf_conntrack_helper *
@@ -866,11 +848,15 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
nf_conntrack_hash_rnd_initted = 1;
}
+ /* We don't want any race condition at early drop stage */
+ atomic_inc(&nf_conntrack_count);
+
if (nf_conntrack_max
- && atomic_read(&nf_conntrack_count) >= nf_conntrack_max) {
+ && atomic_read(&nf_conntrack_count) > nf_conntrack_max) {
unsigned int hash = hash_conntrack(orig);
/* Try dropping from this hash chain. */
if (!early_drop(&nf_conntrack_hash[hash])) {
+ atomic_dec(&nf_conntrack_count);
if (net_ratelimit())
printk(KERN_WARNING
"nf_conntrack: table full, dropping"
@@ -921,10 +907,12 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
init_timer(&conntrack->timeout);
conntrack->timeout.data = (unsigned long)conntrack;
conntrack->timeout.function = death_by_timeout;
+ read_unlock_bh(&nf_ct_cache_lock);
- atomic_inc(&nf_conntrack_count);
+ return conntrack;
out:
read_unlock_bh(&nf_ct_cache_lock);
+ atomic_dec(&nf_conntrack_count);
return conntrack;
}
@@ -1323,7 +1311,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
return ret;
}
write_lock_bh(&nf_conntrack_lock);
- list_prepend(&helpers, me);
+ list_add(&me->list, &helpers);
write_unlock_bh(&nf_conntrack_lock);
return 0;
@@ -1342,8 +1330,8 @@ __nf_conntrack_helper_find_byname(const char *name)
return NULL;
}
-static inline int unhelp(struct nf_conntrack_tuple_hash *i,
- const struct nf_conntrack_helper *me)
+static inline void unhelp(struct nf_conntrack_tuple_hash *i,
+ const struct nf_conntrack_helper *me)
{
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
struct nf_conn_help *help = nfct_help(ct);
@@ -1352,17 +1340,17 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
nf_conntrack_event(IPCT_HELPER, ct);
help->helper = NULL;
}
- return 0;
}
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
{
unsigned int i;
+ struct nf_conntrack_tuple_hash *h;
struct nf_conntrack_expect *exp, *tmp;
/* Need write lock here, to delete helper. */
write_lock_bh(&nf_conntrack_lock);
- LIST_DELETE(&helpers, me);
+ list_del(&me->list);
/* Get rid of expectations */
list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
@@ -1374,10 +1362,12 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
}
/* Get rid of expecteds, set helpers to NULL. */
- LIST_FIND_W(&unconfirmed, unhelp, struct nf_conntrack_tuple_hash*, me);
- for (i = 0; i < nf_conntrack_htable_size; i++)
- LIST_FIND_W(&nf_conntrack_hash[i], unhelp,
- struct nf_conntrack_tuple_hash *, me);
+ list_for_each_entry(h, &unconfirmed, list)
+ unhelp(h, me);
+ for (i = 0; i < nf_conntrack_htable_size; i++) {
+ list_for_each_entry(h, &nf_conntrack_hash[i], list)
+ unhelp(h, me);
+ }
write_unlock_bh(&nf_conntrack_lock);
/* Someone could be still looking at the helper in a bh. */
@@ -1510,37 +1500,40 @@ do_iter(const struct nf_conntrack_tuple_hash *i,
}
/* Bring out ya dead! */
-static struct nf_conntrack_tuple_hash *
+static struct nf_conn *
get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
void *data, unsigned int *bucket)
{
- struct nf_conntrack_tuple_hash *h = NULL;
+ struct nf_conntrack_tuple_hash *h;
+ struct nf_conn *ct;
write_lock_bh(&nf_conntrack_lock);
for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
- h = LIST_FIND_W(&nf_conntrack_hash[*bucket], do_iter,
- struct nf_conntrack_tuple_hash *, iter, data);
- if (h)
- break;
+ list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) {
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (iter(ct, data))
+ goto found;
+ }
}
- if (!h)
- h = LIST_FIND_W(&unconfirmed, do_iter,
- struct nf_conntrack_tuple_hash *, iter, data);
- if (h)
- atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
+ list_for_each_entry(h, &unconfirmed, list) {
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (iter(ct, data))
+ goto found;
+ }
+ return NULL;
+found:
+ atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
write_unlock_bh(&nf_conntrack_lock);
-
- return h;
+ return ct;
}
void
nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data)
{
- struct nf_conntrack_tuple_hash *h;
+ struct nf_conn *ct;
unsigned int bucket = 0;
- while ((h = get_next_corpse(iter, data, &bucket)) != NULL) {
- struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+ while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) {
/* Time to push up daises... */
if (del_timer(&ct->timeout))
death_by_timeout((unsigned long)ct);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 960972d225f..0c17a5bd112 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -21,6 +21,7 @@
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/ctype.h>
+#include <linux/inet.h>
#include <net/checksum.h>
#include <net/tcp.h>
@@ -111,101 +112,14 @@ static struct ftp_search {
},
};
-/* This code is based on inet_pton() in glibc-2.2.4 */
static int
get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term)
{
- static const char xdigits[] = "0123456789abcdef";
- u_int8_t tmp[16], *tp, *endp, *colonp;
- int ch, saw_xdigit;
- u_int32_t val;
- size_t clen = 0;
-
- tp = memset(tmp, '\0', sizeof(tmp));
- endp = tp + sizeof(tmp);
- colonp = NULL;
-
- /* Leading :: requires some special handling. */
- if (*src == ':'){
- if (*++src != ':') {
- DEBUGP("invalid \":\" at the head of addr\n");
- return 0;
- }
- clen++;
- }
-
- saw_xdigit = 0;
- val = 0;
- while ((clen < dlen) && (*src != term)) {
- const char *pch;
-
- ch = tolower(*src++);
- clen++;
-
- pch = strchr(xdigits, ch);
- if (pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if (val > 0xffff)
- return 0;
-
- saw_xdigit = 1;
- continue;
- }
- if (ch != ':') {
- DEBUGP("get_ipv6_addr: invalid char. \'%c\'\n", ch);
- return 0;
- }
-
- if (!saw_xdigit) {
- if (colonp) {
- DEBUGP("invalid location of \"::\".\n");
- return 0;
- }
- colonp = tp;
- continue;
- } else if (*src == term) {
- DEBUGP("trancated IPv6 addr\n");
- return 0;
- }
-
- if (tp + 2 > endp)
- return 0;
- *tp++ = (u_int8_t) (val >> 8) & 0xff;
- *tp++ = (u_int8_t) val & 0xff;
-
- saw_xdigit = 0;
- val = 0;
- continue;
- }
- if (saw_xdigit) {
- if (tp + 2 > endp)
- return 0;
- *tp++ = (u_int8_t) (val >> 8) & 0xff;
- *tp++ = (u_int8_t) val & 0xff;
- }
- if (colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const int n = tp - colonp;
- int i;
-
- if (tp == endp)
- return 0;
-
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
- }
- tp = endp;
- }
- if (tp != endp || (*src != term))
- return 0;
-
- memcpy(dst->s6_addr, tmp, sizeof(dst->s6_addr));
- return clen;
+ const char *end;
+ int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), (u8 *)dst, term, &end);
+ if (ret > 0)
+ return (int)(end - src);
+ return 0;
}
static int try_number(const char *data, size_t dlen, u_int32_t array[],
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 6527d4e048d..1721f7c78c7 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -339,11 +339,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
/* dump everything */
events = ~0UL;
group = NFNLGRP_CONNTRACK_NEW;
- } else if (events & (IPCT_STATUS |
- IPCT_PROTOINFO |
- IPCT_HELPER |
- IPCT_HELPINFO |
- IPCT_NATINFO)) {
+ } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
type = IPCTNL_MSG_CT_NEW;
group = NFNLGRP_CONNTRACK_UPDATE;
} else
@@ -395,6 +391,10 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
goto nfattr_failure;
+ if (events & IPCT_MARK
+ && ctnetlink_dump_mark(skb, ct) < 0)
+ goto nfattr_failure;
+
nlh->nlmsg_len = skb->tail - b;
nfnetlink_send(skb, 0, group, 0);
return NOTIFY_DONE;
@@ -455,6 +455,11 @@ restart:
cb->args[1] = (unsigned long)ct;
goto out;
}
+#ifdef CONFIG_NF_CT_ACCT
+ if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
+ IPCTNL_MSG_CT_GET_CTRZERO)
+ memset(&ct->counters, 0, sizeof(ct->counters));
+#endif
}
if (cb->args[1]) {
cb->args[1] = 0;
@@ -470,50 +475,6 @@ out:
return skb->len;
}
-#ifdef CONFIG_NF_CT_ACCT
-static int
-ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb)
-{
- struct nf_conn *ct = NULL;
- struct nf_conntrack_tuple_hash *h;
- struct list_head *i;
- u_int32_t *id = (u_int32_t *) &cb->args[1];
- struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
- u_int8_t l3proto = nfmsg->nfgen_family;
-
- DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__,
- cb->args[0], *id);
-
- write_lock_bh(&nf_conntrack_lock);
- for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++, *id = 0) {
- list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
- h = (struct nf_conntrack_tuple_hash *) i;
- if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
- continue;
- ct = nf_ct_tuplehash_to_ctrack(h);
- if (l3proto && L3PROTO(ct) != l3proto)
- continue;
- if (ct->id <= *id)
- continue;
- if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- IPCTNL_MSG_CT_NEW,
- 1, ct) < 0)
- goto out;
- *id = ct->id;
-
- memset(&ct->counters, 0, sizeof(ct->counters));
- }
- }
-out:
- write_unlock_bh(&nf_conntrack_lock);
-
- DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
-
- return skb->len;
-}
-#endif
-
static inline int
ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple)
{
@@ -788,22 +749,14 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (nlh->nlmsg_flags & NLM_F_DUMP) {
u32 rlen;
- if (NFNL_MSG_TYPE(nlh->nlmsg_type) ==
- IPCTNL_MSG_CT_GET_CTRZERO) {
-#ifdef CONFIG_NF_CT_ACCT
- if ((*errp = netlink_dump_start(ctnl, skb, nlh,
- ctnetlink_dump_table_w,
- ctnetlink_done)) != 0)
- return -EINVAL;
-#else
+#ifndef CONFIG_NF_CT_ACCT
+ if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
return -ENOTSUPP;
#endif
- } else {
- if ((*errp = netlink_dump_start(ctnl, skb, nlh,
- ctnetlink_dump_table,
- ctnetlink_done)) != 0)
+ if ((*errp = netlink_dump_start(ctnl, skb, nlh,
+ ctnetlink_dump_table,
+ ctnetlink_done)) != 0)
return -EINVAL;
- }
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
@@ -1274,6 +1227,9 @@ static int ctnetlink_expect_event(struct notifier_block *this,
} else
return NOTIFY_DONE;
+ if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW))
+ return NOTIFY_DONE;
+
skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
if (!skb)
return NOTIFY_DONE;
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 46bc27e2756..26408bb0955 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -17,7 +17,7 @@
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack_protocol.h>
-unsigned int nf_ct_generic_timeout = 600*HZ;
+unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
static int generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 9bd8a7877fd..af568777372 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -64,13 +64,13 @@ static const char *sctp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-static unsigned int nf_ct_sctp_timeout_closed = 10 SECS;
-static unsigned int nf_ct_sctp_timeout_cookie_wait = 3 SECS;
-static unsigned int nf_ct_sctp_timeout_cookie_echoed = 3 SECS;
-static unsigned int nf_ct_sctp_timeout_established = 5 DAYS;
-static unsigned int nf_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
-static unsigned int nf_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
-static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
+static unsigned int nf_ct_sctp_timeout_closed __read_mostly = 10 SECS;
+static unsigned int nf_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS;
+static unsigned int nf_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS;
+static unsigned int nf_ct_sctp_timeout_established __read_mostly = 5 DAYS;
+static unsigned int nf_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000;
+static unsigned int nf_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000;
+static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS;
static unsigned int * sctp_timeouts[]
= { NULL, /* SCTP_CONNTRACK_NONE */
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index af8adcba23a..238bbb5b72e 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -57,19 +57,19 @@ static DEFINE_RWLOCK(tcp_lock);
/* "Be conservative in what you do,
be liberal in what you accept from others."
If it's non-zero, we mark only out of window RST segments as INVALID. */
-int nf_ct_tcp_be_liberal = 0;
+int nf_ct_tcp_be_liberal __read_mostly = 0;
/* When connection is picked up from the middle, how many packets are required
to pass in each direction when we assume we are in sync - if any side uses
window scaling, we lost the game.
If it is set to zero, we disable picking up already established
connections. */
-int nf_ct_tcp_loose = 3;
+int nf_ct_tcp_loose __read_mostly = 3;
/* Max number of the retransmitted packets without receiving an (acceptable)
ACK from the destination. If this number is reached, a shorter timer
will be started. */
-int nf_ct_tcp_max_retrans = 3;
+int nf_ct_tcp_max_retrans __read_mostly = 3;
/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
closely. They're more complex. --RR */
@@ -92,19 +92,19 @@ static const char *tcp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-unsigned int nf_ct_tcp_timeout_syn_sent = 2 MINS;
-unsigned int nf_ct_tcp_timeout_syn_recv = 60 SECS;
-unsigned int nf_ct_tcp_timeout_established = 5 DAYS;
-unsigned int nf_ct_tcp_timeout_fin_wait = 2 MINS;
-unsigned int nf_ct_tcp_timeout_close_wait = 60 SECS;
-unsigned int nf_ct_tcp_timeout_last_ack = 30 SECS;
-unsigned int nf_ct_tcp_timeout_time_wait = 2 MINS;
-unsigned int nf_ct_tcp_timeout_close = 10 SECS;
+unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS;
+unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS;
+unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS;
+unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS;
+unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS;
+unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS;
+unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS;
+unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS;
/* RFC1122 says the R2 limit should be at least 100 seconds.
Linux uses 15 packets as limit, which corresponds
to ~13-30min depending on RTO. */
-unsigned int nf_ct_tcp_timeout_max_retrans = 5 MINS;
+unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS;
static unsigned int * tcp_timeouts[]
= { NULL, /* TCP_CONNTRACK_NONE */
@@ -688,13 +688,15 @@ static int tcp_in_window(struct ip_ct_tcp *state,
if (state->last_dir == dir
&& state->last_seq == seq
&& state->last_ack == ack
- && state->last_end == end)
+ && state->last_end == end
+ && state->last_win == win)
state->retrans++;
else {
state->last_dir = dir;
state->last_seq = seq;
state->last_ack = ack;
state->last_end = end;
+ state->last_win = win;
state->retrans = 0;
}
}
@@ -823,8 +825,7 @@ static int tcp_error(struct sk_buff *skb,
/* Checksum invalid? Ignore.
* We skip checking packets on the outgoing path
- * because the semantic of CHECKSUM_HW is different there
- * and moreover root might send raw packets.
+ * because the checksum is assumed to be correct.
*/
/* FIXME: Source route IP option packets --RR */
if (nf_conntrack_checksum &&
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index ae07ebe3ab3..d28981cf9af 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -27,8 +27,8 @@
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack_protocol.h>
-unsigned int nf_ct_udp_timeout = 30*HZ;
-unsigned int nf_ct_udp_timeout_stream = 180*HZ;
+unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
+unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
static int udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
@@ -131,8 +131,7 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
/* Checksum invalid? Ignore.
* We skip checking packets on the outgoing path
- * because the semantic of CHECKSUM_HW is different there
- * and moreover root might send raw packets.
+ * because the checksum is assumed to be correct.
* FIXME: Source route IP option packets --RR */
if (nf_conntrack_checksum &&
((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 4ef83669996..5954f677381 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -37,7 +37,6 @@
#include <net/netfilter/nf_conntrack_protocol.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_helper.h>
-#include <linux/netfilter_ipv4/listhelp.h>
#if 0
#define DEBUGP printk
@@ -428,7 +427,7 @@ static struct file_operations ct_cpu_seq_fops = {
/* Sysctl support */
-int nf_conntrack_checksum = 1;
+int nf_conntrack_checksum __read_mostly = 1;
#ifdef CONFIG_SYSCTL
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index 86e392bfe83..a981971ce1d 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -23,7 +23,7 @@ extern unsigned int nf_iterate(struct list_head *head,
int hook_thresh);
/* nf_queue.c */
-extern int nf_queue(struct sk_buff **skb,
+extern int nf_queue(struct sk_buff *skb,
struct list_head *elem,
int pf, unsigned int hook,
struct net_device *indev,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 662a869593b..4d8936ed581 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -74,13 +74,13 @@ EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
* Any packet that leaves via this function must come back
* through nf_reinject().
*/
-int nf_queue(struct sk_buff **skb,
- struct list_head *elem,
- int pf, unsigned int hook,
- struct net_device *indev,
- struct net_device *outdev,
- int (*okfn)(struct sk_buff *),
- unsigned int queuenum)
+static int __nf_queue(struct sk_buff *skb,
+ struct list_head *elem,
+ int pf, unsigned int hook,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *),
+ unsigned int queuenum)
{
int status;
struct nf_info *info;
@@ -94,14 +94,14 @@ int nf_queue(struct sk_buff **skb,
read_lock(&queue_handler_lock);
if (!queue_handler[pf]) {
read_unlock(&queue_handler_lock);
- kfree_skb(*skb);
+ kfree_skb(skb);
return 1;
}
afinfo = nf_get_afinfo(pf);
if (!afinfo) {
read_unlock(&queue_handler_lock);
- kfree_skb(*skb);
+ kfree_skb(skb);
return 1;
}
@@ -109,9 +109,9 @@ int nf_queue(struct sk_buff **skb,
if (!info) {
if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n",
- *skb);
+ skb);
read_unlock(&queue_handler_lock);
- kfree_skb(*skb);
+ kfree_skb(skb);
return 1;
}
@@ -130,15 +130,15 @@ int nf_queue(struct sk_buff **skb,
if (outdev) dev_hold(outdev);
#ifdef CONFIG_BRIDGE_NETFILTER
- if ((*skb)->nf_bridge) {
- physindev = (*skb)->nf_bridge->physindev;
+ if (skb->nf_bridge) {
+ physindev = skb->nf_bridge->physindev;
if (physindev) dev_hold(physindev);
- physoutdev = (*skb)->nf_bridge->physoutdev;
+ physoutdev = skb->nf_bridge->physoutdev;
if (physoutdev) dev_hold(physoutdev);
}
#endif
- afinfo->saveroute(*skb, info);
- status = queue_handler[pf]->outfn(*skb, info, queuenum,
+ afinfo->saveroute(skb, info);
+ status = queue_handler[pf]->outfn(skb, info, queuenum,
queue_handler[pf]->data);
read_unlock(&queue_handler_lock);
@@ -153,7 +153,7 @@ int nf_queue(struct sk_buff **skb,
#endif
module_put(info->elem->owner);
kfree(info);
- kfree_skb(*skb);
+ kfree_skb(skb);
return 1;
}
@@ -161,6 +161,46 @@ int nf_queue(struct sk_buff **skb,
return 1;
}
+int nf_queue(struct sk_buff *skb,
+ struct list_head *elem,
+ int pf, unsigned int hook,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *),
+ unsigned int queuenum)
+{
+ struct sk_buff *segs;
+
+ if (!skb_is_gso(skb))
+ return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
+ queuenum);
+
+ switch (pf) {
+ case AF_INET:
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case AF_INET6:
+ skb->protocol = htons(ETH_P_IPV6);
+ break;
+ }
+
+ segs = skb_gso_segment(skb, 0);
+ kfree_skb(skb);
+ if (unlikely(IS_ERR(segs)))
+ return 1;
+
+ do {
+ struct sk_buff *nskb = segs->next;
+
+ segs->next = NULL;
+ if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn,
+ queuenum))
+ kfree_skb(segs);
+ segs = nskb;
+ } while (segs);
+ return 1;
+}
+
void nf_reinject(struct sk_buff *skb, struct nf_info *info,
unsigned int verdict)
{
@@ -224,9 +264,9 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
case NF_STOLEN:
break;
case NF_QUEUE:
- if (!nf_queue(&skb, elem, info->pf, info->hook,
- info->indev, info->outdev, info->okfn,
- verdict >> NF_VERDICT_BITS))
+ if (!__nf_queue(skb, elem, info->pf, info->hook,
+ info->indev, info->outdev, info->okfn,
+ verdict >> NF_VERDICT_BITS))
goto next_hook;
break;
default:
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 49ef41e34c4..8eb2473d83e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -377,9 +377,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
break;
case NFQNL_COPY_PACKET:
- if (entskb->ip_summed == CHECKSUM_HW &&
- (*errp = skb_checksum_help(entskb,
- outdev == NULL))) {
+ if ((entskb->ip_summed == CHECKSUM_PARTIAL ||
+ entskb->ip_summed == CHECKSUM_COMPLETE) &&
+ (*errp = skb_checksum_help(entskb))) {
spin_unlock_bh(&queue->lock);
return NULL;
}
@@ -584,7 +584,7 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
queue->queue_dropped++;
status = -ENOSPC;
if (net_ratelimit())
- printk(KERN_WARNING "ip_queue: full at %d entries, "
+ printk(KERN_WARNING "nf_queue: full at %d entries, "
"dropping packets(s). Dropped: %d\n",
queue->queue_total, queue->queue_dropped);
goto err_out_free_nskb;
@@ -635,7 +635,7 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
diff,
GFP_ATOMIC);
if (newskb == NULL) {
- printk(KERN_WARNING "ip_queue: OOM "
+ printk(KERN_WARNING "nf_queue: OOM "
"in mangle, dropping packet\n");
return -ENOMEM;
}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 174e8f97009..58522fc65d3 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -81,12 +81,42 @@ xt_unregister_target(struct xt_target *target)
int af = target->family;
mutex_lock(&xt[af].mutex);
- LIST_DELETE(&xt[af].target, target);
+ list_del(&target->list);
mutex_unlock(&xt[af].mutex);
}
EXPORT_SYMBOL(xt_unregister_target);
int
+xt_register_targets(struct xt_target *target, unsigned int n)
+{
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; i < n; i++) {
+ err = xt_register_target(&target[i]);
+ if (err)
+ goto err;
+ }
+ return err;
+
+err:
+ if (i > 0)
+ xt_unregister_targets(target, i);
+ return err;
+}
+EXPORT_SYMBOL(xt_register_targets);
+
+void
+xt_unregister_targets(struct xt_target *target, unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ xt_unregister_target(&target[i]);
+}
+EXPORT_SYMBOL(xt_unregister_targets);
+
+int
xt_register_match(struct xt_match *match)
{
int ret, af = match->family;
@@ -108,11 +138,41 @@ xt_unregister_match(struct xt_match *match)
int af = match->family;
mutex_lock(&xt[af].mutex);
- LIST_DELETE(&xt[af].match, match);
+ list_del(&match->list);
mutex_unlock(&xt[af].mutex);
}
EXPORT_SYMBOL(xt_unregister_match);
+int
+xt_register_matches(struct xt_match *match, unsigned int n)
+{
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; i < n; i++) {
+ err = xt_register_match(&match[i]);
+ if (err)
+ goto err;
+ }
+ return err;
+
+err:
+ if (i > 0)
+ xt_unregister_matches(match, i);
+ return err;
+}
+EXPORT_SYMBOL(xt_register_matches);
+
+void
+xt_unregister_matches(struct xt_match *match, unsigned int n)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ xt_unregister_match(&match[i]);
+}
+EXPORT_SYMBOL(xt_unregister_matches);
+
/*
* These are weird, but module loading must not be done with mutex
@@ -273,52 +333,65 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
EXPORT_SYMBOL_GPL(xt_check_match);
#ifdef CONFIG_COMPAT
-int xt_compat_match(void *match, void **dstptr, int *size, int convert)
+int xt_compat_match_offset(struct xt_match *match)
{
- struct xt_match *m;
- struct compat_xt_entry_match *pcompat_m;
- struct xt_entry_match *pm;
- u_int16_t msize;
- int off, ret;
+ u_int16_t csize = match->compatsize ? : match->matchsize;
+ return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize);
+}
+EXPORT_SYMBOL_GPL(xt_compat_match_offset);
- ret = 0;
- m = ((struct xt_entry_match *)match)->u.kernel.match;
- off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize);
- switch (convert) {
- case COMPAT_TO_USER:
- pm = (struct xt_entry_match *)match;
- msize = pm->u.user.match_size;
- if (copy_to_user(*dstptr, pm, msize)) {
- ret = -EFAULT;
- break;
- }
- msize -= off;
- if (put_user(msize, (u_int16_t *)*dstptr))
- ret = -EFAULT;
- *size -= off;
- *dstptr += msize;
- break;
- case COMPAT_FROM_USER:
- pcompat_m = (struct compat_xt_entry_match *)match;
- pm = (struct xt_entry_match *)*dstptr;
- msize = pcompat_m->u.user.match_size;
- memcpy(pm, pcompat_m, msize);
- msize += off;
- pm->u.user.match_size = msize;
- *size += off;
- *dstptr += msize;
- break;
- case COMPAT_CALC_SIZE:
- *size += off;
- break;
- default:
- ret = -ENOPROTOOPT;
- break;
+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+ int *size)
+{
+ struct xt_match *match = m->u.kernel.match;
+ struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
+ int pad, off = xt_compat_match_offset(match);
+ u_int16_t msize = cm->u.user.match_size;
+
+ m = *dstptr;
+ memcpy(m, cm, sizeof(*cm));
+ if (match->compat_from_user)
+ match->compat_from_user(m->data, cm->data);
+ else
+ memcpy(m->data, cm->data, msize - sizeof(*cm));
+ pad = XT_ALIGN(match->matchsize) - match->matchsize;
+ if (pad > 0)
+ memset(m->data + match->matchsize, 0, pad);
+
+ msize += off;
+ m->u.user.match_size = msize;
+
+ *size += off;
+ *dstptr += msize;
+}
+EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
+
+int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
+ int *size)
+{
+ struct xt_match *match = m->u.kernel.match;
+ struct compat_xt_entry_match __user *cm = *dstptr;
+ int off = xt_compat_match_offset(match);
+ u_int16_t msize = m->u.user.match_size - off;
+
+ if (copy_to_user(cm, m, sizeof(*cm)) ||
+ put_user(msize, &cm->u.user.match_size))
+ return -EFAULT;
+
+ if (match->compat_to_user) {
+ if (match->compat_to_user((void __user *)cm->data, m->data))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(cm->data, m->data, msize - sizeof(*cm)))
+ return -EFAULT;
}
- return ret;
+
+ *size -= off;
+ *dstptr += msize;
+ return 0;
}
-EXPORT_SYMBOL_GPL(xt_compat_match);
-#endif
+EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
+#endif /* CONFIG_COMPAT */
int xt_check_target(const struct xt_target *target, unsigned short family,
unsigned int size, const char *table, unsigned int hook_mask,
@@ -350,51 +423,64 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
EXPORT_SYMBOL_GPL(xt_check_target);
#ifdef CONFIG_COMPAT
-int xt_compat_target(void *target, void **dstptr, int *size, int convert)
+int xt_compat_target_offset(struct xt_target *target)
{
- struct xt_target *t;
- struct compat_xt_entry_target *pcompat;
- struct xt_entry_target *pt;
- u_int16_t tsize;
- int off, ret;
+ u_int16_t csize = target->compatsize ? : target->targetsize;
+ return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize);
+}
+EXPORT_SYMBOL_GPL(xt_compat_target_offset);
- ret = 0;
- t = ((struct xt_entry_target *)target)->u.kernel.target;
- off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize);
- switch (convert) {
- case COMPAT_TO_USER:
- pt = (struct xt_entry_target *)target;
- tsize = pt->u.user.target_size;
- if (copy_to_user(*dstptr, pt, tsize)) {
- ret = -EFAULT;
- break;
- }
- tsize -= off;
- if (put_user(tsize, (u_int16_t *)*dstptr))
- ret = -EFAULT;
- *size -= off;
- *dstptr += tsize;
- break;
- case COMPAT_FROM_USER:
- pcompat = (struct compat_xt_entry_target *)target;
- pt = (struct xt_entry_target *)*dstptr;
- tsize = pcompat->u.user.target_size;
- memcpy(pt, pcompat, tsize);
- tsize += off;
- pt->u.user.target_size = tsize;
- *size += off;
- *dstptr += tsize;
- break;
- case COMPAT_CALC_SIZE:
- *size += off;
- break;
- default:
- ret = -ENOPROTOOPT;
- break;
+void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
+ int *size)
+{
+ struct xt_target *target = t->u.kernel.target;
+ struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
+ int pad, off = xt_compat_target_offset(target);
+ u_int16_t tsize = ct->u.user.target_size;
+
+ t = *dstptr;
+ memcpy(t, ct, sizeof(*ct));
+ if (target->compat_from_user)
+ target->compat_from_user(t->data, ct->data);
+ else
+ memcpy(t->data, ct->data, tsize - sizeof(*ct));
+ pad = XT_ALIGN(target->targetsize) - target->targetsize;
+ if (pad > 0)
+ memset(t->data + target->targetsize, 0, pad);
+
+ tsize += off;
+ t->u.user.target_size = tsize;
+
+ *size += off;
+ *dstptr += tsize;
+}
+EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
+
+int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr,
+ int *size)
+{
+ struct xt_target *target = t->u.kernel.target;
+ struct compat_xt_entry_target __user *ct = *dstptr;
+ int off = xt_compat_target_offset(target);
+ u_int16_t tsize = t->u.user.target_size - off;
+
+ if (copy_to_user(ct, t, sizeof(*ct)) ||
+ put_user(tsize, &ct->u.user.target_size))
+ return -EFAULT;
+
+ if (target->compat_to_user) {
+ if (target->compat_to_user((void __user *)ct->data, t->data))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(ct->data, t->data, tsize - sizeof(*ct)))
+ return -EFAULT;
}
- return ret;
+
+ *size -= off;
+ *dstptr += tsize;
+ return 0;
}
-EXPORT_SYMBOL_GPL(xt_compat_target);
+EXPORT_SYMBOL_GPL(xt_compat_target_to_user);
#endif
struct xt_table_info *xt_alloc_table_info(unsigned int size)
@@ -515,15 +601,18 @@ int xt_register_table(struct xt_table *table,
{
int ret;
struct xt_table_info *private;
+ struct xt_table *t;
ret = mutex_lock_interruptible(&xt[table->af].mutex);
if (ret != 0)
return ret;
/* Don't autoload: we'd eat our tail... */
- if (list_named_find(&xt[table->af].tables, table->name)) {
- ret = -EEXIST;
- goto unlock;
+ list_for_each_entry(t, &xt[table->af].tables, list) {
+ if (strcmp(t->name, table->name) == 0) {
+ ret = -EEXIST;
+ goto unlock;
+ }
}
/* Simplifies replace_table code. */
@@ -538,7 +627,7 @@ int xt_register_table(struct xt_table *table,
/* save number of initial entries */
private->initial_entries = private->number;
- list_prepend(&xt[table->af].tables, table);
+ list_add(&table->list, &xt[table->af].tables);
ret = 0;
unlock:
@@ -553,7 +642,7 @@ void *xt_unregister_table(struct xt_table *table)
mutex_lock(&xt[table->af].mutex);
private = table->private;
- LIST_DELETE(&xt[table->af].tables, table);
+ list_del(&table->list);
mutex_unlock(&xt[table->af].mutex);
return private;
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index e54e5773001..50de965bb10 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -29,8 +29,7 @@ target(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo,
- void *userinfo)
+ const void *targinfo)
{
const struct xt_classify_target_info *clinfo = targinfo;
@@ -40,47 +39,41 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static struct xt_target classify_reg = {
- .name = "CLASSIFY",
- .target = target,
- .targetsize = sizeof(struct xt_classify_target_info),
- .table = "mangle",
- .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
- (1 << NF_IP_POST_ROUTING),
- .family = AF_INET,
- .me = THIS_MODULE,
+static struct xt_target xt_classify_target[] = {
+ {
+ .family = AF_INET,
+ .name = "CLASSIFY",
+ .target = target,
+ .targetsize = sizeof(struct xt_classify_target_info),
+ .table = "mangle",
+ .hooks = (1 << NF_IP_LOCAL_OUT) |
+ (1 << NF_IP_FORWARD) |
+ (1 << NF_IP_POST_ROUTING),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "CLASSIFY",
+ .family = AF_INET6,
+ .target = target,
+ .targetsize = sizeof(struct xt_classify_target_info),
+ .table = "mangle",
+ .hooks = (1 << NF_IP_LOCAL_OUT) |
+ (1 << NF_IP_FORWARD) |
+ (1 << NF_IP_POST_ROUTING),
+ .me = THIS_MODULE,
+ },
};
-static struct xt_target classify6_reg = {
- .name = "CLASSIFY",
- .target = target,
- .targetsize = sizeof(struct xt_classify_target_info),
- .table = "mangle",
- .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
- (1 << NF_IP_POST_ROUTING),
- .family = AF_INET6,
- .me = THIS_MODULE,
-};
-
static int __init xt_classify_init(void)
{
- int ret;
-
- ret = xt_register_target(&classify_reg);
- if (ret)
- return ret;
-
- ret = xt_register_target(&classify6_reg);
- if (ret)
- xt_unregister_target(&classify_reg);
-
- return ret;
+ return xt_register_targets(xt_classify_target,
+ ARRAY_SIZE(xt_classify_target));
}
static void __exit xt_classify_fini(void)
{
- xt_unregister_target(&classify_reg);
- xt_unregister_target(&classify6_reg);
+ xt_unregister_targets(xt_classify_target,
+ ARRAY_SIZE(xt_classify_target));
}
module_init(xt_classify_init);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 60c375d36f0..c01524f817f 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -38,8 +38,7 @@ target(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo,
- void *userinfo)
+ const void *targinfo)
{
const struct xt_connmark_target_info *markinfo = targinfo;
u_int32_t diff;
@@ -49,24 +48,37 @@ target(struct sk_buff **pskb,
u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
if (ctmark) {
- switch(markinfo->mode) {
- case XT_CONNMARK_SET:
- newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
- if (newmark != *ctmark)
- *ctmark = newmark;
- break;
- case XT_CONNMARK_SAVE:
- newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
- if (*ctmark != newmark)
- *ctmark = newmark;
- break;
- case XT_CONNMARK_RESTORE:
- nfmark = (*pskb)->nfmark;
- diff = (*ctmark ^ nfmark) & markinfo->mask;
- if (diff != 0)
- (*pskb)->nfmark = nfmark ^ diff;
- break;
- }
+ switch(markinfo->mode) {
+ case XT_CONNMARK_SET:
+ newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
+ if (newmark != *ctmark) {
+ *ctmark = newmark;
+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
+ ip_conntrack_event_cache(IPCT_MARK, *pskb);
+#else
+ nf_conntrack_event_cache(IPCT_MARK, *pskb);
+#endif
+ }
+ break;
+ case XT_CONNMARK_SAVE:
+ newmark = (*ctmark & ~markinfo->mask) |
+ ((*pskb)->nfmark & markinfo->mask);
+ if (*ctmark != newmark) {
+ *ctmark = newmark;
+#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
+ ip_conntrack_event_cache(IPCT_MARK, *pskb);
+#else
+ nf_conntrack_event_cache(IPCT_MARK, *pskb);
+#endif
+ }
+ break;
+ case XT_CONNMARK_RESTORE:
+ nfmark = (*pskb)->nfmark;
+ diff = (*ctmark ^ nfmark) & markinfo->mask;
+ if (diff != 0)
+ (*pskb)->nfmark = nfmark ^ diff;
+ break;
+ }
}
return XT_CONTINUE;
@@ -77,65 +89,91 @@ checkentry(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
- unsigned int targinfosize,
unsigned int hook_mask)
{
struct xt_connmark_target_info *matchinfo = targinfo;
if (matchinfo->mode == XT_CONNMARK_RESTORE) {
- if (strcmp(tablename, "mangle") != 0) {
- printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
- return 0;
- }
+ if (strcmp(tablename, "mangle") != 0) {
+ printk(KERN_WARNING "CONNMARK: restore can only be "
+ "called from \"mangle\" table, not \"%s\"\n",
+ tablename);
+ return 0;
+ }
}
-
if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
return 0;
}
-
return 1;
}
-static struct xt_target connmark_reg = {
- .name = "CONNMARK",
- .target = target,
- .targetsize = sizeof(struct xt_connmark_target_info),
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE
+#ifdef CONFIG_COMPAT
+struct compat_xt_connmark_target_info {
+ compat_ulong_t mark, mask;
+ u_int8_t mode;
+ u_int8_t __pad1;
+ u_int16_t __pad2;
};
-static struct xt_target connmark6_reg = {
- .name = "CONNMARK",
- .target = target,
- .targetsize = sizeof(struct xt_connmark_target_info),
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE
+static void compat_from_user(void *dst, void *src)
+{
+ struct compat_xt_connmark_target_info *cm = src;
+ struct xt_connmark_target_info m = {
+ .mark = cm->mark,
+ .mask = cm->mask,
+ .mode = cm->mode,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
+
+static int compat_to_user(void __user *dst, void *src)
+{
+ struct xt_connmark_target_info *m = src;
+ struct compat_xt_connmark_target_info cm = {
+ .mark = m->mark,
+ .mask = m->mask,
+ .mode = m->mode,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct xt_target xt_connmark_target[] = {
+ {
+ .name = "CONNMARK",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_connmark_target_info),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_connmark_target_info),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
+#endif
+ .me = THIS_MODULE
+ },
+ {
+ .name = "CONNMARK",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_connmark_target_info),
+ .me = THIS_MODULE
+ },
};
static int __init xt_connmark_init(void)
{
- int ret;
-
need_conntrack();
-
- ret = xt_register_target(&connmark_reg);
- if (ret)
- return ret;
-
- ret = xt_register_target(&connmark6_reg);
- if (ret)
- xt_unregister_target(&connmark_reg);
-
- return ret;
+ return xt_register_targets(xt_connmark_target,
+ ARRAY_SIZE(xt_connmark_target));
}
static void __exit xt_connmark_fini(void)
{
- xt_unregister_target(&connmark_reg);
- xt_unregister_target(&connmark6_reg);
+ xt_unregister_targets(xt_connmark_target,
+ ARRAY_SIZE(xt_connmark_target));
}
module_init(xt_connmark_init);
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 8c011e02076..46738626667 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -66,7 +66,7 @@ static void secmark_restore(struct sk_buff *skb)
static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo, void *userinfo)
+ const void *targinfo)
{
struct sk_buff *skb = *pskb;
const struct xt_connsecmark_target_info *info = targinfo;
@@ -89,7 +89,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
static int checkentry(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
- unsigned int targinfosize, unsigned int hook_mask)
+ unsigned int hook_mask)
{
struct xt_connsecmark_target_info *info = targinfo;
@@ -106,49 +106,38 @@ static int checkentry(const char *tablename, const void *entry,
return 1;
}
-static struct xt_target ipt_connsecmark_reg = {
- .name = "CONNSECMARK",
- .target = target,
- .targetsize = sizeof(struct xt_connsecmark_target_info),
- .table = "mangle",
- .checkentry = checkentry,
- .me = THIS_MODULE,
- .family = AF_INET,
- .revision = 0,
-};
-
-static struct xt_target ip6t_connsecmark_reg = {
- .name = "CONNSECMARK",
- .target = target,
- .targetsize = sizeof(struct xt_connsecmark_target_info),
- .table = "mangle",
- .checkentry = checkentry,
- .me = THIS_MODULE,
- .family = AF_INET6,
- .revision = 0,
+static struct xt_target xt_connsecmark_target[] = {
+ {
+ .name = "CONNSECMARK",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_connsecmark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "CONNSECMARK",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_connsecmark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
};
static int __init xt_connsecmark_init(void)
{
- int err;
-
need_conntrack();
-
- err = xt_register_target(&ipt_connsecmark_reg);
- if (err)
- return err;
-
- err = xt_register_target(&ip6t_connsecmark_reg);
- if (err)
- xt_unregister_target(&ipt_connsecmark_reg);
-
- return err;
+ return xt_register_targets(xt_connsecmark_target,
+ ARRAY_SIZE(xt_connsecmark_target));
}
static void __exit xt_connsecmark_fini(void)
{
- xt_unregister_target(&ip6t_connsecmark_reg);
- xt_unregister_target(&ipt_connsecmark_reg);
+ xt_unregister_targets(xt_connsecmark_target,
+ ARRAY_SIZE(xt_connsecmark_target));
}
module_init(xt_connsecmark_init);
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
new file mode 100644
index 00000000000..a7cc75aeb38
--- /dev/null
+++ b/net/netfilter/xt_DSCP.c
@@ -0,0 +1,118 @@
+/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8
+ *
+ * (C) 2002 by Harald Welte <laforge@netfilter.org>
+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * See RFC2474 for a description of the DSCP field within the IP Header.
+ *
+ * xt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/dsfield.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_DSCP.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("x_tables DSCP modification module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_DSCP");
+MODULE_ALIAS("ip6t_DSCP");
+
+static unsigned int target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ const struct xt_DSCP_info *dinfo = targinfo;
+ u_int8_t dscp = ipv4_get_dsfield((*pskb)->nh.iph) >> XT_DSCP_SHIFT;
+
+ if (dscp != dinfo->dscp) {
+ if (!skb_make_writable(pskb, sizeof(struct iphdr)))
+ return NF_DROP;
+
+ ipv4_change_dsfield((*pskb)->nh.iph, (__u8)(~XT_DSCP_MASK),
+ dinfo->dscp << XT_DSCP_SHIFT);
+
+ }
+ return XT_CONTINUE;
+}
+
+static unsigned int target6(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ const struct xt_DSCP_info *dinfo = targinfo;
+ u_int8_t dscp = ipv6_get_dsfield((*pskb)->nh.ipv6h) >> XT_DSCP_SHIFT;
+
+ if (dscp != dinfo->dscp) {
+ if (!skb_make_writable(pskb, sizeof(struct ipv6hdr)))
+ return NF_DROP;
+
+ ipv6_change_dsfield((*pskb)->nh.ipv6h, (__u8)(~XT_DSCP_MASK),
+ dinfo->dscp << XT_DSCP_SHIFT);
+ }
+ return XT_CONTINUE;
+}
+
+static int checkentry(const char *tablename,
+ const void *e_void,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
+
+ if ((dscp > XT_DSCP_MAX)) {
+ printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
+ return 0;
+ }
+ return 1;
+}
+
+static struct xt_target xt_dscp_target[] = {
+ {
+ .name = "DSCP",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_DSCP_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "DSCP",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .target = target6,
+ .targetsize = sizeof(struct xt_DSCP_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_dscp_target_init(void)
+{
+ return xt_register_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target));
+}
+
+static void __exit xt_dscp_target_fini(void)
+{
+ xt_unregister_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target));
+}
+
+module_init(xt_dscp_target_init);
+module_exit(xt_dscp_target_fini);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index ee9c34edc76..c6e860a7114 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -27,8 +27,7 @@ target_v0(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo,
- void *userinfo)
+ const void *targinfo)
{
const struct xt_mark_target_info *markinfo = targinfo;
@@ -44,8 +43,7 @@ target_v1(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo,
- void *userinfo)
+ const void *targinfo)
{
const struct xt_mark_target_info_v1 *markinfo = targinfo;
int mark = 0;
@@ -76,7 +74,6 @@ checkentry_v0(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
- unsigned int targinfosize,
unsigned int hook_mask)
{
struct xt_mark_target_info *markinfo = targinfo;
@@ -93,7 +90,6 @@ checkentry_v1(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
- unsigned int targinfosize,
unsigned int hook_mask)
{
struct xt_mark_target_info_v1 *markinfo = targinfo;
@@ -112,65 +108,81 @@ checkentry_v1(const char *tablename,
return 1;
}
-static struct xt_target ipt_mark_reg_v0 = {
- .name = "MARK",
- .target = target_v0,
- .targetsize = sizeof(struct xt_mark_target_info),
- .table = "mangle",
- .checkentry = checkentry_v0,
- .me = THIS_MODULE,
- .family = AF_INET,
- .revision = 0,
+#ifdef CONFIG_COMPAT
+struct compat_xt_mark_target_info_v1 {
+ compat_ulong_t mark;
+ u_int8_t mode;
+ u_int8_t __pad1;
+ u_int16_t __pad2;
};
-static struct xt_target ipt_mark_reg_v1 = {
- .name = "MARK",
- .target = target_v1,
- .targetsize = sizeof(struct xt_mark_target_info_v1),
- .table = "mangle",
- .checkentry = checkentry_v1,
- .me = THIS_MODULE,
- .family = AF_INET,
- .revision = 1,
-};
+static void compat_from_user_v1(void *dst, void *src)
+{
+ struct compat_xt_mark_target_info_v1 *cm = src;
+ struct xt_mark_target_info_v1 m = {
+ .mark = cm->mark,
+ .mode = cm->mode,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
-static struct xt_target ip6t_mark_reg_v0 = {
- .name = "MARK",
- .target = target_v0,
- .targetsize = sizeof(struct xt_mark_target_info),
- .table = "mangle",
- .checkentry = checkentry_v0,
- .me = THIS_MODULE,
- .family = AF_INET6,
- .revision = 0,
+static int compat_to_user_v1(void __user *dst, void *src)
+{
+ struct xt_mark_target_info_v1 *m = src;
+ struct compat_xt_mark_target_info_v1 cm = {
+ .mark = m->mark,
+ .mode = m->mode,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct xt_target xt_mark_target[] = {
+ {
+ .name = "MARK",
+ .family = AF_INET,
+ .revision = 0,
+ .checkentry = checkentry_v0,
+ .target = target_v0,
+ .targetsize = sizeof(struct xt_mark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "MARK",
+ .family = AF_INET,
+ .revision = 1,
+ .checkentry = checkentry_v1,
+ .target = target_v1,
+ .targetsize = sizeof(struct xt_mark_target_info_v1),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_mark_target_info_v1),
+ .compat_from_user = compat_from_user_v1,
+ .compat_to_user = compat_to_user_v1,
+#endif
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "MARK",
+ .family = AF_INET6,
+ .revision = 0,
+ .checkentry = checkentry_v0,
+ .target = target_v0,
+ .targetsize = sizeof(struct xt_mark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
};
static int __init xt_mark_init(void)
{
- int err;
-
- err = xt_register_target(&ipt_mark_reg_v0);
- if (err)
- return err;
-
- err = xt_register_target(&ipt_mark_reg_v1);
- if (err)
- xt_unregister_target(&ipt_mark_reg_v0);
-
- err = xt_register_target(&ip6t_mark_reg_v0);
- if (err) {
- xt_unregister_target(&ipt_mark_reg_v0);
- xt_unregister_target(&ipt_mark_reg_v1);
- }
-
- return err;
+ return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
}
static void __exit xt_mark_fini(void)
{
- xt_unregister_target(&ipt_mark_reg_v0);
- xt_unregister_target(&ipt_mark_reg_v1);
- xt_unregister_target(&ip6t_mark_reg_v0);
+ xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
}
module_init(xt_mark_init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 86ccceb61fd..db9b896e57c 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -29,65 +29,46 @@ target(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo,
- void *userinfo)
+ const void *targinfo)
{
const struct xt_NFQ_info *tinfo = targinfo;
return NF_QUEUE_NR(tinfo->queuenum);
}
-static struct xt_target ipt_NFQ_reg = {
- .name = "NFQUEUE",
- .target = target,
- .targetsize = sizeof(struct xt_NFQ_info),
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_target ip6t_NFQ_reg = {
- .name = "NFQUEUE",
- .target = target,
- .targetsize = sizeof(struct xt_NFQ_info),
- .family = AF_INET6,
- .me = THIS_MODULE,
-};
-
-static struct xt_target arpt_NFQ_reg = {
- .name = "NFQUEUE",
- .target = target,
- .targetsize = sizeof(struct xt_NFQ_info),
- .family = NF_ARP,
- .me = THIS_MODULE,
+static struct xt_target xt_nfqueue_target[] = {
+ {
+ .name = "NFQUEUE",
+ .family = AF_INET,
+ .target = target,
+ .targetsize = sizeof(struct xt_NFQ_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "NFQUEUE",
+ .family = AF_INET6,
+ .target = target,
+ .targetsize = sizeof(struct xt_NFQ_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "NFQUEUE",
+ .family = NF_ARP,
+ .target = target,
+ .targetsize = sizeof(struct xt_NFQ_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_nfqueue_init(void)
{
- int ret;
- ret = xt_register_target(&ipt_NFQ_reg);
- if (ret)
- return ret;
- ret = xt_register_target(&ip6t_NFQ_reg);
- if (ret)
- goto out_ip;
- ret = xt_register_target(&arpt_NFQ_reg);
- if (ret)
- goto out_ip6;
-
- return ret;
-out_ip6:
- xt_unregister_target(&ip6t_NFQ_reg);
-out_ip:
- xt_unregister_target(&ipt_NFQ_reg);
-
- return ret;
+ return xt_register_targets(xt_nfqueue_target,
+ ARRAY_SIZE(xt_nfqueue_target));
}
static void __exit xt_nfqueue_fini(void)
{
- xt_unregister_target(&arpt_NFQ_reg);
- xt_unregister_target(&ip6t_NFQ_reg);
- xt_unregister_target(&ipt_NFQ_reg);
+ xt_register_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target));
}
module_init(xt_nfqueue_init);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 98f4b5363ce..6d00dcaed23 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -16,8 +16,7 @@ target(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo,
- void *userinfo)
+ const void *targinfo)
{
/* Previously seen (loopback)? Ignore. */
if ((*pskb)->nfct != NULL)
@@ -34,43 +33,32 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static struct xt_target notrack_reg = {
- .name = "NOTRACK",
- .target = target,
- .targetsize = 0,
- .table = "raw",
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_target notrack6_reg = {
- .name = "NOTRACK",
- .target = target,
- .targetsize = 0,
- .table = "raw",
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_target xt_notrack_target[] = {
+ {
+ .name = "NOTRACK",
+ .family = AF_INET,
+ .target = target,
+ .table = "raw",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "NOTRACK",
+ .family = AF_INET6,
+ .target = target,
+ .table = "raw",
+ .me = THIS_MODULE,
+ },
};
static int __init xt_notrack_init(void)
{
- int ret;
-
- ret = xt_register_target(&notrack_reg);
- if (ret)
- return ret;
-
- ret = xt_register_target(&notrack6_reg);
- if (ret)
- xt_unregister_target(&notrack_reg);
-
- return ret;
+ return xt_register_targets(xt_notrack_target,
+ ARRAY_SIZE(xt_notrack_target));
}
static void __exit xt_notrack_fini(void)
{
- xt_unregister_target(&notrack6_reg);
- xt_unregister_target(&notrack_reg);
+ xt_unregister_targets(xt_notrack_target, ARRAY_SIZE(xt_notrack_target));
}
module_init(xt_notrack_init);
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index de9537ad9a7..add75219629 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -31,7 +31,7 @@ static u8 mode;
static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo, void *userinfo)
+ const void *targinfo)
{
u32 secmark = 0;
const struct xt_secmark_target_info *info = targinfo;
@@ -85,7 +85,7 @@ static int checkentry_selinux(struct xt_secmark_target_info *info)
static int checkentry(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo,
- unsigned int targinfosize, unsigned int hook_mask)
+ unsigned int hook_mask)
{
struct xt_secmark_target_info *info = targinfo;
@@ -111,47 +111,36 @@ static int checkentry(const char *tablename, const void *entry,
return 1;
}
-static struct xt_target ipt_secmark_reg = {
- .name = "SECMARK",
- .target = target,
- .targetsize = sizeof(struct xt_secmark_target_info),
- .table = "mangle",
- .checkentry = checkentry,
- .me = THIS_MODULE,
- .family = AF_INET,
- .revision = 0,
-};
-
-static struct xt_target ip6t_secmark_reg = {
- .name = "SECMARK",
- .target = target,
- .targetsize = sizeof(struct xt_secmark_target_info),
- .table = "mangle",
- .checkentry = checkentry,
- .me = THIS_MODULE,
- .family = AF_INET6,
- .revision = 0,
+static struct xt_target xt_secmark_target[] = {
+ {
+ .name = "SECMARK",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_secmark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "SECMARK",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .target = target,
+ .targetsize = sizeof(struct xt_secmark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
};
static int __init xt_secmark_init(void)
{
- int err;
-
- err = xt_register_target(&ipt_secmark_reg);
- if (err)
- return err;
-
- err = xt_register_target(&ip6t_secmark_reg);
- if (err)
- xt_unregister_target(&ipt_secmark_reg);
-
- return err;
+ return xt_register_targets(xt_secmark_target,
+ ARRAY_SIZE(xt_secmark_target));
}
static void __exit xt_secmark_fini(void)
{
- xt_unregister_target(&ip6t_secmark_reg);
- xt_unregister_target(&ipt_secmark_reg);
+ xt_unregister_targets(xt_secmark_target, ARRAY_SIZE(xt_secmark_target));
}
module_init(xt_secmark_init);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 197609cb06d..7db492d6522 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -29,41 +29,32 @@ match(const struct sk_buff *skb,
return 1;
}
-static struct xt_match comment_match = {
- .name = "comment",
- .match = match,
- .matchsize = sizeof(struct xt_comment_info),
- .family = AF_INET,
- .me = THIS_MODULE
-};
-
-static struct xt_match comment6_match = {
- .name = "comment",
- .match = match,
- .matchsize = sizeof(struct xt_comment_info),
- .family = AF_INET6,
- .me = THIS_MODULE
+static struct xt_match xt_comment_match[] = {
+ {
+ .name = "comment",
+ .family = AF_INET,
+ .match = match,
+ .matchsize = sizeof(struct xt_comment_info),
+ .me = THIS_MODULE
+ },
+ {
+ .name = "comment",
+ .family = AF_INET6,
+ .match = match,
+ .matchsize = sizeof(struct xt_comment_info),
+ .me = THIS_MODULE
+ },
};
static int __init xt_comment_init(void)
{
- int ret;
-
- ret = xt_register_match(&comment_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&comment6_match);
- if (ret)
- xt_unregister_match(&comment_match);
-
- return ret;
+ return xt_register_matches(xt_comment_match,
+ ARRAY_SIZE(xt_comment_match));
}
static void __exit xt_comment_fini(void)
{
- xt_unregister_match(&comment_match);
- xt_unregister_match(&comment6_match);
+ xt_unregister_matches(xt_comment_match, ARRAY_SIZE(xt_comment_match));
}
module_init(xt_comment_init);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 1396fe2d07c..dcc497ea818 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -125,7 +125,6 @@ static int check(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_connbytes_info *sinfo = matchinfo;
@@ -143,40 +142,35 @@ static int check(const char *tablename,
return 1;
}
-static struct xt_match connbytes_match = {
- .name = "connbytes",
- .match = match,
- .checkentry = check,
- .matchsize = sizeof(struct xt_connbytes_info),
- .family = AF_INET,
- .me = THIS_MODULE
-};
-static struct xt_match connbytes6_match = {
- .name = "connbytes",
- .match = match,
- .checkentry = check,
- .matchsize = sizeof(struct xt_connbytes_info),
- .family = AF_INET6,
- .me = THIS_MODULE
+static struct xt_match xt_connbytes_match[] = {
+ {
+ .name = "connbytes",
+ .family = AF_INET,
+ .checkentry = check,
+ .match = match,
+ .matchsize = sizeof(struct xt_connbytes_info),
+ .me = THIS_MODULE
+ },
+ {
+ .name = "connbytes",
+ .family = AF_INET6,
+ .checkentry = check,
+ .match = match,
+ .matchsize = sizeof(struct xt_connbytes_info),
+ .me = THIS_MODULE
+ },
};
static int __init xt_connbytes_init(void)
{
- int ret;
- ret = xt_register_match(&connbytes_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&connbytes6_match);
- if (ret)
- xt_unregister_match(&connbytes_match);
- return ret;
+ return xt_register_matches(xt_connbytes_match,
+ ARRAY_SIZE(xt_connbytes_match));
}
static void __exit xt_connbytes_fini(void)
{
- xt_unregister_match(&connbytes_match);
- xt_unregister_match(&connbytes6_match);
+ xt_unregister_matches(xt_connbytes_match,
+ ARRAY_SIZE(xt_connbytes_match));
}
module_init(xt_connbytes_init);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 56324c8aff0..92a5726ef23 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -55,7 +55,6 @@ checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
struct xt_connmark_info *cm = matchinfo;
@@ -75,53 +74,80 @@ checkentry(const char *tablename,
}
static void
-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+destroy(const struct xt_match *match, void *matchinfo)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
-static struct xt_match connmark_match = {
- .name = "connmark",
- .match = match,
- .matchsize = sizeof(struct xt_connmark_info),
- .checkentry = checkentry,
- .destroy = destroy,
- .family = AF_INET,
- .me = THIS_MODULE
+#ifdef CONFIG_COMPAT
+struct compat_xt_connmark_info {
+ compat_ulong_t mark, mask;
+ u_int8_t invert;
+ u_int8_t __pad1;
+ u_int16_t __pad2;
};
-static struct xt_match connmark6_match = {
- .name = "connmark",
- .match = match,
- .matchsize = sizeof(struct xt_connmark_info),
- .checkentry = checkentry,
- .destroy = destroy,
- .family = AF_INET6,
- .me = THIS_MODULE
+static void compat_from_user(void *dst, void *src)
+{
+ struct compat_xt_connmark_info *cm = src;
+ struct xt_connmark_info m = {
+ .mark = cm->mark,
+ .mask = cm->mask,
+ .invert = cm->invert,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
+
+static int compat_to_user(void __user *dst, void *src)
+{
+ struct xt_connmark_info *m = src;
+ struct compat_xt_connmark_info cm = {
+ .mark = m->mark,
+ .mask = m->mask,
+ .invert = m->invert,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct xt_match xt_connmark_match[] = {
+ {
+ .name = "connmark",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_connmark_info),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_connmark_info),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
+#endif
+ .me = THIS_MODULE
+ },
+ {
+ .name = "connmark",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_connmark_info),
+ .me = THIS_MODULE
+ },
};
static int __init xt_connmark_init(void)
{
- int ret;
-
need_conntrack();
-
- ret = xt_register_match(&connmark_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&connmark6_match);
- if (ret)
- xt_unregister_match(&connmark_match);
- return ret;
+ return xt_register_matches(xt_connmark_match,
+ ARRAY_SIZE(xt_connmark_match));
}
static void __exit xt_connmark_fini(void)
{
- xt_unregister_match(&connmark6_match);
- xt_unregister_match(&connmark_match);
+ xt_register_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match));
}
module_init(xt_connmark_init);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 145489a4c3f..0ea501a2fda 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -45,7 +45,7 @@ match(const struct sk_buff *skb,
ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
-#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
+#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & invflg))
if (ct == &ip_conntrack_untracked)
statebit = XT_CONNTRACK_STATE_UNTRACKED;
@@ -54,63 +54,72 @@ match(const struct sk_buff *skb,
else
statebit = XT_CONNTRACK_STATE_INVALID;
- if(sinfo->flags & XT_CONNTRACK_STATE) {
+ if (sinfo->flags & XT_CONNTRACK_STATE) {
if (ct) {
- if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)
+ if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
statebit |= XT_CONNTRACK_STATE_SNAT;
-
- if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
+ if (test_bit(IPS_DST_NAT_BIT, &ct->status))
statebit |= XT_CONNTRACK_STATE_DNAT;
}
-
- if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
- return 0;
- }
-
- if(sinfo->flags & XT_CONNTRACK_PROTO) {
- if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
- return 0;
- }
-
- if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
+ if (FWINV((statebit & sinfo->statemask) == 0,
+ XT_CONNTRACK_STATE))
return 0;
}
- if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
+ if (ct == NULL) {
+ if (sinfo->flags & ~XT_CONNTRACK_STATE)
return 0;
+ return 1;
}
- if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
- return 0;
- }
+ if (sinfo->flags & XT_CONNTRACK_PROTO &&
+ FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
+ XT_CONNTRACK_PROTO))
+ return 0;
+
+ if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
+ FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip &
+ sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
+ XT_CONNTRACK_ORIGSRC))
+ return 0;
- if(sinfo->flags & XT_CONNTRACK_REPLDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
- return 0;
- }
+ if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
+ FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip &
+ sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
+ XT_CONNTRACK_ORIGDST))
+ return 0;
- if(sinfo->flags & XT_CONNTRACK_STATUS) {
- if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
- return 0;
- }
+ if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
+ FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip &
+ sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
+ XT_CONNTRACK_REPLSRC))
+ return 0;
- if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
- unsigned long expires;
+ if (sinfo->flags & XT_CONNTRACK_REPLDST &&
+ FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip &
+ sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
+ XT_CONNTRACK_REPLDST))
+ return 0;
- if(!ct)
- return 0;
+ if (sinfo->flags & XT_CONNTRACK_STATUS &&
+ FWINV((ct->status & sinfo->statusmask) == 0,
+ XT_CONNTRACK_STATUS))
+ return 0;
- expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
+ if (sinfo->flags & XT_CONNTRACK_EXPIRES) {
+ unsigned long expires = timer_pending(&ct->timeout) ?
+ (ct->timeout.expires - jiffies)/HZ : 0;
- if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
+ if (FWINV(!(expires >= sinfo->expires_min &&
+ expires <= sinfo->expires_max),
+ XT_CONNTRACK_EXPIRES))
return 0;
}
-
return 1;
}
@@ -141,63 +150,72 @@ match(const struct sk_buff *skb,
else
statebit = XT_CONNTRACK_STATE_INVALID;
- if(sinfo->flags & XT_CONNTRACK_STATE) {
+ if (sinfo->flags & XT_CONNTRACK_STATE) {
if (ct) {
- if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip !=
- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip)
+ if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
statebit |= XT_CONNTRACK_STATE_SNAT;
-
- if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip !=
- ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip)
+ if (test_bit(IPS_DST_NAT_BIT, &ct->status))
statebit |= XT_CONNTRACK_STATE_DNAT;
}
-
- if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
- return 0;
- }
-
- if(sinfo->flags & XT_CONNTRACK_PROTO) {
- if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
- return 0;
- }
-
- if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
+ if (FWINV((statebit & sinfo->statemask) == 0,
+ XT_CONNTRACK_STATE))
return 0;
}
- if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
+ if (ct == NULL) {
+ if (sinfo->flags & ~XT_CONNTRACK_STATE)
return 0;
+ return 1;
}
- if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
- return 0;
- }
+ if (sinfo->flags & XT_CONNTRACK_PROTO &&
+ FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
+ XT_CONNTRACK_PROTO))
+ return 0;
+
+ if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
+ FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip &
+ sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
+ XT_CONNTRACK_ORIGSRC))
+ return 0;
- if(sinfo->flags & XT_CONNTRACK_REPLDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
- return 0;
- }
+ if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
+ FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip &
+ sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
+ XT_CONNTRACK_ORIGDST))
+ return 0;
- if(sinfo->flags & XT_CONNTRACK_STATUS) {
- if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
- return 0;
- }
+ if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
+ FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip &
+ sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
+ XT_CONNTRACK_REPLSRC))
+ return 0;
- if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
- unsigned long expires;
+ if (sinfo->flags & XT_CONNTRACK_REPLDST &&
+ FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip &
+ sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
+ sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
+ XT_CONNTRACK_REPLDST))
+ return 0;
- if(!ct)
- return 0;
+ if (sinfo->flags & XT_CONNTRACK_STATUS &&
+ FWINV((ct->status & sinfo->statusmask) == 0,
+ XT_CONNTRACK_STATUS))
+ return 0;
- expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
+ if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
+ unsigned long expires = timer_pending(&ct->timeout) ?
+ (ct->timeout.expires - jiffies)/HZ : 0;
- if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
+ if (FWINV(!(expires >= sinfo->expires_min &&
+ expires <= sinfo->expires_max),
+ XT_CONNTRACK_EXPIRES))
return 0;
}
-
return 1;
}
@@ -208,7 +226,6 @@ checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -221,8 +238,7 @@ checkentry(const char *tablename,
return 1;
}
-static void
-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+static void destroy(const struct xt_match *match, void *matchinfo)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
@@ -241,11 +257,8 @@ static struct xt_match conntrack_match = {
static int __init xt_conntrack_init(void)
{
- int ret;
need_conntrack();
- ret = xt_register_match(&conntrack_match);
-
- return ret;
+ return xt_register_match(&conntrack_match);
}
static void __exit xt_conntrack_fini(void)
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2e2f825dad4..3e6cf430e51 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -131,7 +131,6 @@ checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_dccp_info *info = matchinfo;
@@ -141,27 +140,26 @@ checkentry(const char *tablename,
&& !(info->invflags & ~info->flags);
}
-static struct xt_match dccp_match =
-{
- .name = "dccp",
- .match = match,
- .matchsize = sizeof(struct xt_dccp_info),
- .proto = IPPROTO_DCCP,
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
+static struct xt_match xt_dccp_match[] = {
+ {
+ .name = "dccp",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_dccp_info),
+ .proto = IPPROTO_DCCP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "dccp",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_dccp_info),
+ .proto = IPPROTO_DCCP,
+ .me = THIS_MODULE,
+ },
};
-static struct xt_match dccp6_match =
-{
- .name = "dccp",
- .match = match,
- .matchsize = sizeof(struct xt_dccp_info),
- .proto = IPPROTO_DCCP,
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE,
-};
-
static int __init xt_dccp_init(void)
{
@@ -173,27 +171,19 @@ static int __init xt_dccp_init(void)
dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
if (!dccp_optbuf)
return -ENOMEM;
- ret = xt_register_match(&dccp_match);
+ ret = xt_register_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match));
if (ret)
goto out_kfree;
- ret = xt_register_match(&dccp6_match);
- if (ret)
- goto out_unreg;
-
return ret;
-out_unreg:
- xt_unregister_match(&dccp_match);
out_kfree:
kfree(dccp_optbuf);
-
return ret;
}
static void __exit xt_dccp_fini(void)
{
- xt_unregister_match(&dccp6_match);
- xt_unregister_match(&dccp_match);
+ xt_unregister_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match));
kfree(dccp_optbuf);
}
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
new file mode 100644
index 00000000000..26c7f4ad102
--- /dev/null
+++ b/net/netfilter/xt_dscp.c
@@ -0,0 +1,103 @@
+/* IP tables module for matching the value of the IPv4/IPv6 DSCP field
+ *
+ * xt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp
+ *
+ * (C) 2002 by Harald Welte <laforge@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/dsfield.h>
+
+#include <linux/netfilter/xt_dscp.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("x_tables DSCP matching module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_dscp");
+MODULE_ALIAS("ip6t_dscp");
+
+static int 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,
+ int *hotdrop)
+{
+ const struct xt_dscp_info *info = matchinfo;
+ u_int8_t dscp = ipv4_get_dsfield(skb->nh.iph) >> XT_DSCP_SHIFT;
+
+ return (dscp == info->dscp) ^ !!info->invert;
+}
+
+static int match6(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,
+ int *hotdrop)
+{
+ const struct xt_dscp_info *info = matchinfo;
+ u_int8_t dscp = ipv6_get_dsfield(skb->nh.ipv6h) >> XT_DSCP_SHIFT;
+
+ return (dscp == info->dscp) ^ !!info->invert;
+}
+
+static int checkentry(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
+{
+ const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
+
+ if (dscp > XT_DSCP_MAX) {
+ printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct xt_match xt_dscp_match[] = {
+ {
+ .name = "dscp",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_dscp_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "dscp",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match6,
+ .matchsize = sizeof(struct xt_dscp_info),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_dscp_match_init(void)
+{
+ return xt_register_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
+}
+
+static void __exit xt_dscp_match_fini(void)
+{
+ xt_unregister_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match));
+}
+
+module_init(xt_dscp_match_init);
+module_exit(xt_dscp_match_fini);
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index 9dad6281e0c..7c95f149d94 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -79,7 +79,6 @@ checkentry(const char *tablename,
const void *ip_void,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchinfosize,
unsigned int hook_mask)
{
const struct xt_esp *espinfo = matchinfo;
@@ -92,44 +91,35 @@ checkentry(const char *tablename,
return 1;
}
-static struct xt_match esp_match = {
- .name = "esp",
- .family = AF_INET,
- .proto = IPPROTO_ESP,
- .match = &match,
- .matchsize = sizeof(struct xt_esp),
- .checkentry = &checkentry,
- .me = THIS_MODULE,
-};
-
-static struct xt_match esp6_match = {
- .name = "esp",
- .family = AF_INET6,
- .proto = IPPROTO_ESP,
- .match = &match,
- .matchsize = sizeof(struct xt_esp),
- .checkentry = &checkentry,
- .me = THIS_MODULE,
+static struct xt_match xt_esp_match[] = {
+ {
+ .name = "esp",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_esp),
+ .proto = IPPROTO_ESP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "esp",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_esp),
+ .proto = IPPROTO_ESP,
+ .me = THIS_MODULE,
+ },
};
static int __init xt_esp_init(void)
{
- int ret;
- ret = xt_register_match(&esp_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&esp6_match);
- if (ret)
- xt_unregister_match(&esp_match);
-
- return ret;
+ return xt_register_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match));
}
static void __exit xt_esp_cleanup(void)
{
- xt_unregister_match(&esp_match);
- xt_unregister_match(&esp6_match);
+ xt_unregister_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match));
}
module_init(xt_esp_init);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index 799c2a43e3b..5d7818b73e3 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -139,7 +139,6 @@ static int check(const char *tablename,
const void *inf,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
struct xt_helper_info *info = matchinfo;
@@ -156,52 +155,44 @@ static int check(const char *tablename,
}
static void
-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+destroy(const struct xt_match *match, void *matchinfo)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
-static struct xt_match helper_match = {
- .name = "helper",
- .match = match,
- .matchsize = sizeof(struct xt_helper_info),
- .checkentry = check,
- .destroy = destroy,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-static struct xt_match helper6_match = {
- .name = "helper",
- .match = match,
- .matchsize = sizeof(struct xt_helper_info),
- .checkentry = check,
- .destroy = destroy,
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_helper_match[] = {
+ {
+ .name = "helper",
+ .family = AF_INET,
+ .checkentry = check,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_helper_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "helper",
+ .family = AF_INET6,
+ .checkentry = check,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_helper_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_helper_init(void)
{
- int ret;
need_conntrack();
-
- ret = xt_register_match(&helper_match);
- if (ret < 0)
- return ret;
-
- ret = xt_register_match(&helper6_match);
- if (ret < 0)
- xt_unregister_match(&helper_match);
-
- return ret;
+ return xt_register_matches(xt_helper_match,
+ ARRAY_SIZE(xt_helper_match));
}
static void __exit xt_helper_fini(void)
{
- xt_unregister_match(&helper_match);
- xt_unregister_match(&helper6_match);
+ xt_unregister_matches(xt_helper_match, ARRAY_SIZE(xt_helper_match));
}
module_init(xt_helper_init);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 109132c9a14..67fd30d9f30 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -52,39 +52,32 @@ match6(const struct sk_buff *skb,
return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
}
-static struct xt_match length_match = {
- .name = "length",
- .match = match,
- .matchsize = sizeof(struct xt_length_info),
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match length6_match = {
- .name = "length",
- .match = match6,
- .matchsize = sizeof(struct xt_length_info),
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_length_match[] = {
+ {
+ .name = "length",
+ .family = AF_INET,
+ .match = match,
+ .matchsize = sizeof(struct xt_length_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "length",
+ .family = AF_INET6,
+ .match = match6,
+ .matchsize = sizeof(struct xt_length_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_length_init(void)
{
- int ret;
- ret = xt_register_match(&length_match);
- if (ret)
- return ret;
- ret = xt_register_match(&length6_match);
- if (ret)
- xt_unregister_match(&length_match);
-
- return ret;
+ return xt_register_matches(xt_length_match,
+ ARRAY_SIZE(xt_length_match));
}
static void __exit xt_length_fini(void)
{
- xt_unregister_match(&length_match);
- xt_unregister_match(&length6_match);
+ xt_unregister_matches(xt_length_match, ARRAY_SIZE(xt_length_match));
}
module_init(xt_length_init);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index ce7fdb7e4e0..fda7b7dec27 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -110,7 +110,6 @@ ipt_limit_checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
struct xt_rateinfo *r = matchinfo;
@@ -123,55 +122,95 @@ ipt_limit_checkentry(const char *tablename,
return 0;
}
- /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
- 128. */
- r->prev = jiffies;
- r->credit = user2credits(r->avg * r->burst); /* Credits full. */
- r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
- r->cost = user2credits(r->avg);
-
/* For SMP, we only want to use one set of counters. */
r->master = r;
-
+ if (r->cost == 0) {
+ /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
+ 128. */
+ r->prev = jiffies;
+ r->credit = user2credits(r->avg * r->burst); /* Credits full. */
+ r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
+ r->cost = user2credits(r->avg);
+ }
return 1;
}
-static struct xt_match ipt_limit_reg = {
- .name = "limit",
- .match = ipt_limit_match,
- .matchsize = sizeof(struct xt_rateinfo),
- .checkentry = ipt_limit_checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
+#ifdef CONFIG_COMPAT
+struct compat_xt_rateinfo {
+ u_int32_t avg;
+ u_int32_t burst;
+
+ compat_ulong_t prev;
+ u_int32_t credit;
+ u_int32_t credit_cap, cost;
+
+ u_int32_t master;
};
-static struct xt_match limit6_reg = {
- .name = "limit",
- .match = ipt_limit_match,
- .matchsize = sizeof(struct xt_rateinfo),
- .checkentry = ipt_limit_checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE,
+
+/* To keep the full "prev" timestamp, the upper 32 bits are stored in the
+ * master pointer, which does not need to be preserved. */
+static void compat_from_user(void *dst, void *src)
+{
+ struct compat_xt_rateinfo *cm = src;
+ struct xt_rateinfo m = {
+ .avg = cm->avg,
+ .burst = cm->burst,
+ .prev = cm->prev | (unsigned long)cm->master << 32,
+ .credit = cm->credit,
+ .credit_cap = cm->credit_cap,
+ .cost = cm->cost,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
+
+static int compat_to_user(void __user *dst, void *src)
+{
+ struct xt_rateinfo *m = src;
+ struct compat_xt_rateinfo cm = {
+ .avg = m->avg,
+ .burst = m->burst,
+ .prev = m->prev,
+ .credit = m->credit,
+ .credit_cap = m->credit_cap,
+ .cost = m->cost,
+ .master = m->prev >> 32,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct xt_match xt_limit_match[] = {
+ {
+ .name = "limit",
+ .family = AF_INET,
+ .checkentry = ipt_limit_checkentry,
+ .match = ipt_limit_match,
+ .matchsize = sizeof(struct xt_rateinfo),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_rateinfo),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
+#endif
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "limit",
+ .family = AF_INET6,
+ .checkentry = ipt_limit_checkentry,
+ .match = ipt_limit_match,
+ .matchsize = sizeof(struct xt_rateinfo),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_limit_init(void)
{
- int ret;
-
- ret = xt_register_match(&ipt_limit_reg);
- if (ret)
- return ret;
-
- ret = xt_register_match(&limit6_reg);
- if (ret)
- xt_unregister_match(&ipt_limit_reg);
-
- return ret;
+ return xt_register_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match));
}
static void __exit xt_limit_fini(void)
{
- xt_unregister_match(&ipt_limit_reg);
- xt_unregister_match(&limit6_reg);
+ xt_unregister_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match));
}
module_init(xt_limit_init);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 356290ffe38..425fc21e31f 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -43,43 +43,37 @@ match(const struct sk_buff *skb,
^ info->invert));
}
-static struct xt_match mac_match = {
- .name = "mac",
- .match = match,
- .matchsize = sizeof(struct xt_mac_info),
- .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
- (1 << NF_IP_FORWARD),
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-static struct xt_match mac6_match = {
- .name = "mac",
- .match = match,
- .matchsize = sizeof(struct xt_mac_info),
- .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
- (1 << NF_IP_FORWARD),
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_mac_match[] = {
+ {
+ .name = "mac",
+ .family = AF_INET,
+ .match = match,
+ .matchsize = sizeof(struct xt_mac_info),
+ .hooks = (1 << NF_IP_PRE_ROUTING) |
+ (1 << NF_IP_LOCAL_IN) |
+ (1 << NF_IP_FORWARD),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "mac",
+ .family = AF_INET6,
+ .match = match,
+ .matchsize = sizeof(struct xt_mac_info),
+ .hooks = (1 << NF_IP_PRE_ROUTING) |
+ (1 << NF_IP_LOCAL_IN) |
+ (1 << NF_IP_FORWARD),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_mac_init(void)
{
- int ret;
- ret = xt_register_match(&mac_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&mac6_match);
- if (ret)
- xt_unregister_match(&mac_match);
-
- return ret;
+ return xt_register_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match));
}
static void __exit xt_mac_fini(void)
{
- xt_unregister_match(&mac_match);
- xt_unregister_match(&mac6_match);
+ xt_unregister_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match));
}
module_init(xt_mac_init);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 876bc579773..934dddfbcd2 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -39,7 +39,6 @@ checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_mark_info *minfo = matchinfo;
@@ -51,42 +50,69 @@ checkentry(const char *tablename,
return 1;
}
-static struct xt_match mark_match = {
- .name = "mark",
- .match = match,
- .matchsize = sizeof(struct xt_mark_info),
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
+#ifdef CONFIG_COMPAT
+struct compat_xt_mark_info {
+ compat_ulong_t mark, mask;
+ u_int8_t invert;
+ u_int8_t __pad1;
+ u_int16_t __pad2;
};
-static struct xt_match mark6_match = {
- .name = "mark",
- .match = match,
- .matchsize = sizeof(struct xt_mark_info),
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE,
-};
+static void compat_from_user(void *dst, void *src)
+{
+ struct compat_xt_mark_info *cm = src;
+ struct xt_mark_info m = {
+ .mark = cm->mark,
+ .mask = cm->mask,
+ .invert = cm->invert,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
-static int __init xt_mark_init(void)
+static int compat_to_user(void __user *dst, void *src)
{
- int ret;
- ret = xt_register_match(&mark_match);
- if (ret)
- return ret;
+ struct xt_mark_info *m = src;
+ struct compat_xt_mark_info cm = {
+ .mark = m->mark,
+ .mask = m->mask,
+ .invert = m->invert,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif /* CONFIG_COMPAT */
- ret = xt_register_match(&mark6_match);
- if (ret)
- xt_unregister_match(&mark_match);
+static struct xt_match xt_mark_match[] = {
+ {
+ .name = "mark",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_mark_info),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_mark_info),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
+#endif
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "mark",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_mark_info),
+ .me = THIS_MODULE,
+ },
+};
- return ret;
+static int __init xt_mark_init(void)
+{
+ return xt_register_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match));
}
static void __exit xt_mark_fini(void)
{
- xt_unregister_match(&mark_match);
- xt_unregister_match(&mark6_match);
+ xt_unregister_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match));
}
module_init(xt_mark_init);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index 1ff0a25396e..d3aefd38093 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -176,7 +176,6 @@ checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct ipt_ip *ip = info;
@@ -191,7 +190,6 @@ checkentry_v1(const char *tablename,
const void *info,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct ipt_ip *ip = info;
@@ -206,7 +204,6 @@ checkentry6(const char *tablename,
const void *info,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct ip6t_ip6 *ip = info;
@@ -221,7 +218,6 @@ checkentry6_v1(const char *tablename,
const void *info,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct ip6t_ip6 *ip = info;
@@ -231,84 +227,55 @@ checkentry6_v1(const char *tablename,
multiinfo->count);
}
-static struct xt_match multiport_match = {
- .name = "multiport",
- .revision = 0,
- .matchsize = sizeof(struct xt_multiport),
- .match = &match,
- .checkentry = &checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match multiport_match_v1 = {
- .name = "multiport",
- .revision = 1,
- .matchsize = sizeof(struct xt_multiport_v1),
- .match = &match_v1,
- .checkentry = &checkentry_v1,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match multiport6_match = {
- .name = "multiport",
- .revision = 0,
- .matchsize = sizeof(struct xt_multiport),
- .match = &match,
- .checkentry = &checkentry6,
- .family = AF_INET6,
- .me = THIS_MODULE,
-};
-
-static struct xt_match multiport6_match_v1 = {
- .name = "multiport",
- .revision = 1,
- .matchsize = sizeof(struct xt_multiport_v1),
- .match = &match_v1,
- .checkentry = &checkentry6_v1,
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_multiport_match[] = {
+ {
+ .name = "multiport",
+ .family = AF_INET,
+ .revision = 0,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_multiport),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "multiport",
+ .family = AF_INET,
+ .revision = 1,
+ .checkentry = checkentry_v1,
+ .match = match_v1,
+ .matchsize = sizeof(struct xt_multiport_v1),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "multiport",
+ .family = AF_INET6,
+ .revision = 0,
+ .checkentry = checkentry6,
+ .match = match,
+ .matchsize = sizeof(struct xt_multiport),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "multiport",
+ .family = AF_INET6,
+ .revision = 1,
+ .checkentry = checkentry6_v1,
+ .match = match_v1,
+ .matchsize = sizeof(struct xt_multiport_v1),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_multiport_init(void)
{
- int ret;
-
- ret = xt_register_match(&multiport_match);
- if (ret)
- goto out;
-
- ret = xt_register_match(&multiport_match_v1);
- if (ret)
- goto out_unreg_multi_v0;
-
- ret = xt_register_match(&multiport6_match);
- if (ret)
- goto out_unreg_multi_v1;
-
- ret = xt_register_match(&multiport6_match_v1);
- if (ret)
- goto out_unreg_multi6_v0;
-
- return ret;
-
-out_unreg_multi6_v0:
- xt_unregister_match(&multiport6_match);
-out_unreg_multi_v1:
- xt_unregister_match(&multiport_match_v1);
-out_unreg_multi_v0:
- xt_unregister_match(&multiport_match);
-out:
- return ret;
+ return xt_register_matches(xt_multiport_match,
+ ARRAY_SIZE(xt_multiport_match));
}
static void __exit xt_multiport_fini(void)
{
- xt_unregister_match(&multiport_match);
- xt_unregister_match(&multiport_match_v1);
- xt_unregister_match(&multiport6_match);
- xt_unregister_match(&multiport6_match_v1);
+ xt_unregister_matches(xt_multiport_match,
+ ARRAY_SIZE(xt_multiport_match));
}
module_init(xt_multiport_init);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 63a96546746..fd8f954cded 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -106,7 +106,6 @@ checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_physdev_info *info = matchinfo;
@@ -132,43 +131,34 @@ checkentry(const char *tablename,
return 1;
}
-static struct xt_match physdev_match = {
- .name = "physdev",
- .match = match,
- .matchsize = sizeof(struct xt_physdev_info),
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match physdev6_match = {
- .name = "physdev",
- .match = match,
- .matchsize = sizeof(struct xt_physdev_info),
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_physdev_match[] = {
+ {
+ .name = "physdev",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_physdev_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "physdev",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_physdev_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_physdev_init(void)
{
- int ret;
-
- ret = xt_register_match(&physdev_match);
- if (ret < 0)
- return ret;
-
- ret = xt_register_match(&physdev6_match);
- if (ret < 0)
- xt_unregister_match(&physdev_match);
-
- return ret;
+ return xt_register_matches(xt_physdev_match,
+ ARRAY_SIZE(xt_physdev_match));
}
static void __exit xt_physdev_fini(void)
{
- xt_unregister_match(&physdev_match);
- xt_unregister_match(&physdev6_match);
+ xt_unregister_matches(xt_physdev_match, ARRAY_SIZE(xt_physdev_match));
}
module_init(xt_physdev_init);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index d2f5320a80b..16e7b080428 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -43,40 +43,32 @@ static int match(const struct sk_buff *skb,
return (type == info->pkttype) ^ info->invert;
}
-static struct xt_match pkttype_match = {
- .name = "pkttype",
- .match = match,
- .matchsize = sizeof(struct xt_pkttype_info),
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match pkttype6_match = {
- .name = "pkttype",
- .match = match,
- .matchsize = sizeof(struct xt_pkttype_info),
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_pkttype_match[] = {
+ {
+ .name = "pkttype",
+ .family = AF_INET,
+ .match = match,
+ .matchsize = sizeof(struct xt_pkttype_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "pkttype",
+ .family = AF_INET6,
+ .match = match,
+ .matchsize = sizeof(struct xt_pkttype_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_pkttype_init(void)
{
- int ret;
- ret = xt_register_match(&pkttype_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&pkttype6_match);
- if (ret)
- xt_unregister_match(&pkttype_match);
-
- return ret;
+ return xt_register_matches(xt_pkttype_match,
+ ARRAY_SIZE(xt_pkttype_match));
}
static void __exit xt_pkttype_fini(void)
{
- xt_unregister_match(&pkttype_match);
- xt_unregister_match(&pkttype6_match);
+ xt_unregister_matches(xt_pkttype_match, ARRAY_SIZE(xt_pkttype_match));
}
module_init(xt_pkttype_init);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index ba1ca03abad..46bde2b1e1e 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -135,8 +135,7 @@ static int match(const struct sk_buff *skb,
static int checkentry(const char *tablename, const void *ip_void,
const struct xt_match *match,
- void *matchinfo, unsigned int matchsize,
- unsigned int hook_mask)
+ void *matchinfo, unsigned int hook_mask)
{
struct xt_policy_info *info = matchinfo;
@@ -165,43 +164,34 @@ static int checkentry(const char *tablename, const void *ip_void,
return 1;
}
-static struct xt_match policy_match = {
- .name = "policy",
- .family = AF_INET,
- .match = match,
- .matchsize = sizeof(struct xt_policy_info),
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match policy6_match = {
- .name = "policy",
- .family = AF_INET6,
- .match = match,
- .matchsize = sizeof(struct xt_policy_info),
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_policy_match[] = {
+ {
+ .name = "policy",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_policy_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "policy",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_policy_info),
+ .me = THIS_MODULE,
+ },
};
static int __init init(void)
{
- int ret;
-
- ret = xt_register_match(&policy_match);
- if (ret)
- return ret;
- ret = xt_register_match(&policy6_match);
- if (ret)
- xt_unregister_match(&policy_match);
- return ret;
+ return xt_register_matches(xt_policy_match,
+ ARRAY_SIZE(xt_policy_match));
}
static void __exit fini(void)
{
- xt_unregister_match(&policy6_match);
- xt_unregister_match(&policy_match);
+ xt_unregister_matches(xt_policy_match, ARRAY_SIZE(xt_policy_match));
}
module_init(init);
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index be8d3c26b56..b75fa2c70e6 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -41,7 +41,7 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename, const void *entry,
const struct xt_match *match, void *matchinfo,
- unsigned int matchsize, unsigned int hook_mask)
+ unsigned int hook_mask)
{
struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
@@ -52,46 +52,33 @@ checkentry(const char *tablename, const void *entry,
return 1;
}
-static struct xt_match quota_match = {
- .name = "quota",
- .family = AF_INET,
- .match = match,
- .matchsize = sizeof(struct xt_quota_info),
- .checkentry = checkentry,
- .me = THIS_MODULE
-};
-
-static struct xt_match quota_match6 = {
- .name = "quota",
- .family = AF_INET6,
- .match = match,
- .matchsize = sizeof(struct xt_quota_info),
- .checkentry = checkentry,
- .me = THIS_MODULE
+static struct xt_match xt_quota_match[] = {
+ {
+ .name = "quota",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_quota_info),
+ .me = THIS_MODULE
+ },
+ {
+ .name = "quota",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_quota_info),
+ .me = THIS_MODULE
+ },
};
static int __init xt_quota_init(void)
{
- int ret;
-
- ret = xt_register_match(&quota_match);
- if (ret)
- goto err1;
- ret = xt_register_match(&quota_match6);
- if (ret)
- goto err2;
- return ret;
-
-err2:
- xt_unregister_match(&quota_match);
-err1:
- return ret;
+ return xt_register_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match));
}
static void __exit xt_quota_fini(void)
{
- xt_unregister_match(&quota_match6);
- xt_unregister_match(&quota_match);
+ xt_unregister_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match));
}
module_init(xt_quota_init);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 843383e01d4..7956acaaa24 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -163,7 +163,6 @@ checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_sctp_info *info = matchinfo;
@@ -178,44 +177,35 @@ checkentry(const char *tablename,
| SCTP_CHUNK_MATCH_ONLY)));
}
-static struct xt_match sctp_match = {
- .name = "sctp",
- .match = match,
- .matchsize = sizeof(struct xt_sctp_info),
- .proto = IPPROTO_SCTP,
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE
-};
-
-static struct xt_match sctp6_match = {
- .name = "sctp",
- .match = match,
- .matchsize = sizeof(struct xt_sctp_info),
- .proto = IPPROTO_SCTP,
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE
+static struct xt_match xt_sctp_match[] = {
+ {
+ .name = "sctp",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_sctp_info),
+ .proto = IPPROTO_SCTP,
+ .me = THIS_MODULE
+ },
+ {
+ .name = "sctp",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_sctp_info),
+ .proto = IPPROTO_SCTP,
+ .me = THIS_MODULE
+ },
};
static int __init xt_sctp_init(void)
{
- int ret;
- ret = xt_register_match(&sctp_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&sctp6_match);
- if (ret)
- xt_unregister_match(&sctp_match);
-
- return ret;
+ return xt_register_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match));
}
static void __exit xt_sctp_fini(void)
{
- xt_unregister_match(&sctp6_match);
- xt_unregister_match(&sctp_match);
+ xt_unregister_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match));
}
module_init(xt_sctp_init);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index f9e304dc450..d9010b16a1f 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -48,7 +48,6 @@ static int check(const char *tablename,
const void *inf,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -62,54 +61,43 @@ static int check(const char *tablename,
}
static void
-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+destroy(const struct xt_match *match, void *matchinfo)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
-static struct xt_match state_match = {
- .name = "state",
- .match = match,
- .checkentry = check,
- .destroy = destroy,
- .matchsize = sizeof(struct xt_state_info),
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match state6_match = {
- .name = "state",
- .match = match,
- .checkentry = check,
- .destroy = destroy,
- .matchsize = sizeof(struct xt_state_info),
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_state_match[] = {
+ {
+ .name = "state",
+ .family = AF_INET,
+ .checkentry = check,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_state_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "state",
+ .family = AF_INET6,
+ .checkentry = check,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_state_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_state_init(void)
{
- int ret;
-
need_conntrack();
-
- ret = xt_register_match(&state_match);
- if (ret < 0)
- return ret;
-
- ret = xt_register_match(&state6_match);
- if (ret < 0)
- xt_unregister_match(&state_match);
-
- return ret;
+ return xt_register_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
}
static void __exit xt_state_fini(void)
{
- xt_unregister_match(&state_match);
- xt_unregister_match(&state6_match);
+ xt_unregister_matches(xt_state_match, ARRAY_SIZE(xt_state_match));
}
module_init(xt_state_init);
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index de1037f5859..091a9f89f5d 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -55,7 +55,7 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename, const void *entry,
const struct xt_match *match, void *matchinfo,
- unsigned int matchsize, unsigned int hook_mask)
+ unsigned int hook_mask)
{
struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
@@ -66,46 +66,35 @@ checkentry(const char *tablename, const void *entry,
return 1;
}
-static struct xt_match statistic_match = {
- .name = "statistic",
- .match = match,
- .matchsize = sizeof(struct xt_statistic_info),
- .checkentry = checkentry,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match statistic_match6 = {
- .name = "statistic",
- .match = match,
- .matchsize = sizeof(struct xt_statistic_info),
- .checkentry = checkentry,
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_statistic_match[] = {
+ {
+ .name = "statistic",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_statistic_info),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "statistic",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .matchsize = sizeof(struct xt_statistic_info),
+ .me = THIS_MODULE,
+ },
};
static int __init xt_statistic_init(void)
{
- int ret;
-
- ret = xt_register_match(&statistic_match);
- if (ret)
- goto err1;
-
- ret = xt_register_match(&statistic_match6);
- if (ret)
- goto err2;
- return ret;
-err2:
- xt_unregister_match(&statistic_match);
-err1:
- return ret;
+ return xt_register_matches(xt_statistic_match,
+ ARRAY_SIZE(xt_statistic_match));
}
static void __exit xt_statistic_fini(void)
{
- xt_unregister_match(&statistic_match6);
- xt_unregister_match(&statistic_match);
+ xt_unregister_matches(xt_statistic_match,
+ ARRAY_SIZE(xt_statistic_match));
}
module_init(xt_statistic_init);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 275330fcdaa..4453252400a 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -46,7 +46,6 @@ static int checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
struct xt_string_info *conf = matchinfo;
@@ -69,49 +68,40 @@ static int checkentry(const char *tablename,
return 1;
}
-static void destroy(const struct xt_match *match, void *matchinfo,
- unsigned int matchsize)
+static void destroy(const struct xt_match *match, void *matchinfo)
{
textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
}
-static struct xt_match string_match = {
- .name = "string",
- .match = match,
- .matchsize = sizeof(struct xt_string_info),
- .checkentry = checkentry,
- .destroy = destroy,
- .family = AF_INET,
- .me = THIS_MODULE
-};
-static struct xt_match string6_match = {
- .name = "string",
- .match = match,
- .matchsize = sizeof(struct xt_string_info),
- .checkentry = checkentry,
- .destroy = destroy,
- .family = AF_INET6,
- .me = THIS_MODULE
+static struct xt_match xt_string_match[] = {
+ {
+ .name = "string",
+ .family = AF_INET,
+ .checkentry = checkentry,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_string_info),
+ .me = THIS_MODULE
+ },
+ {
+ .name = "string",
+ .family = AF_INET6,
+ .checkentry = checkentry,
+ .match = match,
+ .destroy = destroy,
+ .matchsize = sizeof(struct xt_string_info),
+ .me = THIS_MODULE
+ },
};
static int __init xt_string_init(void)
{
- int ret;
-
- ret = xt_register_match(&string_match);
- if (ret)
- return ret;
- ret = xt_register_match(&string6_match);
- if (ret)
- xt_unregister_match(&string_match);
-
- return ret;
+ return xt_register_matches(xt_string_match, ARRAY_SIZE(xt_string_match));
}
static void __exit xt_string_fini(void)
{
- xt_unregister_match(&string_match);
- xt_unregister_match(&string6_match);
+ xt_unregister_matches(xt_string_match, ARRAY_SIZE(xt_string_match));
}
module_init(xt_string_init);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index cf7d335cadc..a3682fe2f19 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -18,21 +18,22 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
-#define TH_SYN 0x02
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables TCP MSS match module");
MODULE_ALIAS("ipt_tcpmss");
-/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
-static inline int
-mssoption_match(u_int16_t min, u_int16_t max,
- const struct sk_buff *skb,
- unsigned int protoff,
- int invert,
- int *hotdrop)
+static int
+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,
+ int *hotdrop)
{
+ const struct xt_tcpmss_match_info *info = matchinfo;
struct tcphdr _tcph, *th;
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
u8 _opt[15 * 4 - sizeof(_tcph)], *op;
@@ -64,72 +65,50 @@ mssoption_match(u_int16_t min, u_int16_t max,
mssval = (op[i+2] << 8) | op[i+3];
- return (mssval >= min && mssval <= max) ^ invert;
+ return (mssval >= info->mss_min &&
+ mssval <= info->mss_max) ^ info->invert;
}
- if (op[i] < 2) i++;
- else i += op[i+1]?:1;
+ if (op[i] < 2)
+ i++;
+ else
+ i += op[i+1] ? : 1;
}
out:
- return invert;
+ return info->invert;
- dropit:
+dropit:
*hotdrop = 1;
return 0;
}
-static int
-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,
- int *hotdrop)
-{
- const struct xt_tcpmss_match_info *info = matchinfo;
-
- return mssoption_match(info->mss_min, info->mss_max, skb, protoff,
- info->invert, hotdrop);
-}
-
-static struct xt_match tcpmss_match = {
- .name = "tcpmss",
- .match = match,
- .matchsize = sizeof(struct xt_tcpmss_match_info),
- .proto = IPPROTO_TCP,
- .family = AF_INET,
- .me = THIS_MODULE,
-};
-
-static struct xt_match tcpmss6_match = {
- .name = "tcpmss",
- .match = match,
- .matchsize = sizeof(struct xt_tcpmss_match_info),
- .proto = IPPROTO_TCP,
- .family = AF_INET6,
- .me = THIS_MODULE,
+static struct xt_match xt_tcpmss_match[] = {
+ {
+ .name = "tcpmss",
+ .family = AF_INET,
+ .match = match,
+ .matchsize = sizeof(struct xt_tcpmss_match_info),
+ .proto = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "tcpmss",
+ .family = AF_INET6,
+ .match = match,
+ .matchsize = sizeof(struct xt_tcpmss_match_info),
+ .proto = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ },
};
-
static int __init xt_tcpmss_init(void)
{
- int ret;
- ret = xt_register_match(&tcpmss_match);
- if (ret)
- return ret;
-
- ret = xt_register_match(&tcpmss6_match);
- if (ret)
- xt_unregister_match(&tcpmss_match);
-
- return ret;
+ return xt_register_matches(xt_tcpmss_match,
+ ARRAY_SIZE(xt_tcpmss_match));
}
static void __exit xt_tcpmss_fini(void)
{
- xt_unregister_match(&tcpmss6_match);
- xt_unregister_match(&tcpmss_match);
+ xt_unregister_matches(xt_tcpmss_match, ARRAY_SIZE(xt_tcpmss_match));
}
module_init(xt_tcpmss_init);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index a9a63aa6893..e76a68e0bc6 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -141,7 +141,6 @@ tcp_checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_tcp *tcpinfo = matchinfo;
@@ -190,7 +189,6 @@ udp_checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
void *matchinfo,
- unsigned int matchsize,
unsigned int hook_mask)
{
const struct xt_tcp *udpinfo = matchinfo;
@@ -199,81 +197,54 @@ udp_checkentry(const char *tablename,
return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
}
-static struct xt_match tcp_matchstruct = {
- .name = "tcp",
- .match = tcp_match,
- .matchsize = sizeof(struct xt_tcp),
- .proto = IPPROTO_TCP,
- .family = AF_INET,
- .checkentry = tcp_checkentry,
- .me = THIS_MODULE,
-};
-
-static struct xt_match tcp6_matchstruct = {
- .name = "tcp",
- .match = tcp_match,
- .matchsize = sizeof(struct xt_tcp),
- .proto = IPPROTO_TCP,
- .family = AF_INET6,
- .checkentry = tcp_checkentry,
- .me = THIS_MODULE,
-};
-
-static struct xt_match udp_matchstruct = {
- .name = "udp",
- .match = udp_match,
- .matchsize = sizeof(struct xt_udp),
- .proto = IPPROTO_UDP,
- .family = AF_INET,
- .checkentry = udp_checkentry,
- .me = THIS_MODULE,
-};
-static struct xt_match udp6_matchstruct = {
- .name = "udp",
- .match = udp_match,
- .matchsize = sizeof(struct xt_udp),
- .proto = IPPROTO_UDP,
- .family = AF_INET6,
- .checkentry = udp_checkentry,
- .me = THIS_MODULE,
+static struct xt_match xt_tcpudp_match[] = {
+ {
+ .name = "tcp",
+ .family = AF_INET,
+ .checkentry = tcp_checkentry,
+ .match = tcp_match,
+ .matchsize = sizeof(struct xt_tcp),
+ .proto = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "tcp",
+ .family = AF_INET6,
+ .checkentry = tcp_checkentry,
+ .match = tcp_match,
+ .matchsize = sizeof(struct xt_tcp),
+ .proto = IPPROTO_TCP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "udp",
+ .family = AF_INET,
+ .checkentry = udp_checkentry,
+ .match = udp_match,
+ .matchsize = sizeof(struct xt_udp),
+ .proto = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "udp",
+ .family = AF_INET6,
+ .checkentry = udp_checkentry,
+ .match = udp_match,
+ .matchsize = sizeof(struct xt_udp),
+ .proto = IPPROTO_UDP,
+ .me = THIS_MODULE,
+ },
};
static int __init xt_tcpudp_init(void)
{
- int ret;
- ret = xt_register_match(&tcp_matchstruct);
- if (ret)
- return ret;
-
- ret = xt_register_match(&tcp6_matchstruct);
- if (ret)
- goto out_unreg_tcp;
-
- ret = xt_register_match(&udp_matchstruct);
- if (ret)
- goto out_unreg_tcp6;
-
- ret = xt_register_match(&udp6_matchstruct);
- if (ret)
- goto out_unreg_udp;
-
- return ret;
-
-out_unreg_udp:
- xt_unregister_match(&udp_matchstruct);
-out_unreg_tcp6:
- xt_unregister_match(&tcp6_matchstruct);
-out_unreg_tcp:
- xt_unregister_match(&tcp_matchstruct);
- return ret;
+ return xt_register_matches(xt_tcpudp_match,
+ ARRAY_SIZE(xt_tcpudp_match));
}
static void __exit xt_tcpudp_fini(void)
{
- xt_unregister_match(&udp6_matchstruct);
- xt_unregister_match(&udp_matchstruct);
- xt_unregister_match(&tcp6_matchstruct);
- xt_unregister_match(&tcp_matchstruct);
+ xt_unregister_matches(xt_tcpudp_match, ARRAY_SIZE(xt_tcpudp_match));
}
module_init(xt_tcpudp_init);