* [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.