Skip to content

Commit

Permalink
netfilter: xtables: generate initial table on-demand
Browse files Browse the repository at this point in the history
The static initial tables are pretty large, and after the net
namespace has been instantiated, they just hang around for nothing.
This commit removes them and creates tables on-demand at runtime when
needed.

Size shrinks by 7735 bytes (x86_64).

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
  • Loading branch information
Jan Engelhardt committed Feb 10, 2010
1 parent 2b95efe commit e3eaa99
Show file tree
Hide file tree
Showing 18 changed files with 141 additions and 334 deletions.
1 change: 1 addition & 0 deletions include/linux/netfilter_arp/arp_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ struct arpt_error {
.target.errorname = "ERROR", \
}

extern void *arpt_alloc_initial_table(const struct xt_table *);
extern struct xt_table *arpt_register_table(struct net *net,
const struct xt_table *table,
const struct arpt_replace *repl);
Expand Down
1 change: 1 addition & 0 deletions include/linux/netfilter_ipv4/ip_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ struct ipt_error {
.target.errorname = "ERROR", \
}

extern void *ipt_alloc_initial_table(const struct xt_table *);
extern unsigned int ipt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct net_device *in,
Expand Down
1 change: 1 addition & 0 deletions include/linux/netfilter_ipv6/ip6_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ ip6t_get_target(struct ip6t_entry *e)
#include <linux/init.h>
extern void ip6t_init(void) __init;

extern void *ip6t_alloc_initial_table(const struct xt_table *);
extern struct xt_table *ip6t_register_table(struct net *net,
const struct xt_table *table,
const struct ip6t_replace *repl);
Expand Down
7 changes: 7 additions & 0 deletions net/ipv4/netfilter/arp_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp/arp_tables.h>
#include "../../netfilter/xt_repldata.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
Expand Down Expand Up @@ -58,6 +59,12 @@ do { \
#define ARP_NF_ASSERT(x)
#endif

void *arpt_alloc_initial_table(const struct xt_table *info)
{
return xt_alloc_initial_table(arpt, ARPT);
}
EXPORT_SYMBOL_GPL(arpt_alloc_initial_table);

static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
const char *hdr_addr, int len)
{
Expand Down
40 changes: 8 additions & 32 deletions net/ipv4/netfilter/arptable_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include <linux/module.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp/arp_tables.h>

MODULE_LICENSE("GPL");
Expand All @@ -15,36 +16,6 @@ MODULE_DESCRIPTION("arptables filter table");
#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
(1 << NF_ARP_FORWARD))

static const struct
{
struct arpt_replace repl;
struct arpt_standard entries[3];
struct arpt_error term;
} initial_table __net_initdata = {
.repl = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
.num_entries = 4,
.size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
.hook_entry = {
[NF_ARP_IN] = 0,
[NF_ARP_OUT] = sizeof(struct arpt_standard),
[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
},
.underflow = {
[NF_ARP_IN] = 0,
[NF_ARP_OUT] = sizeof(struct arpt_standard),
[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
},
},
.entries = {
ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
},
.term = ARPT_ERROR_INIT,
};

static const struct xt_table packet_filter = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
Expand All @@ -68,9 +39,14 @@ static struct nf_hook_ops *arpfilter_ops __read_mostly;

static int __net_init arptable_filter_net_init(struct net *net)
{
/* Register table */
struct arpt_replace *repl;

repl = arpt_alloc_initial_table(&packet_filter);
if (repl == NULL)
return -ENOMEM;
net->ipv4.arptable_filter =
arpt_register_table(net, &packet_filter, &initial_table.repl);
arpt_register_table(net, &packet_filter, repl);
kfree(repl);
if (IS_ERR(net->ipv4.arptable_filter))
return PTR_ERR(net->ipv4.arptable_filter);
return 0;
Expand Down
7 changes: 7 additions & 0 deletions net/ipv4/netfilter/ip_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <net/netfilter/nf_log.h>
#include "../../netfilter/xt_repldata.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
Expand Down Expand Up @@ -66,6 +67,12 @@ do { \
#define inline
#endif

void *ipt_alloc_initial_table(const struct xt_table *info)
{
return xt_alloc_initial_table(ipt, IPT);
}
EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);

/*
We keep a set of rules for each CPU, so we can avoid write-locking
them in the softirq when updating the counters and therefore
Expand Down
46 changes: 11 additions & 35 deletions net/ipv4/netfilter/iptable_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,6 @@ MODULE_DESCRIPTION("iptables filter table");
(1 << NF_INET_FORWARD) | \
(1 << NF_INET_LOCAL_OUT))

static struct
{
struct ipt_replace repl;
struct ipt_standard entries[3];
struct ipt_error term;
} initial_table __net_initdata = {
.repl = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
.num_entries = 4,
.size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
.hook_entry = {
[NF_INET_LOCAL_IN] = 0,
[NF_INET_FORWARD] = sizeof(struct ipt_standard),
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
},
.underflow = {
[NF_INET_LOCAL_IN] = 0,
[NF_INET_FORWARD] = sizeof(struct ipt_standard),
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
},
},
.entries = {
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
.term = IPT_ERROR_INIT, /* ERROR */
};

static const struct xt_table packet_filter = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
Expand Down Expand Up @@ -86,9 +56,18 @@ module_param(forward, bool, 0000);

static int __net_init iptable_filter_net_init(struct net *net)
{
/* Register table */
struct ipt_replace *repl;

repl = ipt_alloc_initial_table(&packet_filter);
if (repl == NULL)
return -ENOMEM;
/* Entry 1 is the FORWARD hook */
((struct ipt_standard *)repl->entries)[1].target.verdict =
-forward - 1;

net->ipv4.iptable_filter =
ipt_register_table(net, &packet_filter, &initial_table.repl);
ipt_register_table(net, &packet_filter, repl);
kfree(repl);
if (IS_ERR(net->ipv4.iptable_filter))
return PTR_ERR(net->ipv4.iptable_filter);
return 0;
Expand All @@ -113,9 +92,6 @@ static int __init iptable_filter_init(void)
return -EINVAL;
}

/* Entry 1 is the FORWARD hook */
initial_table.entries[1].target.verdict = -forward - 1;

ret = register_pernet_subsys(&iptable_filter_net_ops);
if (ret < 0)
return ret;
Expand Down
46 changes: 7 additions & 39 deletions net/ipv4/netfilter/iptable_mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,6 @@ MODULE_DESCRIPTION("iptables mangle table");
(1 << NF_INET_LOCAL_OUT) | \
(1 << NF_INET_POST_ROUTING))

/* Ouch - five different hooks? Maybe this should be a config option..... -- BC */
static const struct
{
struct ipt_replace repl;
struct ipt_standard entries[5];
struct ipt_error term;
} initial_table __net_initdata = {
.repl = {
.name = "mangle",
.valid_hooks = MANGLE_VALID_HOOKS,
.num_entries = 6,
.size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
.hook_entry = {
[NF_INET_PRE_ROUTING] = 0,
[NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
[NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
[NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
},
.underflow = {
[NF_INET_PRE_ROUTING] = 0,
[NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
[NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
[NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
},
},
.entries = {
IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
},
.term = IPT_ERROR_INIT, /* ERROR */
};

static const struct xt_table packet_mangler = {
.name = "mangle",
.valid_hooks = MANGLE_VALID_HOOKS,
Expand Down Expand Up @@ -134,9 +97,14 @@ static struct nf_hook_ops *mangle_ops __read_mostly;

static int __net_init iptable_mangle_net_init(struct net *net)
{
/* Register table */
struct ipt_replace *repl;

repl = ipt_alloc_initial_table(&packet_mangler);
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_mangle =
ipt_register_table(net, &packet_mangler, &initial_table.repl);
ipt_register_table(net, &packet_mangler, repl);
kfree(repl);
if (IS_ERR(net->ipv4.iptable_mangle))
return PTR_ERR(net->ipv4.iptable_mangle);
return 0;
Expand Down
36 changes: 7 additions & 29 deletions net/ipv4/netfilter/iptable_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,6 @@

#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))

static const struct
{
struct ipt_replace repl;
struct ipt_standard entries[2];
struct ipt_error term;
} initial_table __net_initdata = {
.repl = {
.name = "raw",
.valid_hooks = RAW_VALID_HOOKS,
.num_entries = 3,
.size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
.hook_entry = {
[NF_INET_PRE_ROUTING] = 0,
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
},
.underflow = {
[NF_INET_PRE_ROUTING] = 0,
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
},
},
.entries = {
IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
.term = IPT_ERROR_INIT, /* ERROR */
};

static const struct xt_table packet_raw = {
.name = "raw",
.valid_hooks = RAW_VALID_HOOKS,
Expand Down Expand Up @@ -66,9 +39,14 @@ static struct nf_hook_ops *rawtable_ops __read_mostly;

static int __net_init iptable_raw_net_init(struct net *net)
{
/* Register table */
struct ipt_replace *repl;

repl = ipt_alloc_initial_table(&packet_raw);
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_raw =
ipt_register_table(net, &packet_raw, &initial_table.repl);
ipt_register_table(net, &packet_raw, repl);
kfree(repl);
if (IS_ERR(net->ipv4.iptable_raw))
return PTR_ERR(net->ipv4.iptable_raw);
return 0;
Expand Down
39 changes: 7 additions & 32 deletions net/ipv4/netfilter/iptable_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,6 @@ MODULE_DESCRIPTION("iptables security table, for MAC rules");
(1 << NF_INET_FORWARD) | \
(1 << NF_INET_LOCAL_OUT)

static const struct
{
struct ipt_replace repl;
struct ipt_standard entries[3];
struct ipt_error term;
} initial_table __net_initdata = {
.repl = {
.name = "security",
.valid_hooks = SECURITY_VALID_HOOKS,
.num_entries = 4,
.size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
.hook_entry = {
[NF_INET_LOCAL_IN] = 0,
[NF_INET_FORWARD] = sizeof(struct ipt_standard),
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
},
.underflow = {
[NF_INET_LOCAL_IN] = 0,
[NF_INET_FORWARD] = sizeof(struct ipt_standard),
[NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
},
},
.entries = {
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
.term = IPT_ERROR_INIT, /* ERROR */
};

static const struct xt_table security_table = {
.name = "security",
.valid_hooks = SECURITY_VALID_HOOKS,
Expand Down Expand Up @@ -87,9 +57,14 @@ static struct nf_hook_ops *sectbl_ops __read_mostly;

static int __net_init iptable_security_net_init(struct net *net)
{
net->ipv4.iptable_security =
ipt_register_table(net, &security_table, &initial_table.repl);
struct ipt_replace *repl;

repl = ipt_alloc_initial_table(&security_table);
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_security =
ipt_register_table(net, &security_table, repl);
kfree(repl);
if (IS_ERR(net->ipv4.iptable_security))
return PTR_ERR(net->ipv4.iptable_security);

Expand Down
Loading

0 comments on commit e3eaa99

Please sign in to comment.