aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_netfilter.c2
-rw-r--r--net/bridge/netfilter/ebtable_broute.c26
-rw-r--r--net/bridge/netfilter/ebtable_filter.c41
-rw-r--r--net/bridge/netfilter/ebtable_nat.c38
-rw-r--r--net/bridge/netfilter/ebtables.c52
5 files changed, 118 insertions, 41 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 274194b78247..a65e43a17fbb 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -369,7 +369,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
369 if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev)) 369 if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
370 goto free_skb; 370 goto free_skb;
371 371
372 if (!ip_route_output_key(&init_net, &rt, &fl)) { 372 if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
373 /* - Bridged-and-DNAT'ed traffic doesn't 373 /* - Bridged-and-DNAT'ed traffic doesn't
374 * require ip_forwarding. */ 374 * require ip_forwarding. */
375 if (((struct dst_entry *)rt)->dev == dev) { 375 if (((struct dst_entry *)rt)->dev == dev) {
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index 246626bb0c87..8604dfc1fc3b 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -56,29 +56,47 @@ static int ebt_broute(struct sk_buff *skb)
56 int ret; 56 int ret;
57 57
58 ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, 58 ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
59 &broute_table); 59 dev_net(skb->dev)->xt.broute_table);
60 if (ret == NF_DROP) 60 if (ret == NF_DROP)
61 return 1; /* route it */ 61 return 1; /* route it */
62 return 0; /* bridge it */ 62 return 0; /* bridge it */
63} 63}
64 64
65static int __net_init broute_net_init(struct net *net)
66{
67 net->xt.broute_table = ebt_register_table(net, &broute_table);
68 if (IS_ERR(net->xt.broute_table))
69 return PTR_ERR(net->xt.broute_table);
70 return 0;
71}
72
73static void __net_exit broute_net_exit(struct net *net)
74{
75 ebt_unregister_table(net->xt.broute_table);
76}
77
78static struct pernet_operations broute_net_ops = {
79 .init = broute_net_init,
80 .exit = broute_net_exit,
81};
82
65static int __init ebtable_broute_init(void) 83static int __init ebtable_broute_init(void)
66{ 84{
67 int ret; 85 int ret;
68 86
69 ret = ebt_register_table(&broute_table); 87 ret = register_pernet_subsys(&broute_net_ops);
70 if (ret < 0) 88 if (ret < 0)
71 return ret; 89 return ret;
72 /* see br_input.c */ 90 /* see br_input.c */
73 rcu_assign_pointer(br_should_route_hook, ebt_broute); 91 rcu_assign_pointer(br_should_route_hook, ebt_broute);
74 return ret; 92 return 0;
75} 93}
76 94
77static void __exit ebtable_broute_fini(void) 95static void __exit ebtable_broute_fini(void)
78{ 96{
79 rcu_assign_pointer(br_should_route_hook, NULL); 97 rcu_assign_pointer(br_should_route_hook, NULL);
80 synchronize_net(); 98 synchronize_net();
81 ebt_unregister_table(&broute_table); 99 unregister_pernet_subsys(&broute_net_ops);
82} 100}
83 101
84module_init(ebtable_broute_init); 102module_init(ebtable_broute_init);
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 1a58af51a2e2..2b2e8040a9c6 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -61,29 +61,36 @@ static struct ebt_table frame_filter =
61}; 61};
62 62
63static unsigned int 63static unsigned int
64ebt_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, 64ebt_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
65 const struct net_device *out, int (*okfn)(struct sk_buff *)) 65 const struct net_device *out, int (*okfn)(struct sk_buff *))
66{ 66{
67 return ebt_do_table(hook, skb, in, out, &frame_filter); 67 return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_filter);
68}
69
70static unsigned int
71ebt_out_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
72 const struct net_device *out, int (*okfn)(struct sk_buff *))
73{
74 return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_filter);
68} 75}
69 76
70static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { 77static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
71 { 78 {
72 .hook = ebt_hook, 79 .hook = ebt_in_hook,
73 .owner = THIS_MODULE, 80 .owner = THIS_MODULE,
74 .pf = PF_BRIDGE, 81 .pf = PF_BRIDGE,
75 .hooknum = NF_BR_LOCAL_IN, 82 .hooknum = NF_BR_LOCAL_IN,
76 .priority = NF_BR_PRI_FILTER_BRIDGED, 83 .priority = NF_BR_PRI_FILTER_BRIDGED,
77 }, 84 },
78 { 85 {
79 .hook = ebt_hook, 86 .hook = ebt_in_hook,
80 .owner = THIS_MODULE, 87 .owner = THIS_MODULE,
81 .pf = PF_BRIDGE, 88 .pf = PF_BRIDGE,
82 .hooknum = NF_BR_FORWARD, 89 .hooknum = NF_BR_FORWARD,
83 .priority = NF_BR_PRI_FILTER_BRIDGED, 90 .priority = NF_BR_PRI_FILTER_BRIDGED,
84 }, 91 },
85 { 92 {
86 .hook = ebt_hook, 93 .hook = ebt_out_hook,
87 .owner = THIS_MODULE, 94 .owner = THIS_MODULE,
88 .pf = PF_BRIDGE, 95 .pf = PF_BRIDGE,
89 .hooknum = NF_BR_LOCAL_OUT, 96 .hooknum = NF_BR_LOCAL_OUT,
@@ -91,23 +98,41 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
91 }, 98 },
92}; 99};
93 100
101static int __net_init frame_filter_net_init(struct net *net)
102{
103 net->xt.frame_filter = ebt_register_table(net, &frame_filter);
104 if (IS_ERR(net->xt.frame_filter))
105 return PTR_ERR(net->xt.frame_filter);
106 return 0;
107}
108
109static void __net_exit frame_filter_net_exit(struct net *net)
110{
111 ebt_unregister_table(net->xt.frame_filter);
112}
113
114static struct pernet_operations frame_filter_net_ops = {
115 .init = frame_filter_net_init,
116 .exit = frame_filter_net_exit,
117};
118
94static int __init ebtable_filter_init(void) 119static int __init ebtable_filter_init(void)
95{ 120{
96 int ret; 121 int ret;
97 122
98 ret = ebt_register_table(&frame_filter); 123 ret = register_pernet_subsys(&frame_filter_net_ops);
99 if (ret < 0) 124 if (ret < 0)
100 return ret; 125 return ret;
101 ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); 126 ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
102 if (ret < 0) 127 if (ret < 0)
103 ebt_unregister_table(&frame_filter); 128 unregister_pernet_subsys(&frame_filter_net_ops);
104 return ret; 129 return ret;
105} 130}
106 131
107static void __exit ebtable_filter_fini(void) 132static void __exit ebtable_filter_fini(void)
108{ 133{
109 nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter)); 134 nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
110 ebt_unregister_table(&frame_filter); 135 unregister_pernet_subsys(&frame_filter_net_ops);
111} 136}
112 137
113module_init(ebtable_filter_init); 138module_init(ebtable_filter_init);
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index f60c1e78e575..3fe1ae87e35f 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -61,36 +61,36 @@ static struct ebt_table frame_nat =
61}; 61};
62 62
63static unsigned int 63static unsigned int
64ebt_nat_dst(unsigned int hook, struct sk_buff *skb, const struct net_device *in 64ebt_nat_in(unsigned int hook, struct sk_buff *skb, const struct net_device *in
65 , const struct net_device *out, int (*okfn)(struct sk_buff *)) 65 , const struct net_device *out, int (*okfn)(struct sk_buff *))
66{ 66{
67 return ebt_do_table(hook, skb, in, out, &frame_nat); 67 return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_nat);
68} 68}
69 69
70static unsigned int 70static unsigned int
71ebt_nat_src(unsigned int hook, struct sk_buff *skb, const struct net_device *in 71ebt_nat_out(unsigned int hook, struct sk_buff *skb, const struct net_device *in
72 , const struct net_device *out, int (*okfn)(struct sk_buff *)) 72 , const struct net_device *out, int (*okfn)(struct sk_buff *))
73{ 73{
74 return ebt_do_table(hook, skb, in, out, &frame_nat); 74 return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_nat);
75} 75}
76 76
77static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { 77static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
78 { 78 {
79 .hook = ebt_nat_dst, 79 .hook = ebt_nat_out,
80 .owner = THIS_MODULE, 80 .owner = THIS_MODULE,
81 .pf = PF_BRIDGE, 81 .pf = PF_BRIDGE,
82 .hooknum = NF_BR_LOCAL_OUT, 82 .hooknum = NF_BR_LOCAL_OUT,
83 .priority = NF_BR_PRI_NAT_DST_OTHER, 83 .priority = NF_BR_PRI_NAT_DST_OTHER,
84 }, 84 },
85 { 85 {
86 .hook = ebt_nat_src, 86 .hook = ebt_nat_out,
87 .owner = THIS_MODULE, 87 .owner = THIS_MODULE,
88 .pf = PF_BRIDGE, 88 .pf = PF_BRIDGE,
89 .hooknum = NF_BR_POST_ROUTING, 89 .hooknum = NF_BR_POST_ROUTING,
90 .priority = NF_BR_PRI_NAT_SRC, 90 .priority = NF_BR_PRI_NAT_SRC,
91 }, 91 },
92 { 92 {
93 .hook = ebt_nat_dst, 93 .hook = ebt_nat_in,
94 .owner = THIS_MODULE, 94 .owner = THIS_MODULE,
95 .pf = PF_BRIDGE, 95 .pf = PF_BRIDGE,
96 .hooknum = NF_BR_PRE_ROUTING, 96 .hooknum = NF_BR_PRE_ROUTING,
@@ -98,23 +98,41 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
98 }, 98 },
99}; 99};
100 100
101static int __net_init frame_nat_net_init(struct net *net)
102{
103 net->xt.frame_nat = ebt_register_table(net, &frame_nat);
104 if (IS_ERR(net->xt.frame_nat))
105 return PTR_ERR(net->xt.frame_nat);
106 return 0;
107}
108
109static void __net_exit frame_nat_net_exit(struct net *net)
110{
111 ebt_unregister_table(net->xt.frame_nat);
112}
113
114static struct pernet_operations frame_nat_net_ops = {
115 .init = frame_nat_net_init,
116 .exit = frame_nat_net_exit,
117};
118
101static int __init ebtable_nat_init(void) 119static int __init ebtable_nat_init(void)
102{ 120{
103 int ret; 121 int ret;
104 122
105 ret = ebt_register_table(&frame_nat); 123 ret = register_pernet_subsys(&frame_nat_net_ops);
106 if (ret < 0) 124 if (ret < 0)
107 return ret; 125 return ret;
108 ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); 126 ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
109 if (ret < 0) 127 if (ret < 0)
110 ebt_unregister_table(&frame_nat); 128 unregister_pernet_subsys(&frame_nat_net_ops);
111 return ret; 129 return ret;
112} 130}
113 131
114static void __exit ebtable_nat_fini(void) 132static void __exit ebtable_nat_fini(void)
115{ 133{
116 nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat)); 134 nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
117 ebt_unregister_table(&frame_nat); 135 unregister_pernet_subsys(&frame_nat_net_ops);
118} 136}
119 137
120module_init(ebtable_nat_init); 138module_init(ebtable_nat_init);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 0fa208e86405..fa108c46e851 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -55,7 +55,6 @@
55 55
56 56
57static DEFINE_MUTEX(ebt_mutex); 57static DEFINE_MUTEX(ebt_mutex);
58static LIST_HEAD(ebt_tables);
59 58
60static struct xt_target ebt_standard_target = { 59static struct xt_target ebt_standard_target = {
61 .name = "standard", 60 .name = "standard",
@@ -315,9 +314,11 @@ find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
315} 314}
316 315
317static inline struct ebt_table * 316static inline struct ebt_table *
318find_table_lock(const char *name, int *error, struct mutex *mutex) 317find_table_lock(struct net *net, const char *name, int *error,
318 struct mutex *mutex)
319{ 319{
320 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); 320 return find_inlist_lock(&net->xt.tables[NFPROTO_BRIDGE], name,
321 "ebtable_", error, mutex);
321} 322}
322 323
323static inline int 324static inline int
@@ -944,7 +945,7 @@ static void get_counters(struct ebt_counter *oldcounters,
944} 945}
945 946
946/* replace the table */ 947/* replace the table */
947static int do_replace(void __user *user, unsigned int len) 948static int do_replace(struct net *net, void __user *user, unsigned int len)
948{ 949{
949 int ret, i, countersize; 950 int ret, i, countersize;
950 struct ebt_table_info *newinfo; 951 struct ebt_table_info *newinfo;
@@ -1016,7 +1017,7 @@ static int do_replace(void __user *user, unsigned int len)
1016 if (ret != 0) 1017 if (ret != 0)
1017 goto free_counterstmp; 1018 goto free_counterstmp;
1018 1019
1019 t = find_table_lock(tmp.name, &ret, &ebt_mutex); 1020 t = find_table_lock(net, tmp.name, &ret, &ebt_mutex);
1020 if (!t) { 1021 if (!t) {
1021 ret = -ENOENT; 1022 ret = -ENOENT;
1022 goto free_iterate; 1023 goto free_iterate;
@@ -1097,7 +1098,7 @@ free_newinfo:
1097 return ret; 1098 return ret;
1098} 1099}
1099 1100
1100int ebt_register_table(struct ebt_table *table) 1101struct ebt_table *ebt_register_table(struct net *net, struct ebt_table *table)
1101{ 1102{
1102 struct ebt_table_info *newinfo; 1103 struct ebt_table_info *newinfo;
1103 struct ebt_table *t; 1104 struct ebt_table *t;
@@ -1109,14 +1110,21 @@ int ebt_register_table(struct ebt_table *table)
1109 repl->entries_size == 0 || 1110 repl->entries_size == 0 ||
1110 repl->counters || table->private) { 1111 repl->counters || table->private) {
1111 BUGPRINT("Bad table data for ebt_register_table!!!\n"); 1112 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1112 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;
1113 } 1121 }
1114 1122
1115 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids; 1123 countersize = COUNTER_OFFSET(repl->nentries) * nr_cpu_ids;
1116 newinfo = vmalloc(sizeof(*newinfo) + countersize); 1124 newinfo = vmalloc(sizeof(*newinfo) + countersize);
1117 ret = -ENOMEM; 1125 ret = -ENOMEM;
1118 if (!newinfo) 1126 if (!newinfo)
1119 return -ENOMEM; 1127 goto free_table;
1120 1128
1121 p = vmalloc(repl->entries_size); 1129 p = vmalloc(repl->entries_size);
1122 if (!p) 1130 if (!p)
@@ -1148,7 +1156,7 @@ int ebt_register_table(struct ebt_table *table)
1148 1156
1149 if (table->check && table->check(newinfo, table->valid_hooks)) { 1157 if (table->check && table->check(newinfo, table->valid_hooks)) {
1150 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");
1151 return -EINVAL; 1159 return ERR_PTR(-EINVAL);
1152 } 1160 }
1153 1161
1154 table->private = newinfo; 1162 table->private = newinfo;
@@ -1157,7 +1165,7 @@ int ebt_register_table(struct ebt_table *table)
1157 if (ret != 0) 1165 if (ret != 0)
1158 goto free_chainstack; 1166 goto free_chainstack;
1159 1167
1160 list_for_each_entry(t, &ebt_tables, list) { 1168 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
1161 if (strcmp(t->name, table->name) == 0) { 1169 if (strcmp(t->name, table->name) == 0) {
1162 ret = -EEXIST; 1170 ret = -EEXIST;
1163 BUGPRINT("Table name already exists\n"); 1171 BUGPRINT("Table name already exists\n");
@@ -1170,9 +1178,9 @@ int ebt_register_table(struct ebt_table *table)
1170 ret = -ENOENT; 1178 ret = -ENOENT;
1171 goto free_unlock; 1179 goto free_unlock;
1172 } 1180 }
1173 list_add(&table->list, &ebt_tables); 1181 list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
1174 mutex_unlock(&ebt_mutex); 1182 mutex_unlock(&ebt_mutex);
1175 return 0; 1183 return table;
1176free_unlock: 1184free_unlock:
1177 mutex_unlock(&ebt_mutex); 1185 mutex_unlock(&ebt_mutex);
1178free_chainstack: 1186free_chainstack:
@@ -1184,7 +1192,10 @@ free_chainstack:
1184 vfree(newinfo->entries); 1192 vfree(newinfo->entries);
1185free_newinfo: 1193free_newinfo:
1186 vfree(newinfo); 1194 vfree(newinfo);
1187 return ret; 1195free_table:
1196 kfree(table);
1197out:
1198 return ERR_PTR(ret);
1188} 1199}
1189 1200
1190void ebt_unregister_table(struct ebt_table *table) 1201void ebt_unregister_table(struct ebt_table *table)
@@ -1198,6 +1209,10 @@ void ebt_unregister_table(struct ebt_table *table)
1198 mutex_lock(&ebt_mutex); 1209 mutex_lock(&ebt_mutex);
1199 list_del(&table->list); 1210 list_del(&table->list);
1200 mutex_unlock(&ebt_mutex); 1211 mutex_unlock(&ebt_mutex);
1212 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
1213 ebt_cleanup_entry, NULL);
1214 if (table->private->nentries)
1215 module_put(table->me);
1201 vfree(table->private->entries); 1216 vfree(table->private->entries);
1202 if (table->private->chainstack) { 1217 if (table->private->chainstack) {
1203 for_each_possible_cpu(i) 1218 for_each_possible_cpu(i)
@@ -1205,10 +1220,11 @@ void ebt_unregister_table(struct ebt_table *table)
1205 vfree(table->private->chainstack); 1220 vfree(table->private->chainstack);
1206 } 1221 }
1207 vfree(table->private); 1222 vfree(table->private);
1223 kfree(table);
1208} 1224}
1209 1225
1210/* userspace just supplied us with counters */ 1226/* userspace just supplied us with counters */
1211static int update_counters(void __user *user, unsigned int len) 1227static int update_counters(struct net *net, void __user *user, unsigned int len)
1212{ 1228{
1213 int i, ret; 1229 int i, ret;
1214 struct ebt_counter *tmp; 1230 struct ebt_counter *tmp;
@@ -1228,7 +1244,7 @@ static int update_counters(void __user *user, unsigned int len)
1228 return -ENOMEM; 1244 return -ENOMEM;
1229 } 1245 }
1230 1246
1231 t = find_table_lock(hlp.name, &ret, &ebt_mutex); 1247 t = find_table_lock(net, hlp.name, &ret, &ebt_mutex);
1232 if (!t) 1248 if (!t)
1233 goto free_tmp; 1249 goto free_tmp;
1234 1250
@@ -1386,10 +1402,10 @@ static int do_ebt_set_ctl(struct sock *sk,
1386 1402
1387 switch(cmd) { 1403 switch(cmd) {
1388 case EBT_SO_SET_ENTRIES: 1404 case EBT_SO_SET_ENTRIES:
1389 ret = do_replace(user, len); 1405 ret = do_replace(sock_net(sk), user, len);
1390 break; 1406 break;
1391 case EBT_SO_SET_COUNTERS: 1407 case EBT_SO_SET_COUNTERS:
1392 ret = update_counters(user, len); 1408 ret = update_counters(sock_net(sk), user, len);
1393 break; 1409 break;
1394 default: 1410 default:
1395 ret = -EINVAL; 1411 ret = -EINVAL;
@@ -1406,7 +1422,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1406 if (copy_from_user(&tmp, user, sizeof(tmp))) 1422 if (copy_from_user(&tmp, user, sizeof(tmp)))
1407 return -EFAULT; 1423 return -EFAULT;
1408 1424
1409 t = find_table_lock(tmp.name, &ret, &ebt_mutex); 1425 t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex);
1410 if (!t) 1426 if (!t)
1411 return ret; 1427 return ret;
1412 1428