aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-11-04 08:27:15 -0500
committerPatrick McHardy <kaber@trash.net>2008-11-04 08:27:15 -0500
commit6beceee5aa2cb94c4ae9f0784c7d3135d343f5b5 (patch)
tree9f6bd8ee8c966a2ad5eab64a2472c395ef29e2f4 /net/bridge
parent511061e2dd1b84bb21bb97c9216a19606c29ac02 (diff)
netfilter: netns ebtables: part 2
* return ebt_table from ebt_register_table(), module code will save it into per-netns data for unregistration * duplicate ebt_table at the very beginning of registration -- it's added into list, so one ebt_table wouldn't end up in many lists (and each netns has different one) * introduce underscored tables in individial modules, this is temporary to not break bisection. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/ebtable_broute.c19
-rw-r--r--net/bridge/netfilter/ebtable_filter.c17
-rw-r--r--net/bridge/netfilter/ebtable_nat.c19
-rw-r--r--net/bridge/netfilter/ebtables.c23
4 files changed, 45 insertions, 33 deletions
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 1731ce8f7479..3277d682dfcf 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -41,22 +41,23 @@ static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
41 return 0; 41 return 0;
42} 42}
43 43
44static struct ebt_table broute_table = 44static struct ebt_table __broute_table =
45{ 45{
46 .name = "broute", 46 .name = "broute",
47 .table = &initial_table, 47 .table = &initial_table,
48 .valid_hooks = 1 << NF_BR_BROUTING, 48 .valid_hooks = 1 << NF_BR_BROUTING,
49 .lock = __RW_LOCK_UNLOCKED(broute_table.lock), 49 .lock = __RW_LOCK_UNLOCKED(__broute_table.lock),
50 .check = check, 50 .check = check,
51 .me = THIS_MODULE, 51 .me = THIS_MODULE,
52}; 52};
53static struct ebt_table *broute_table;
53 54
54static int ebt_broute(struct sk_buff *skb) 55static int ebt_broute(struct sk_buff *skb)
55{ 56{
56 int ret; 57 int ret;
57 58
58 ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, 59 ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
59 &broute_table); 60 broute_table);
60 if (ret == NF_DROP) 61 if (ret == NF_DROP)
61 return 1; /* route it */ 62 return 1; /* route it */
62 return 0; /* bridge it */ 63 return 0; /* bridge it */
@@ -64,21 +65,19 @@ static int ebt_broute(struct sk_buff *skb)
64 65
65static int __init ebtable_broute_init(void) 66static int __init ebtable_broute_init(void)
66{ 67{
67 int ret; 68 broute_table = ebt_register_table(&init_net, &__broute_table);
68 69 if (IS_ERR(broute_table))
69 ret = ebt_register_table(&init_net, &broute_table); 70 return PTR_ERR(broute_table);
70 if (ret < 0)
71 return ret;
72 /* see br_input.c */ 71 /* see br_input.c */
73 rcu_assign_pointer(br_should_route_hook, ebt_broute); 72 rcu_assign_pointer(br_should_route_hook, ebt_broute);
74 return ret; 73 return 0;
75} 74}
76 75
77static void __exit ebtable_broute_fini(void) 76static void __exit ebtable_broute_fini(void)
78{ 77{
79 rcu_assign_pointer(br_should_route_hook, NULL); 78 rcu_assign_pointer(br_should_route_hook, NULL);
80 synchronize_net(); 79 synchronize_net();
81 ebt_unregister_table(&broute_table); 80 ebt_unregister_table(broute_table);
82} 81}
83 82
84module_init(ebtable_broute_init); 83module_init(ebtable_broute_init);
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index af8953c9a57c..596564c7aa58 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -50,21 +50,22 @@ static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
50 return 0; 50 return 0;
51} 51}
52 52
53static struct ebt_table frame_filter = 53static struct ebt_table __frame_filter =
54{ 54{
55 .name = "filter", 55 .name = "filter",
56 .table = &initial_table, 56 .table = &initial_table,
57 .valid_hooks = FILTER_VALID_HOOKS, 57 .valid_hooks = FILTER_VALID_HOOKS,
58 .lock = __RW_LOCK_UNLOCKED(frame_filter.lock), 58 .lock = __RW_LOCK_UNLOCKED(__frame_filter.lock),
59 .check = check, 59 .check = check,
60 .me = THIS_MODULE, 60 .me = THIS_MODULE,
61}; 61};
62static struct ebt_table *frame_filter;
62 63
63static unsigned int 64static unsigned int
64ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, 65ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
65 const struct net_device *out, int (*okfn)(struct sk_buff *)) 66 const struct net_device *out, int (*okfn)(struct sk_buff *))
66{ 67{
67 return ebt_do_table(hook, skb, in, out, &frame_filter); 68 return ebt_do_table(hook, skb, in, out, frame_filter);
68} 69}
69 70
70static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { 71static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
@@ -95,19 +96,19 @@ static int __init ebtable_filter_init(void)
95{ 96{
96 int ret; 97 int ret;
97 98
98 ret = ebt_register_table(&init_net, &frame_filter); 99 frame_filter = ebt_register_table(&init_net, &__frame_filter);
99 if (ret < 0) 100 if (IS_ERR(frame_filter))
100 return ret; 101 return PTR_ERR(frame_filter);
101 ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); 102 ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
102 if (ret < 0) 103 if (ret < 0)
103 ebt_unregister_table(&frame_filter); 104 ebt_unregister_table(frame_filter);
104 return ret; 105 return ret;
105} 106}
106 107
107static void __exit ebtable_filter_fini(void) 108static void __exit ebtable_filter_fini(void)
108{ 109{
109 nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); 110 nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
110 ebt_unregister_table(&frame_filter); 111 ebt_unregister_table(frame_filter);
111} 112}
112 113
113module_init(ebtable_filter_init); 114module_init(ebtable_filter_init);
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index bafe16029bd7..0d8fc5bcddd1 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -50,28 +50,29 @@ static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
50 return 0; 50 return 0;
51} 51}
52 52
53static struct ebt_table frame_nat = 53static struct ebt_table __frame_nat =
54{ 54{
55 .name = "nat", 55 .name = "nat",
56 .table = &initial_table, 56 .table = &initial_table,
57 .valid_hooks = NAT_VALID_HOOKS, 57 .valid_hooks = NAT_VALID_HOOKS,
58 .lock = __RW_LOCK_UNLOCKED(frame_nat.lock), 58 .lock = __RW_LOCK_UNLOCKED(__frame_nat.lock),
59 .check = check, 59 .check = check,
60 .me = THIS_MODULE, 60 .me = THIS_MODULE,
61}; 61};
62static struct ebt_table *frame_nat;
62 63
63static unsigned int 64static unsigned int
64ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in 65ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in
65 , const struct net_device *out, int (*okfn)(struct sk_buff *)) 66 , const struct net_device *out, int (*okfn)(struct sk_buff *))
66{ 67{
67 return ebt_do_table(hook, skb, in, out, &frame_nat); 68 return ebt_do_table(hook, skb, in, out, frame_nat);
68} 69}
69 70
70static unsigned int 71static unsigned int
71ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in 72ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in
72 , const struct net_device *out, int (*okfn)(struct sk_buff *)) 73 , const struct net_device *out, int (*okfn)(struct sk_buff *))
73{ 74{
74 return ebt_do_table(hook, skb, in, out, &frame_nat); 75 return ebt_do_table(hook, skb, in, out, frame_nat);
75} 76}
76 77
77static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { 78static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
@@ -102,19 +103,19 @@ static int __init ebtable_nat_init(void)
102{ 103{
103 int ret; 104 int ret;
104 105
105 ret = ebt_register_table(&init_net, &frame_nat); 106 frame_nat = ebt_register_table(&init_net, &__frame_nat);
106 if (ret < 0) 107 if (IS_ERR(frame_nat))
107 return ret; 108 return PTR_ERR(frame_nat);
108 ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); 109 ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
109 if (ret < 0) 110 if (ret < 0)
110 ebt_unregister_table(&frame_nat); 111 ebt_unregister_table(frame_nat);
111 return ret; 112 return ret;
112} 113}
113 114
114static void __exit ebtable_nat_fini(void) 115static void __exit ebtable_nat_fini(void)
115{ 116{
116 nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); 117 nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
117 ebt_unregister_table(&frame_nat); 118 ebt_unregister_table(frame_nat);
118} 119}
119 120
120module_init(ebtable_nat_init); 121module_init(ebtable_nat_init);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index c1a82b2826eb..82e17527e21e 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1098,7 +1098,7 @@ free_newinfo:
1098 return ret; 1098 return ret;
1099} 1099}
1100 1100
1101int ebt_register_table(struct net *net, struct ebt_table *table) 1101struct ebt_table *ebt_register_table(struct net *net, struct ebt_table *table)
1102{ 1102{
1103 struct ebt_table_info *newinfo; 1103 struct ebt_table_info *newinfo;
1104 struct ebt_table *t; 1104 struct ebt_table *t;
@@ -1110,14 +1110,21 @@ int ebt_register_table(struct net *net, struct ebt_table *table)
1110 repl->entries_size == 0 || 1110 repl->entries_size == 0 ||
1111 repl->counters || table->private) { 1111 repl->counters || table->private) {
1112 BUGPRINT("Bad table data for ebt_register_table!!!\n"); 1112 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1113 return -EINVAL; 1113 return ERR_PTR(-EINVAL);
1114 }
1115
1116 /* Don't add one table to multiple lists. */
1117 table = kmemdup(table, sizeof(struct ebt_table), GFP_KERNEL);
1118 if (!table) {
1119 ret = -ENOMEM;
1120 goto out;
1114 } 1121 }
1115 1122
1116 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids; 1123 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
1117 newinfo = vmalloc(sizeof(*newinfo) + countersize); 1124 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1118 ret = -ENOMEM; 1125 ret = -ENOMEM;
1119 if (!newinfo) 1126 if (!newinfo)
1120 return -ENOMEM; 1127 goto free_table;
1121 1128
1122 p = vmalloc(repl->entries_size); 1129 p = vmalloc(repl->entries_size);
1123 if (!p) 1130 if (!p)
@@ -1149,7 +1156,7 @@ int ebt_register_table(struct net *net, struct ebt_table *table)
1149 1156
1150 if (table->check && table->check(newinfo, table->valid_hooks)) { 1157 if (table->check && table->check(newinfo, table->valid_hooks)) {
1151 BUGPRINT("The table doesn't like its own initial data, lol\n"); 1158 BUGPRINT("The table doesn't like its own initial data, lol\n");
1152 return -EINVAL; 1159 return ERR_PTR(-EINVAL);
1153 } 1160 }
1154 1161
1155 table->private = newinfo; 1162 table->private = newinfo;
@@ -1173,7 +1180,7 @@ int ebt_register_table(struct net *net, struct ebt_table *table)
1173 } 1180 }
1174 list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]); 1181 list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
1175 mutex_unlock(&ebt_mutex); 1182 mutex_unlock(&ebt_mutex);
1176 return 0; 1183 return table;
1177free_unlock: 1184free_unlock:
1178 mutex_unlock(&ebt_mutex); 1185 mutex_unlock(&ebt_mutex);
1179free_chainstack: 1186free_chainstack:
@@ -1185,7 +1192,10 @@ free_chainstack:
1185 vfree(newinfo->entries); 1192 vfree(newinfo->entries);
1186free_newinfo: 1193free_newinfo:
1187 vfree(newinfo); 1194 vfree(newinfo);
1188 return ret; 1195free_table:
1196 kfree(table);
1197out:
1198 return ERR_PTR(ret);
1189} 1199}
1190 1200
1191void ebt_unregister_table(struct ebt_table *table) 1201void ebt_unregister_table(struct ebt_table *table)
@@ -1206,6 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table)
1206 vfree(table->private->chainstack); 1216 vfree(table->private->chainstack);
1207 } 1217 }
1208 vfree(table->private); 1218 vfree(table->private);
1219 kfree(table);
1209} 1220}
1210 1221
1211/* userspace just supplied us with counters */ 1222/* userspace just supplied us with counters */