* [PATCH] priv_data 1/2
@ 2006-06-26 14:43 Massimiliano Hofer
2006-07-01 0:05 ` Massimiliano Hofer
0 siblings, 1 reply; 2+ messages in thread
From: Massimiliano Hofer @ 2006-06-26 14:43 UTC (permalink / raw)
To: netfilter-devel; +Cc: Patrick McHardy
[-- Attachment #1: Type: text/plain, Size: 105 bytes --]
Hi,
this is the first part. Modifications to the core netfilter code.
--
Saluti,
Massimiliano Hofer
[-- Attachment #2: 01-2.6.17.1-priv_data-core.patch --]
[-- Type: text/x-diff, Size: 25813 bytes --]
diff -Nru linux-2.6.17.1/include/linux/netfilter/x_tables.h linux-2.6.17.1-priv_data-core/include/linux/netfilter/x_tables.h
--- linux-2.6.17.1/include/linux/netfilter/x_tables.h 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/include/linux/netfilter/x_tables.h 2006-06-24 18:57:28.000000000 +0200
@@ -20,6 +20,7 @@
/* Used inside the kernel */
struct xt_match *match;
+ void *priv_data;
} kernel;
/* Total length */
@@ -45,6 +46,7 @@
/* Used inside the kernel */
struct xt_target *target;
+ void *priv_data;
} kernel;
/* Total length */
@@ -166,20 +168,22 @@
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 matchinfosize,
- unsigned int hook_mask);
+ int (*init)(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask,
+ void *priv_data);
/* Called when entry of this type deleted. */
void (*destroy)(const struct xt_match *match, void *matchinfo,
- unsigned int matchinfosize);
+ unsigned int matchinfosize, void *priv_data);
/* Called when userspace align differs from kernel space one */
int (*compat)(void *match, void **dstptr, int *size, int convert);
@@ -189,6 +193,7 @@
char *table;
unsigned int matchsize;
+ size_t priv_size;
unsigned int hooks;
unsigned short proto;
@@ -212,22 +217,24 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userdata);
+ void *userdata,
+ 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,
+ int (*init)(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int targinfosize,
- unsigned int hook_mask);
+ unsigned int hook_mask,
+ void *priv_data);
/* Called when entry of this type deleted. */
void (*destroy)(const struct xt_target *target, void *targinfo,
- unsigned int targinfosize);
+ unsigned int targinfosize, void *priv_data);
/* Called when userspace align differs from kernel space one */
int (*compat)(void *target, void **dstptr, int *size, int convert);
@@ -237,6 +244,7 @@
char *table;
unsigned int targetsize;
+ size_t priv_size;
unsigned int hooks;
unsigned short proto;
@@ -293,12 +301,16 @@
extern int xt_register_match(struct xt_match *target);
extern void xt_unregister_match(struct xt_match *target);
-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 *t);
extern int xt_register_table(struct xt_table *table,
struct xt_table_info *bootstrap,
diff -Nru linux-2.6.17.1/net/ipv4/netfilter/arp_tables.c linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/arp_tables.c
--- linux-2.6.17.1/net/ipv4/netfilter/arp_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/arp_tables.c 2006-06-25 00:23:58.000000000 +0200
@@ -210,7 +210,8 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userinfo)
+ void *userinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("arp_tables: error: '%s'\n", (char *)targinfo);
@@ -299,11 +300,10 @@
* abs. verdicts
*/
verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data,
- userdata);
+ in, out, hook,
+ t->u.kernel.target,
+ t->data, userdata,
+ t->u.kernel.priv_data);
/* Target might have changed stuff. */
arp = (*pskb)->nh.arph;
@@ -459,11 +459,10 @@
static struct arpt_target arpt_standard_target;
-static inline int check_entry(struct arpt_entry *e, const char *name, unsigned int size,
- unsigned int *i)
+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)) {
@@ -472,18 +471,10 @@
}
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_check_target(target, NF_ARP, t->u.target_size - sizeof(*t),
- name, e->comefrom, 0, 0);
+ ret = xt_init_target(t, "arpt", NF_ARP,
+ name, e->comefrom, 0, 0);
+
if (ret)
goto err;
@@ -492,11 +483,12 @@
ret = -EINVAL;
goto out;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- t->u.target_size
- - sizeof(*t),
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ t->u.target_size - sizeof(*t),
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("arp_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -506,7 +498,7 @@
(*i)++;
return 0;
err:
- module_put(t->u.kernel.target->me);
+ xt_destroy_target(t);
out:
return ret;
}
@@ -563,8 +555,9 @@
t = arpt_get_target(e);
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->u.kernel.target, t->data,
- t->u.target_size - sizeof(*t));
- module_put(t->u.kernel.target->me);
+ t->u.target_size - sizeof(*t),
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -637,7 +630,7 @@
/* 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 -Nru linux-2.6.17.1/net/ipv4/netfilter/ip_tables.c linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/ip_tables.c
--- linux-2.6.17.1/net/ipv4/netfilter/ip_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/ip_tables.c 2006-06-25 00:31:31.000000000 +0200
@@ -182,7 +182,8 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userinfo)
+ void *userinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("ip_tables: error: `%s'\n", (char *)targinfo);
@@ -200,7 +201,8 @@
{
/* 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;
@@ -304,12 +306,11 @@
((struct ipt_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data,
- userdata);
+ verdict = t->u.kernel.target->target(
+ pskb, in, out, hook,
+ t->u.kernel.target,
+ t->data, userdata,
+ t->u.kernel.priv_data);
#ifdef CONFIG_NETFILTER_DEBUG
if (((struct ipt_entry *)table_base)->comefrom
@@ -468,8 +469,9 @@
if (m->u.kernel.match->destroy)
m->u.kernel.match->destroy(m->u.kernel.match, m->data,
- m->u.match_size - sizeof(*m));
- module_put(m->u.kernel.match->me);
+ m->u.match_size - sizeof(*m),
+ m->u.kernel.priv_data);
+ xt_destroy_match(m);
return 0;
}
@@ -495,34 +497,25 @@
}
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,
- m->u.match_size - sizeof(*m),
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ip, m->u.kernel.match,
+ m->data,
+ m->u.match_size - sizeof(*m),
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -532,18 +525,17 @@
(*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,
- unsigned int *i)
+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;
@@ -553,25 +545,15 @@
}
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;
@@ -580,11 +562,12 @@
ret = -EINVAL;
goto cleanup_matches;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- t->u.target_size
- - sizeof(*t),
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ t->u.target_size - sizeof(*t),
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -594,7 +577,7 @@
(*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;
@@ -656,8 +639,9 @@
t = ipt_get_target(e);
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->u.kernel.target, t->data,
- t->u.target_size - sizeof(*t));
- module_put(t->u.kernel.target->me);
+ t->u.target_size - sizeof(*t),
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -726,7 +710,7 @@
/* 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,
@@ -1545,7 +1529,7 @@
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 out;
}
@@ -1600,10 +1584,10 @@
if (ret)
return ret;
- if (m->u.kernel.match->checkentry
- && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
- dm->u.match_size - sizeof(*dm),
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ip, match, dm->data,
+ dm->u.match_size - sizeof(*dm),
+ hookmask)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
return -EINVAL;
@@ -2152,7 +2136,8 @@
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;
@@ -2180,12 +2165,13 @@
/* 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 matchsize,
- unsigned int hook_mask)
+icmp_init(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask,
+ void *priv_data)
{
const struct ipt_icmp *icmpinfo = matchinfo;
@@ -2232,7 +2218,7 @@
.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 -Nru linux-2.6.17.1/net/ipv6/netfilter/ip6_tables.c linux-2.6.17.1-priv_data-core/net/ipv6/netfilter/ip6_tables.c
--- linux-2.6.17.1/net/ipv6/netfilter/ip6_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/ipv6/netfilter/ip6_tables.c 2006-06-25 00:23:54.000000000 +0200
@@ -221,7 +221,8 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userinfo)
+ void *userinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("ip6_tables: error: `%s'\n", (char *)targinfo);
@@ -240,7 +241,8 @@
{
/* 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;
@@ -345,12 +347,11 @@
((struct ip6t_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data,
- userdata);
+ verdict = t->u.kernel.target->target(
+ pskb, in, out, hook,
+ t->u.kernel.target,
+ t->data, userdata,
+ t->u.kernel.priv_data);
#ifdef CONFIG_NETFILTER_DEBUG
if (((struct ip6t_entry *)table_base)->comefrom
@@ -508,8 +509,9 @@
if (m->u.kernel.match->destroy)
m->u.kernel.match->destroy(m->u.kernel.match, m->data,
- m->u.match_size - sizeof(*m));
- module_put(m->u.kernel.match->me);
+ m->u.match_size - sizeof(*m),
+ m->u.kernel.priv_data);
+ xt_destroy_match(m);
return 0;
}
@@ -535,34 +537,25 @@
}
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,
- m->u.match_size - sizeof(*m),
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ipv6, m->u.kernel.match,
+ m->data,
+ m->u.match_size - sizeof(*m),
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -572,18 +565,17 @@
(*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;
@@ -593,25 +585,15 @@
}
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;
@@ -620,11 +602,12 @@
ret = -EINVAL;
goto cleanup_matches;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- t->u.target_size
- - sizeof(*t),
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ t->u.target_size - sizeof(*t),
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -634,7 +617,7 @@
(*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;
@@ -696,8 +679,9 @@
t = ip6t_get_target(e);
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->u.kernel.target, t->data,
- t->u.target_size - sizeof(*t));
- module_put(t->u.kernel.target->me);
+ t->u.target_size - sizeof(*t),
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -766,7 +750,7 @@
/* 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,
@@ -1320,7 +1304,8 @@
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;
@@ -1347,12 +1332,13 @@
/* 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 matchsize,
- unsigned int hook_mask)
+ unsigned int hook_mask,
+ void *priv_data)
{
const struct ip6t_icmp *icmpinfo = matchinfo;
@@ -1388,7 +1374,7 @@
.name = "icmp6",
.match = &icmp6_match,
.matchsize = sizeof(struct ip6t_icmp),
- .checkentry = icmp6_checkentry,
+ .init = icmp6_init,
.proto = IPPROTO_ICMPV6,
.family = AF_INET6,
};
diff -Nru linux-2.6.17.1/net/netfilter/x_tables.c linux-2.6.17.1-priv_data-core/net/netfilter/x_tables.c
--- linux-2.6.17.1/net/netfilter/x_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/netfilter/x_tables.c 2006-06-25 00:23:52.000000000 +0200
@@ -244,10 +244,27 @@
}
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,
@@ -269,9 +286,30 @@
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(void *match, void **dstptr, int *size, int convert)
@@ -321,10 +359,28 @@
EXPORT_SYMBOL_GPL(xt_compat_match);
#endif
-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,
@@ -346,9 +402,30 @@
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(void *target, void **dstptr, int *size, int convert)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] priv_data 1/2
2006-06-26 14:43 [PATCH] priv_data 1/2 Massimiliano Hofer
@ 2006-07-01 0:05 ` Massimiliano Hofer
0 siblings, 0 replies; 2+ messages in thread
From: Massimiliano Hofer @ 2006-07-01 0:05 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 244 bytes --]
Hi,
I had the opportunity to test the patch on a x86_64 CPU and found that my
previous version didn't even compile.
This one compiles and survives a quick test. The second part of the patch
remains unmodified.
--
Bye,
Massimiliano Hofer
[-- Attachment #2: 01-2.6.17.1-priv_data-core-2.patch --]
[-- Type: text/x-diff, Size: 27402 bytes --]
diff -Nru linux-2.6.17.1/include/linux/netfilter/x_tables.h linux-2.6.17.1-priv_data-core/include/linux/netfilter/x_tables.h
--- linux-2.6.17.1/include/linux/netfilter/x_tables.h 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/include/linux/netfilter/x_tables.h 2006-06-24 18:57:28.000000000 +0200
@@ -20,6 +20,7 @@
/* Used inside the kernel */
struct xt_match *match;
+ void *priv_data;
} kernel;
/* Total length */
@@ -45,6 +46,7 @@
/* Used inside the kernel */
struct xt_target *target;
+ void *priv_data;
} kernel;
/* Total length */
@@ -166,20 +168,22 @@
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 matchinfosize,
- unsigned int hook_mask);
+ int (*init)(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask,
+ void *priv_data);
/* Called when entry of this type deleted. */
void (*destroy)(const struct xt_match *match, void *matchinfo,
- unsigned int matchinfosize);
+ unsigned int matchinfosize, void *priv_data);
/* Called when userspace align differs from kernel space one */
int (*compat)(void *match, void **dstptr, int *size, int convert);
@@ -189,6 +193,7 @@
char *table;
unsigned int matchsize;
+ size_t priv_size;
unsigned int hooks;
unsigned short proto;
@@ -212,22 +217,24 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userdata);
+ void *userdata,
+ 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,
+ int (*init)(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int targinfosize,
- unsigned int hook_mask);
+ unsigned int hook_mask,
+ void *priv_data);
/* Called when entry of this type deleted. */
void (*destroy)(const struct xt_target *target, void *targinfo,
- unsigned int targinfosize);
+ unsigned int targinfosize, void *priv_data);
/* Called when userspace align differs from kernel space one */
int (*compat)(void *target, void **dstptr, int *size, int convert);
@@ -237,6 +244,7 @@
char *table;
unsigned int targetsize;
+ size_t priv_size;
unsigned int hooks;
unsigned short proto;
@@ -293,12 +301,16 @@
extern int xt_register_match(struct xt_match *target);
extern void xt_unregister_match(struct xt_match *target);
-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 *t);
extern int xt_register_table(struct xt_table *table,
struct xt_table_info *bootstrap,
diff -Nru linux-2.6.17.1/net/ipv4/netfilter/arp_tables.c linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/arp_tables.c
--- linux-2.6.17.1/net/ipv4/netfilter/arp_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/arp_tables.c 2006-06-25 00:23:58.000000000 +0200
@@ -210,7 +210,8 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userinfo)
+ void *userinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("arp_tables: error: '%s'\n", (char *)targinfo);
@@ -299,11 +300,10 @@
* abs. verdicts
*/
verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data,
- userdata);
+ in, out, hook,
+ t->u.kernel.target,
+ t->data, userdata,
+ t->u.kernel.priv_data);
/* Target might have changed stuff. */
arp = (*pskb)->nh.arph;
@@ -459,11 +459,10 @@
static struct arpt_target arpt_standard_target;
-static inline int check_entry(struct arpt_entry *e, const char *name, unsigned int size,
- unsigned int *i)
+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)) {
@@ -472,18 +471,10 @@
}
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_check_target(target, NF_ARP, t->u.target_size - sizeof(*t),
- name, e->comefrom, 0, 0);
+ ret = xt_init_target(t, "arpt", NF_ARP,
+ name, e->comefrom, 0, 0);
+
if (ret)
goto err;
@@ -492,11 +483,12 @@
ret = -EINVAL;
goto out;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- t->u.target_size
- - sizeof(*t),
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ t->u.target_size - sizeof(*t),
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("arp_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -506,7 +498,7 @@
(*i)++;
return 0;
err:
- module_put(t->u.kernel.target->me);
+ xt_destroy_target(t);
out:
return ret;
}
@@ -563,8 +555,9 @@
t = arpt_get_target(e);
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->u.kernel.target, t->data,
- t->u.target_size - sizeof(*t));
- module_put(t->u.kernel.target->me);
+ t->u.target_size - sizeof(*t),
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -637,7 +630,7 @@
/* 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 -Nru linux-2.6.17.1/net/ipv4/netfilter/ip_tables.c linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/ip_tables.c
--- linux-2.6.17.1/net/ipv4/netfilter/ip_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/ipv4/netfilter/ip_tables.c 2006-07-01 00:49:40.000000000 +0200
@@ -182,7 +182,8 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userinfo)
+ void *userinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("ip_tables: error: `%s'\n", (char *)targinfo);
@@ -200,7 +201,8 @@
{
/* 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;
@@ -304,12 +306,11 @@
((struct ipt_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data,
- userdata);
+ verdict = t->u.kernel.target->target(
+ pskb, in, out, hook,
+ t->u.kernel.target,
+ t->data, userdata,
+ t->u.kernel.priv_data);
#ifdef CONFIG_NETFILTER_DEBUG
if (((struct ipt_entry *)table_base)->comefrom
@@ -468,8 +469,9 @@
if (m->u.kernel.match->destroy)
m->u.kernel.match->destroy(m->u.kernel.match, m->data,
- m->u.match_size - sizeof(*m));
- module_put(m->u.kernel.match->me);
+ m->u.match_size - sizeof(*m),
+ m->u.kernel.priv_data);
+ xt_destroy_match(m);
return 0;
}
@@ -495,34 +497,25 @@
}
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,
- m->u.match_size - sizeof(*m),
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ip, m->u.kernel.match,
+ m->data,
+ m->u.match_size - sizeof(*m),
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -532,18 +525,17 @@
(*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,
- unsigned int *i)
+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;
@@ -553,25 +545,15 @@
}
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;
@@ -580,11 +562,12 @@
ret = -EINVAL;
goto cleanup_matches;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- t->u.target_size
- - sizeof(*t),
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ t->u.target_size - sizeof(*t),
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -594,7 +577,7 @@
(*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;
@@ -656,8 +639,9 @@
t = ipt_get_target(e);
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->u.kernel.target, t->data,
- t->u.target_size - sizeof(*t));
- module_put(t->u.kernel.target->me);
+ t->u.target_size - sizeof(*t),
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -726,7 +710,7 @@
/* 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,
@@ -1545,7 +1529,7 @@
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 out;
}
@@ -1594,21 +1578,25 @@
else
xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
- ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
- name, hookmask, ip->proto,
- ip->invflags & IPT_INV_PROTO);
- if (ret)
- return ret;
+ 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,
- dm->u.match_size - sizeof(*dm),
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ip, match, dm->data,
+ dm->u.match_size - sizeof(*dm),
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err;
}
return 0;
+err:
+ xt_destroy_match(m);
+ return ret;
}
static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
@@ -1649,25 +1637,28 @@
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 out;
+ goto err;
ret = -EINVAL;
if (t->u.kernel.target == &ipt_standard_target) {
if (!standard_check(t, *size))
- goto out;
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, de, target,
+ goto err;
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, de, target,
t->data, t->u.target_size - sizeof(*t),
- de->comefrom)) {
+ de->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: compat: check failed for `%s'.\n",
t->u.kernel.target->name);
- goto out;
+ goto err;
}
- ret = 0;
+ return 0;
+err:
+ xt_destroy_target(t);
out:
return ret;
}
@@ -2152,7 +2143,8 @@
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;
@@ -2180,12 +2172,13 @@
/* 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 matchsize,
- unsigned int hook_mask)
+icmp_init(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask,
+ void *priv_data)
{
const struct ipt_icmp *icmpinfo = matchinfo;
@@ -2232,7 +2225,7 @@
.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 -Nru linux-2.6.17.1/net/ipv6/netfilter/ip6_tables.c linux-2.6.17.1-priv_data-core/net/ipv6/netfilter/ip6_tables.c
--- linux-2.6.17.1/net/ipv6/netfilter/ip6_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/ipv6/netfilter/ip6_tables.c 2006-06-25 00:23:54.000000000 +0200
@@ -221,7 +221,8 @@
unsigned int hooknum,
const struct xt_target *target,
const void *targinfo,
- void *userinfo)
+ void *userinfo,
+ void *priv_data)
{
if (net_ratelimit())
printk("ip6_tables: error: `%s'\n", (char *)targinfo);
@@ -240,7 +241,8 @@
{
/* 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;
@@ -345,12 +347,11 @@
((struct ip6t_entry *)table_base)->comefrom
= 0xeeeeeeec;
#endif
- verdict = t->u.kernel.target->target(pskb,
- in, out,
- hook,
- t->u.kernel.target,
- t->data,
- userdata);
+ verdict = t->u.kernel.target->target(
+ pskb, in, out, hook,
+ t->u.kernel.target,
+ t->data, userdata,
+ t->u.kernel.priv_data);
#ifdef CONFIG_NETFILTER_DEBUG
if (((struct ip6t_entry *)table_base)->comefrom
@@ -508,8 +509,9 @@
if (m->u.kernel.match->destroy)
m->u.kernel.match->destroy(m->u.kernel.match, m->data,
- m->u.match_size - sizeof(*m));
- module_put(m->u.kernel.match->me);
+ m->u.match_size - sizeof(*m),
+ m->u.kernel.priv_data);
+ xt_destroy_match(m);
return 0;
}
@@ -535,34 +537,25 @@
}
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,
- m->u.match_size - sizeof(*m),
- hookmask)) {
+ if (m->u.kernel.match->init
+ && !m->u.kernel.match->init(name, ipv6, m->u.kernel.match,
+ m->data,
+ m->u.match_size - sizeof(*m),
+ hookmask, m->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
@@ -572,18 +565,17 @@
(*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;
@@ -593,25 +585,15 @@
}
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;
@@ -620,11 +602,12 @@
ret = -EINVAL;
goto cleanup_matches;
}
- } else if (t->u.kernel.target->checkentry
- && !t->u.kernel.target->checkentry(name, e, target, t->data,
- t->u.target_size
- - sizeof(*t),
- e->comefrom)) {
+ } else if (t->u.kernel.target->init
+ && !t->u.kernel.target->init(name, e, t->u.kernel.target,
+ t->data,
+ t->u.target_size - sizeof(*t),
+ e->comefrom,
+ t->u.kernel.priv_data)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
@@ -634,7 +617,7 @@
(*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;
@@ -696,8 +679,9 @@
t = ip6t_get_target(e);
if (t->u.kernel.target->destroy)
t->u.kernel.target->destroy(t->u.kernel.target, t->data,
- t->u.target_size - sizeof(*t));
- module_put(t->u.kernel.target->me);
+ t->u.target_size - sizeof(*t),
+ t->u.kernel.priv_data);
+ xt_destroy_target(t);
return 0;
}
@@ -766,7 +750,7 @@
/* 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,
@@ -1320,7 +1304,8 @@
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;
@@ -1347,12 +1332,13 @@
/* 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 matchsize,
- unsigned int hook_mask)
+ unsigned int hook_mask,
+ void *priv_data)
{
const struct ip6t_icmp *icmpinfo = matchinfo;
@@ -1388,7 +1374,7 @@
.name = "icmp6",
.match = &icmp6_match,
.matchsize = sizeof(struct ip6t_icmp),
- .checkentry = icmp6_checkentry,
+ .init = icmp6_init,
.proto = IPPROTO_ICMPV6,
.family = AF_INET6,
};
diff -Nru linux-2.6.17.1/net/netfilter/x_tables.c linux-2.6.17.1-priv_data-core/net/netfilter/x_tables.c
--- linux-2.6.17.1/net/netfilter/x_tables.c 2006-06-20 11:31:55.000000000 +0200
+++ linux-2.6.17.1-priv_data-core/net/netfilter/x_tables.c 2006-06-25 00:23:52.000000000 +0200
@@ -244,10 +244,27 @@
}
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,
@@ -269,9 +286,30 @@
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(void *match, void **dstptr, int *size, int convert)
@@ -321,10 +359,28 @@
EXPORT_SYMBOL_GPL(xt_compat_match);
#endif
-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,
@@ -346,9 +402,30 @@
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(void *target, void **dstptr, int *size, int convert)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-07-01 0:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-26 14:43 [PATCH] priv_data 1/2 Massimiliano Hofer
2006-07-01 0:05 ` Massimiliano Hofer
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.