From: Massimiliano Hofer <max@nucleus.it>
To: netfilter-devel@lists.netfilter.org
Subject: [PATCH 1/2][priv_data-condition][part 1/2][core]
Date: Mon, 25 Sep 2006 10:16:33 +0200 [thread overview]
Message-ID: <200609251016.33590.max@nucleus.it> (raw)
In-Reply-To: <200609250040.49298.max@nucleus.it>
From 8fc22c9b95e4bfa7f56a303587bdcd6f01a6ce52 Mon Sep 17 00:00:00 2001
From: Massimiliano Hofer <max@nucleus.it>
Date: Mon, 25 Sep 2006 10:06:12 +0200
Subject: [PATCH] priv_data
This patch adds support for instance specific data in matches and
targets.
I seize the opportunity of this massive function parameter change
to rename checkentry as init.
This is the core implementation. It won't compile without the
corresponding updates in matches and targets (in the following
patch).
Signed-off-by: Massimiliano Hofer <max@nucleus.it>
---
include/linux/netfilter/x_tables.h | 58 +++++++++------
net/ipv4/netfilter/arp_tables.c | 49 ++++++-------
net/ipv4/netfilter/ip_tables.c | 141 +++++++++++++++++-------------------
net/ipv6/netfilter/ip6_tables.c | 109 +++++++++++++---------------
net/netfilter/x_tables.c | 95 ++++++++++++++++++++++--
5 files changed, 258 insertions(+), 194 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 04319a7..e855fd2 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -20,6 +20,7 @@ struct xt_entry_match
/* Used inside the kernel */
struct xt_match *match;
+ void *priv_data;
} kernel;
/* Total length */
@@ -45,6 +46,7 @@ struct xt_entry_target
/* Used inside the kernel */
struct xt_target *target;
+ void *priv_data;
} kernel;
/* Total length */
@@ -156,18 +158,21 @@ struct xt_match
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop);
+ int *hotdrop,
+ void *priv_data);
/* Called when user tries to insert an entry of this type. */
/* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask);
+ int (*init)(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask,
+ void *priv_data);
/* Called when entry of this type deleted. */
- void (*destroy)(const struct xt_match *match, void *matchinfo);
+ void (*destroy)(const struct xt_match *match, void *matchinfo,
+ void *priv_data);
/* Called when userspace align differs from kernel space one */
void (*compat_from_user)(void *dst, void *src);
@@ -182,6 +187,7 @@ struct xt_match
char *table;
unsigned int matchsize;
unsigned int compatsize;
+ size_t priv_size;
unsigned int hooks;
unsigned short proto;
@@ -204,20 +210,23 @@ struct xt_target
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo);
+ const void *targinfo,
+ void *priv_data);
/* Called when user tries to insert an entry of this type:
hook_mask is a bitmask of hooks from which it can be
called. */
/* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask);
+ int (*init)(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask,
+ void *priv_data);
/* Called when entry of this type deleted. */
- void (*destroy)(const struct xt_target *target, void *targinfo);
+ void (*destroy)(const struct xt_target *target, void *targinfo,
+ void *priv_data);
/* Called when userspace align differs from kernel space one */
void (*compat_from_user)(void *dst, void *src);
@@ -229,6 +238,7 @@ struct xt_target
char *table;
unsigned int targetsize;
unsigned int compatsize;
+ size_t priv_size;
unsigned int hooks;
unsigned short proto;
@@ -290,12 +300,16 @@ extern void xt_unregister_match(struct x
extern int xt_register_matches(struct xt_match *match, unsigned int n);
extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
-extern int xt_check_match(const struct xt_match *match, unsigned short family,
- unsigned int size, const char *table, unsigned int hook,
- unsigned short proto, int inv_proto);
-extern int xt_check_target(const struct xt_target *target, unsigned short family,
- unsigned int size, const char *table, unsigned int hook,
- unsigned short proto, int inv_proto);
+extern int xt_init_match(struct xt_entry_match *m, char *module_prefix,
+ unsigned short family, const char *table,
+ unsigned int hook_mask, unsigned short proto,
+ int inv_proto);
+extern void xt_destroy_match(struct xt_entry_match *m);
+extern int xt_init_target(struct xt_entry_target *t, char *module_prefix,
+ unsigned short family, const char *table,
+ unsigned int hook_mask, unsigned short proto,
+ int inv_proto);
+extern void xt_destroy_target(struct xt_entry_target *m);
extern int xt_register_table(struct xt_table *table,
struct xt_table_info *bootstrap,
@@ -390,13 +404,13 @@ extern int xt_compat_match_offset(struct
extern void xt_compat_match_from_user(struct xt_entry_match *m,
void **dstptr, int *size);
extern int xt_compat_match_to_user(struct xt_entry_match *m,
- void __user **dstptr, int *size);
+ void * __user *dstptr, int *size);
extern int xt_compat_target_offset(struct xt_target *target);
extern void xt_compat_target_from_user(struct xt_entry_target *t,
void **dstptr, int *size);
extern int xt_compat_target_to_user(struct xt_entry_target *t,
- void __user **dstptr, int *size);
+ void * __user *dstptr, int *size);
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 85f0d73..e6fbe3a 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -206,7 +206,8 @@ static unsigned int arpt_error(struct sk
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo)
+ const void *targinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("arp_tables: error: '%s'\n", (char *)targinfo);
@@ -294,11 +295,13 @@ unsigned int arpt_do_table(struct sk_buf
/* Targets which reenter must return
* abs. verdicts
*/
- verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data);
+ verdict = t->u.kernel.target->target(
+ pskb,
+ in, out,
+ hook,
+ t->u.kernel.target,
+ t->data,
+ t->u.kernel.priv_data);
/* Target might have changed stuff. */
arp = (*pskb)->nh.arph;
@@ -454,11 +457,10 @@ static inline int standard_check(const s
static struct arpt_target arpt_standard_target;
-static inline int check_entry(struct arpt_entry *e, const char *name, unsigned int size,
+static inline int init_entry(struct arpt_entry *e, const char *name, unsigned int size,
unsigned int *i)
{
struct arpt_entry_target *t;
- struct arpt_target *target;
int ret;
if (!arp_checkentry(&e->arp)) {
@@ -467,18 +469,9 @@ static inline int check_entry(struct arp
}
t = arpt_get_target(e);
- target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
- t->u.user.revision),
- "arpt_%s", t->u.user.name);
- if (IS_ERR(target) || !target) {
- duprintf("check_entry: `%s' not found\n", t->u.user.name);
- ret = target ? PTR_ERR(target) : -ENOENT;
- goto out;
- }
- t->u.kernel.target = target;
+ ret = xt_init_target(t, "arpt", NF_ARP,
+ name, e->comefrom, 0, 0);
- ret = xt_check_target(target, NF_ARP, t->u.target_size - sizeof(*t),
- name, e->comefrom, 0, 0);
if (ret)
goto err;
@@ -487,9 +480,11 @@ static inline int check_entry(struct arp
ret = -EINVAL;
goto err;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("arp_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -499,8 +494,7 @@ static inline int check_entry(struct arp
(*i)++;
return 0;
err:
- module_put(t->u.kernel.target->me);
-out:
+ xt_destroy_target(t);
return ret;
}
@@ -555,8 +549,9 @@ static inline int cleanup_entry(struct a
t = arpt_get_target(e);
if (t->u.kernel.target->destroy)
- t->u.kernel.target->destroy(t->u.kernel.target, t->data);
- module_put(t->u.kernel.target->me);
+ t->u.kernel.target->destroy(t->u.kernel.target, t->data,
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -629,7 +624,7 @@ static int translate_table(const char *n
/* Finally, each sanity check must pass */
i = 0;
ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
- check_entry, name, size, &i);
+ init_entry, name, size, &i);
if (ret != 0) {
ARPT_ENTRY_ITERATE(entry0, newinfo->size,
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 78a44b0..d96f322 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -180,7 +180,8 @@ ipt_error(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo)
+ const void *targinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("ip_tables: error: `%s'\n", (char *)targinfo);
@@ -198,7 +199,8 @@ int do_match(struct ipt_entry_match *m,
{
/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
- offset, skb->nh.iph->ihl*4, hotdrop))
+ offset, skb->nh.iph->ihl*4, hotdrop,
+ m->u.kernel.priv_data))
return 1;
else
return 0;
@@ -306,7 +308,8 @@ #endif
in, out,
hook,
t->u.kernel.target,
- t->data);
+ t->data,
+ t->u.kernel.priv_data);
#ifdef CONFIG_NETFILTER_DEBUG
if (((struct ipt_entry *)table_base)->comefrom
@@ -464,8 +467,9 @@ cleanup_match(struct ipt_entry_match *m,
return 1;
if (m->u.kernel.match->destroy)
- m->u.kernel.match->destroy(m->u.kernel.match, m->data);
- module_put(m->u.kernel.match->me);
+ m->u.kernel.match->destroy(m->u.kernel.match, m->data,
+ m->u.kernel.priv_data);
+ xt_destroy_match(m);
return 0;
}
@@ -491,33 +495,24 @@ standard_check(const struct ipt_entry_ta
}
static inline int
-check_match(struct ipt_entry_match *m,
- const char *name,
- const struct ipt_ip *ip,
- unsigned int hookmask,
- unsigned int *i)
+init_match(struct ipt_entry_match *m,
+ const char *name,
+ const struct ipt_ip *ip,
+ unsigned int hookmask,
+ unsigned int *i)
{
- struct ipt_match *match;
int ret;
- match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
- m->u.user.revision),
- "ipt_%s", m->u.user.name);
- if (IS_ERR(match) || !match) {
- duprintf("check_match: `%s' not found\n", m->u.user.name);
- return match ? PTR_ERR(match) : -ENOENT;
- }
- m->u.kernel.match = match;
-
- ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
- name, hookmask, ip->proto,
- ip->invflags & IPT_INV_PROTO);
+ ret = xt_init_match(m, "ipt", AF_INET,
+ name, hookmask, ip->proto,
+ ip->invflags & IPT_INV_PROTO);
if (ret)
goto err;
- if (m->u.kernel.match->checkentry
- && !m->u.kernel.match->checkentry(name, ip, match, m->data,
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ip, m->u.kernel.match,
+ m->data,
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -527,18 +522,17 @@ check_match(struct ipt_entry_match *m,
(*i)++;
return 0;
err:
- module_put(m->u.kernel.match->me);
+ xt_destroy_match(m);
return ret;
}
static struct ipt_target ipt_standard_target;
static inline int
-check_entry(struct ipt_entry *e, const char *name, unsigned int size,
+init_entry(struct ipt_entry *e, const char *name, unsigned int size,
unsigned int *i)
{
struct ipt_entry_target *t;
- struct ipt_target *target;
int ret;
unsigned int j;
@@ -548,25 +542,14 @@ check_entry(struct ipt_entry *e, const c
}
j = 0;
- ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
+ ret = IPT_MATCH_ITERATE(e, init_match, name, &e->ip, e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ipt_get_target(e);
- target = try_then_request_module(xt_find_target(AF_INET,
- t->u.user.name,
- t->u.user.revision),
- "ipt_%s", t->u.user.name);
- if (IS_ERR(target) || !target) {
- duprintf("check_entry: `%s' not found\n", t->u.user.name);
- ret = target ? PTR_ERR(target) : -ENOENT;
- goto cleanup_matches;
- }
- t->u.kernel.target = target;
-
- ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
- name, e->comefrom, e->ip.proto,
- e->ip.invflags & IPT_INV_PROTO);
+ ret = xt_init_target(t, "ipt", AF_INET,
+ name, e->comefrom, e->ip.proto,
+ e->ip.invflags & IPT_INV_PROTO);
if (ret)
goto err;
@@ -575,9 +558,11 @@ check_entry(struct ipt_entry *e, const c
ret = -EINVAL;
goto err;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -587,7 +572,7 @@ check_entry(struct ipt_entry *e, const c
(*i)++;
return 0;
err:
- module_put(t->u.kernel.target->me);
+ xt_destroy_target(t);
cleanup_matches:
IPT_MATCH_ITERATE(e, cleanup_match, &j);
return ret;
@@ -648,8 +633,9 @@ cleanup_entry(struct ipt_entry *e, unsig
IPT_MATCH_ITERATE(e, cleanup_match, NULL);
t = ipt_get_target(e);
if (t->u.kernel.target->destroy)
- t->u.kernel.target->destroy(t->u.kernel.target, t->data);
- module_put(t->u.kernel.target->me);
+ t->u.kernel.target->destroy(t->u.kernel.target, t->data,
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -718,7 +704,7 @@ translate_table(const char *name,
/* Finally, each sanity check must pass */
i = 0;
ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
- check_entry, name, size, &i);
+ init_entry, name, size, &i);
if (ret != 0) {
IPT_ENTRY_ITERATE(entry0, newinfo->size,
@@ -1364,15 +1350,15 @@ struct compat_ipt_replace {
};
static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
- void __user **dstptr, compat_uint_t *size)
+ void * __user *dstptr, compat_uint_t *size)
{
return xt_compat_match_to_user(m, dstptr, size);
}
static int compat_copy_entry_to_user(struct ipt_entry *e,
- void __user **dstptr, compat_uint_t *size)
+ void * __user *dstptr, compat_uint_t *size)
{
- struct ipt_entry_target *t;
+ struct ipt_entry_target __user *t;
struct compat_ipt_entry __user *ce;
u_int16_t target_offset, next_offset;
compat_uint_t origsize;
@@ -1477,7 +1463,7 @@ check_compat_entry_size_and_hooks(struct
t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
- duprintf("check_entry: `%s' not found\n", t->u.user.name);
+ duprintf("init_entry: `%s' not found\n", t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
goto cleanup_matches;
}
@@ -1523,15 +1509,15 @@ static inline int compat_copy_match_from
match = m->u.kernel.match;
xt_compat_match_from_user(m, dstptr, size);
- ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
- name, hookmask, ip->proto,
- ip->invflags & IPT_INV_PROTO);
+ ret = xt_init_match(m, "ipt", AF_INET,
+ name, hookmask, ip->proto,
+ ip->invflags & IPT_INV_PROTO);
if (ret)
goto err;
- if (m->u.kernel.match->checkentry
- && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ip, match, dm->data,
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -1541,7 +1527,7 @@ static inline int compat_copy_match_from
return 0;
err:
- module_put(m->u.kernel.match->me);
+ xt_destroy_match(m);
return ret;
}
@@ -1581,9 +1567,9 @@ static int compat_copy_entry_from_user(s
t = ipt_get_target(de);
target = t->u.kernel.target;
- ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
- name, e->comefrom, e->ip.proto,
- e->ip.invflags & IPT_INV_PROTO);
+ ret = xt_init_target(t, "ipt", AF_INET,
+ name, e->comefrom, e->ip.proto,
+ e->ip.invflags & IPT_INV_PROTO);
if (ret)
goto err;
@@ -1591,9 +1577,10 @@ static int compat_copy_entry_from_user(s
if (t->u.kernel.target == &ipt_standard_target) {
if (!standard_check(t, *size))
goto err;
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, de, target,
- t->data, de->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, de, target,
+ t->data, de->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: compat: check failed for `%s'.\n",
t->u.kernel.target->name);
goto err;
@@ -1602,7 +1589,7 @@ static int compat_copy_entry_from_user(s
return ret;
err:
- module_put(t->u.kernel.target->me);
+ xt_destroy_target(t);
cleanup_matches:
IPT_MATCH_ITERATE(e, cleanup_match, &j);
return ret;
@@ -2090,7 +2077,8 @@ icmp_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ int *hotdrop,
+ void *priv_data)
{
struct icmphdr _icmph, *ic;
const struct ipt_icmp *icmpinfo = matchinfo;
@@ -2118,11 +2106,12 @@ icmp_match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
-icmp_checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+icmp_init(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask,
+ void *priv_data)
{
const struct ipt_icmp *icmpinfo = matchinfo;
@@ -2171,7 +2160,7 @@ static struct ipt_match icmp_matchstruct
.matchsize = sizeof(struct ipt_icmp),
.proto = IPPROTO_ICMP,
.family = AF_INET,
- .checkentry = icmp_checkentry,
+ .init = icmp_init,
};
static int __init ip_tables_init(void)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4ab368f..2c3ed69 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -217,7 +217,8 @@ ip6t_error(struct sk_buff **pskb,
const struct net_device *out,
unsigned int hooknum,
const struct xt_target *target,
- const void *targinfo)
+ const void *targinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("ip6_tables: error: `%s'\n", (char *)targinfo);
@@ -236,7 +237,8 @@ int do_match(struct ip6t_entry_match *m,
{
/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
- offset, protoff, hotdrop))
+ offset, protoff, hotdrop,
+ m->u.kernel.priv_data))
return 1;
else
return 0;
@@ -340,11 +342,13 @@ #ifdef CONFIG_NETFILTER_DEBUG
((struct ip6t_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data);
+ verdict = t->u.kernel.target->target(
+ pskb,
+ in, out,
+ hook,
+ t->u.kernel.target,
+ t->data,
+ t->u.kernel.priv_data);
#ifdef CONFIG_NETFILTER_DEBUG
if (((struct ip6t_entry *)table_base)->comefrom
@@ -501,8 +505,9 @@ cleanup_match(struct ip6t_entry_match *m
return 1;
if (m->u.kernel.match->destroy)
- m->u.kernel.match->destroy(m->u.kernel.match, m->data);
- module_put(m->u.kernel.match->me);
+ m->u.kernel.match->destroy(m->u.kernel.match, m->data,
+ m->u.kernel.priv_data);
+ xt_destroy_match(m);
return 0;
}
@@ -528,33 +533,24 @@ standard_check(const struct ip6t_entry_t
}
static inline int
-check_match(struct ip6t_entry_match *m,
- const char *name,
- const struct ip6t_ip6 *ipv6,
- unsigned int hookmask,
- unsigned int *i)
+init_match(struct ip6t_entry_match *m,
+ const char *name,
+ const struct ip6t_ip6 *ipv6,
+ unsigned int hookmask,
+ unsigned int *i)
{
- struct ip6t_match *match;
int ret;
- match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
- m->u.user.revision),
- "ip6t_%s", m->u.user.name);
- if (IS_ERR(match) || !match) {
- duprintf("check_match: `%s' not found\n", m->u.user.name);
- return match ? PTR_ERR(match) : -ENOENT;
- }
- m->u.kernel.match = match;
-
- ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m),
- name, hookmask, ipv6->proto,
- ipv6->invflags & IP6T_INV_PROTO);
+ ret = xt_init_match(m, "ip6t", AF_INET6,
+ name, hookmask, ipv6->proto,
+ ipv6->invflags & IP6T_INV_PROTO);
if (ret)
goto err;
- if (m->u.kernel.match->checkentry
- && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ipv6, m->u.kernel.match,
+ m->data, hookmask,
+ m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -564,18 +560,17 @@ check_match(struct ip6t_entry_match *m,
(*i)++;
return 0;
err:
- module_put(m->u.kernel.match->me);
+ xt_destroy_match(m);
return ret;
}
static struct ip6t_target ip6t_standard_target;
static inline int
-check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
- unsigned int *i)
+init_entry(struct ip6t_entry *e, const char *name, unsigned int size,
+ unsigned int *i)
{
struct ip6t_entry_target *t;
- struct ip6t_target *target;
int ret;
unsigned int j;
@@ -585,25 +580,14 @@ check_entry(struct ip6t_entry *e, const
}
j = 0;
- ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
+ ret = IP6T_MATCH_ITERATE(e, init_match, name, &e->ipv6, e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;
t = ip6t_get_target(e);
- target = try_then_request_module(xt_find_target(AF_INET6,
- t->u.user.name,
- t->u.user.revision),
- "ip6t_%s", t->u.user.name);
- if (IS_ERR(target) || !target) {
- duprintf("check_entry: `%s' not found\n", t->u.user.name);
- ret = target ? PTR_ERR(target) : -ENOENT;
- goto cleanup_matches;
- }
- t->u.kernel.target = target;
-
- ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t),
- name, e->comefrom, e->ipv6.proto,
- e->ipv6.invflags & IP6T_INV_PROTO);
+ ret = xt_init_target(t, "ip6t", AF_INET6,
+ name, e->comefrom, e->ipv6.proto,
+ e->ipv6.invflags & IP6T_INV_PROTO);
if (ret)
goto err;
@@ -612,9 +596,11 @@ check_entry(struct ip6t_entry *e, const
ret = -EINVAL;
goto err;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -624,7 +610,7 @@ check_entry(struct ip6t_entry *e, const
(*i)++;
return 0;
err:
- module_put(t->u.kernel.target->me);
+ xt_destroy_target(t);
cleanup_matches:
IP6T_MATCH_ITERATE(e, cleanup_match, &j);
return ret;
@@ -685,8 +671,9 @@ cleanup_entry(struct ip6t_entry *e, unsi
IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
t = ip6t_get_target(e);
if (t->u.kernel.target->destroy)
- t->u.kernel.target->destroy(t->u.kernel.target, t->data);
- module_put(t->u.kernel.target->me);
+ t->u.kernel.target->destroy(t->u.kernel.target, t->data,
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -755,7 +742,7 @@ translate_table(const char *name,
/* Finally, each sanity check must pass */
i = 0;
ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
- check_entry, name, size, &i);
+ init_entry, name, size, &i);
if (ret != 0) {
IP6T_ENTRY_ITERATE(entry0, newinfo->size,
@@ -1310,7 +1297,8 @@ icmp6_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ int *hotdrop,
+ void *priv_data)
{
struct icmp6hdr _icmp, *ic;
const struct ip6t_icmp *icmpinfo = matchinfo;
@@ -1337,11 +1325,12 @@ icmp6_match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
-icmp6_checkentry(const char *tablename,
+icmp6_init(const char *tablename,
const void *entry,
const struct xt_match *match,
void *matchinfo,
- unsigned int hook_mask)
+ unsigned int hook_mask,
+ void *priv_data)
{
const struct ip6t_icmp *icmpinfo = matchinfo;
@@ -1377,7 +1366,7 @@ static struct ip6t_match icmp6_matchstru
.name = "icmp6",
.match = &icmp6_match,
.matchsize = sizeof(struct ip6t_icmp),
- .checkentry = icmp6_checkentry,
+ .init = icmp6_init,
.proto = IPPROTO_ICMPV6,
.family = AF_INET6,
};
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 58522fc..5822202 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -303,10 +303,27 @@ int xt_find_revision(int af, const char
}
EXPORT_SYMBOL_GPL(xt_find_revision);
-int xt_check_match(const struct xt_match *match, unsigned short family,
- unsigned int size, const char *table, unsigned int hook_mask,
- unsigned short proto, int inv_proto)
-{
+int xt_init_match(struct xt_entry_match *m, char *module_prefix,
+ unsigned short family, const char *table,
+ unsigned int hook_mask,
+ unsigned short proto, int inv_proto)
+{
+ struct xt_match *match;
+ unsigned int size = (m->u.match_size - sizeof(*m));
+
+ match = try_then_request_module(xt_find_match(family, m->u.user.name,
+ m->u.user.revision),
+ "%s_%s",
+ module_prefix, m->u.user.name);
+ if (IS_ERR(match) || !match) {
+ duprintf("init_match: `%s' not found\n", m->u.user.name);
+ m->u.kernel.match = NULL;
+ m->u.kernel.priv_data = NULL;
+ return match ? PTR_ERR(match) : -ENOENT;
+ }
+ m->u.kernel.match = match;
+ m->u.kernel.priv_data = NULL;
+
if (XT_ALIGN(match->matchsize) != size) {
printk("%s_tables: %s match: invalid size %Zu != %u\n",
xt_prefix[family], match->name,
@@ -328,9 +345,30 @@ int xt_check_match(const struct xt_match
xt_prefix[family], match->name, match->proto);
return -EINVAL;
}
+
+ if (match->priv_size) {
+ m->u.kernel.priv_data = kzalloc(match->priv_size,
+ GFP_KERNEL);
+ if (!m->u.kernel.priv_data) {
+ printk("%s_tables: %s match: "
+ "unable to allocate memory\n",
+ xt_prefix[family], match->name);
+ return -ENOMEM;
+ }
+ }
+
return 0;
}
-EXPORT_SYMBOL_GPL(xt_check_match);
+EXPORT_SYMBOL_GPL(xt_init_match);
+
+void xt_destroy_match(struct xt_entry_match *m)
+{
+ BUG_ON(!m);
+ kfree(m->u.kernel.priv_data);
+ if (m->u.kernel.match)
+ module_put(m->u.kernel.match->me);
+}
+EXPORT_SYMBOL_GPL(xt_destroy_match);
#ifdef CONFIG_COMPAT
int xt_compat_match_offset(struct xt_match *match)
@@ -393,10 +431,28 @@ int xt_compat_match_to_user(struct xt_en
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,
- unsigned short proto, int inv_proto)
+int xt_init_target(struct xt_entry_target *t, char *module_prefix,
+ unsigned short family, const char *table,
+ unsigned int hook_mask, unsigned short proto,
+ int inv_proto)
{
+ struct xt_target *target;
+ unsigned int size = t->u.target_size - sizeof(*t);
+
+ target = try_then_request_module(xt_find_target(family,
+ t->u.user.name,
+ t->u.user.revision),
+ "%s_%s",
+ module_prefix, t->u.user.name);
+ if (IS_ERR(target) || !target) {
+ duprintf("init_target: `%s' not found\n", t->u.user.name);
+ t->u.kernel.target = NULL;
+ t->u.kernel.priv_data = NULL;
+ return target ? PTR_ERR(target) : -ENOENT;
+ }
+ t->u.kernel.target = target;
+ t->u.kernel.priv_data = NULL;
+
if (XT_ALIGN(target->targetsize) != size) {
printk("%s_tables: %s target: invalid size %Zu != %u\n",
xt_prefix[family], target->name,
@@ -418,9 +474,30 @@ int xt_check_target(const struct xt_targ
xt_prefix[family], target->name, target->proto);
return -EINVAL;
}
+
+ if (target->priv_size) {
+ t->u.kernel.priv_data = kzalloc(target->priv_size,
+ GFP_KERNEL);
+ if (!t->u.kernel.priv_data) {
+ printk("%s_tables: %s target: "
+ "unable to allocate memory\n",
+ xt_prefix[family], target->name);
+ return -ENOMEM;
+ }
+ }
+
return 0;
}
-EXPORT_SYMBOL_GPL(xt_check_target);
+EXPORT_SYMBOL_GPL(xt_init_target);
+
+void xt_destroy_target(struct xt_entry_target *t)
+{
+ BUG_ON(!t);
+ kfree(t->u.kernel.priv_data);
+ if (t->u.kernel.target)
+ module_put(t->u.kernel.target->me);
+}
+EXPORT_SYMBOL_GPL(xt_destroy_target);
#ifdef CONFIG_COMPAT
int xt_compat_target_offset(struct xt_target *target)
--
1.4.2
next prev parent reply other threads:[~2006-09-25 8:16 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-24 22:40 [PATCH 0/2][priv_data-condition] Massimiliano Hofer
2006-09-25 8:15 ` Massimiliano Hofer
2006-09-25 8:16 ` Massimiliano Hofer [this message]
2006-09-30 16:54 ` [PATCH 1/2][priv_data-condition][part 1/2][core] Patrick McHardy
2006-12-05 22:06 ` Massimiliano Hofer
2006-09-25 8:17 ` [PATCH 1/2][priv_data-condition][part 2/2][matches_and_targets] Massimiliano Hofer
2006-09-30 16:55 ` Patrick McHardy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200609251016.33590.max@nucleus.it \
--to=max@nucleus.it \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.