diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-18 05:47:48 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 22:58:31 (GMT) |
commit | b386d9f5960a9afce7f077edf2095fccfbb1a8e6 (patch) | |
tree | c7ccccf204ef62c239a87943c160a3bf25f97895 /net/netfilter | |
parent | 73cd598df46a73d6f02063f2520df115a9b88aa5 (diff) | |
download | linux-b386d9f5960a9afce7f077edf2095fccfbb1a8e6.tar.xz |
[NETFILTER]: ip_tables: move compat offset calculation to x_tables
Its needed by ip6_tables and arp_tables as well.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/x_tables.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index b95284e..8d4fca9 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -34,12 +34,21 @@ MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module"); #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) +struct compat_delta { + struct compat_delta *next; + unsigned int offset; + short delta; +}; + struct xt_af { struct mutex mutex; struct list_head match; struct list_head target; struct list_head tables; +#ifdef CONFIG_COMPAT struct mutex compat_mutex; + struct compat_delta *compat_offsets; +#endif }; static struct xt_af *xt; @@ -335,6 +344,54 @@ int xt_check_match(const struct xt_match *match, unsigned short family, EXPORT_SYMBOL_GPL(xt_check_match); #ifdef CONFIG_COMPAT +int xt_compat_add_offset(int af, unsigned int offset, short delta) +{ + struct compat_delta *tmp; + + tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + tmp->offset = offset; + tmp->delta = delta; + + if (xt[af].compat_offsets) { + tmp->next = xt[af].compat_offsets->next; + xt[af].compat_offsets->next = tmp; + } else { + xt[af].compat_offsets = tmp; + tmp->next = NULL; + } + return 0; +} +EXPORT_SYMBOL_GPL(xt_compat_add_offset); + +void xt_compat_flush_offsets(int af) +{ + struct compat_delta *tmp, *next; + + if (xt[af].compat_offsets) { + for (tmp = xt[af].compat_offsets; tmp; tmp = next) { + next = tmp->next; + kfree(tmp); + } + xt[af].compat_offsets = NULL; + } +} +EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); + +short xt_compat_calc_jump(int af, unsigned int offset) +{ + struct compat_delta *tmp; + short delta; + + for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next) + if (tmp->offset < offset) + delta += tmp->delta; + return delta; +} +EXPORT_SYMBOL_GPL(xt_compat_calc_jump); + int xt_compat_match_offset(struct xt_match *match) { u_int16_t csize = match->compatsize ? : match->matchsize; @@ -873,6 +930,7 @@ static int __init xt_init(void) mutex_init(&xt[i].mutex); #ifdef CONFIG_COMPAT mutex_init(&xt[i].compat_mutex); + xt[i].compat_offsets = NULL; #endif INIT_LIST_HEAD(&xt[i].target); INIT_LIST_HEAD(&xt[i].match); |