aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-09-18 05:29:03 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-09-26 12:42:31 -0400
commit34666d467cbf1e2e3c7bb15a63eccfb582cdd71f (patch)
treef4b44a26f14d9c06dbb2d5df9284f0a00ee974bc
parent7276ca3fa23864133f5ee7431c51546d9b7f695f (diff)
netfilter: bridge: move br_netfilter out of the core
Jesper reported that br_netfilter always registers the hooks since this is part of the bridge core. This harms performance for people that don't need this. This patch modularizes br_netfilter so it can be rmmod'ed, thus, the hooks can be unregistered. I think the bridge netfilter should have been a separated module since the beginning, Patrick agreed on that. Note that this is breaking compatibility for users that expect that bridge netfilter is going to be available after explicitly 'modprobe bridge' or via automatic load through brctl. However, the damage can be easily undone by modprobing br_netfilter. The bridge core also spots a message to provide a clue to people that didn't notice that this has been deprecated. On top of that, the plan is that nftables will not rely on this software layer, but integrate the connection tracking into the bridge layer to enable stateful filtering and NAT, which is was bridge netfilter users seem to require. This patch still keeps the fake_dst_ops in the bridge core, since this is required by when the bridge port is initialized. So we can safely modprobe/rmmod br_netfilter anytime. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Acked-by: Florian Westphal <fw@strlen.de>
-rw-r--r--include/linux/netfilter_bridge.h2
-rw-r--r--include/linux/skbuff.h12
-rw-r--r--include/net/neighbour.h2
-rw-r--r--include/net/netfilter/ipv4/nf_reject.h2
-rw-r--r--include/net/netfilter/ipv6/nf_reject.h2
-rw-r--r--net/Kconfig7
-rw-r--r--net/bridge/Makefile5
-rw-r--r--net/bridge/br.c14
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_forward.c2
-rw-r--r--net/bridge/br_input.c1
-rw-r--r--net/bridge/br_netfilter.c88
-rw-r--r--net/bridge/br_netlink.c2
-rw-r--r--net/bridge/br_nf_core.c96
-rw-r--r--net/bridge/br_private.h12
-rw-r--r--net/bridge/br_sysfs_br.c4
16 files changed, 151 insertions, 104 deletions
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index fe996d59de64..c755e4971fa3 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -15,7 +15,7 @@ enum nf_br_hook_priorities {
15 NF_BR_PRI_LAST = INT_MAX, 15 NF_BR_PRI_LAST = INT_MAX,
16}; 16};
17 17
18#ifdef CONFIG_BRIDGE_NETFILTER 18#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
19 19
20#define BRNF_PKT_TYPE 0x01 20#define BRNF_PKT_TYPE 0x01
21#define BRNF_BRIDGED_DNAT 0x02 21#define BRNF_BRIDGED_DNAT 0x02
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 07c9fdd0c126..c4ff43f84573 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -156,7 +156,7 @@ struct nf_conntrack {
156}; 156};
157#endif 157#endif
158 158
159#ifdef CONFIG_BRIDGE_NETFILTER 159#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
160struct nf_bridge_info { 160struct nf_bridge_info {
161 atomic_t use; 161 atomic_t use;
162 unsigned int mask; 162 unsigned int mask;
@@ -560,7 +560,7 @@ struct sk_buff {
560#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 560#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
561 struct nf_conntrack *nfct; 561 struct nf_conntrack *nfct;
562#endif 562#endif
563#ifdef CONFIG_BRIDGE_NETFILTER 563#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
564 struct nf_bridge_info *nf_bridge; 564 struct nf_bridge_info *nf_bridge;
565#endif 565#endif
566 566
@@ -2977,7 +2977,7 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
2977 atomic_inc(&nfct->use); 2977 atomic_inc(&nfct->use);
2978} 2978}
2979#endif 2979#endif
2980#ifdef CONFIG_BRIDGE_NETFILTER 2980#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
2981static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) 2981static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2982{ 2982{
2983 if (nf_bridge && atomic_dec_and_test(&nf_bridge->use)) 2983 if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
@@ -2995,7 +2995,7 @@ static inline void nf_reset(struct sk_buff *skb)
2995 nf_conntrack_put(skb->nfct); 2995 nf_conntrack_put(skb->nfct);
2996 skb->nfct = NULL; 2996 skb->nfct = NULL;
2997#endif 2997#endif
2998#ifdef CONFIG_BRIDGE_NETFILTER 2998#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
2999 nf_bridge_put(skb->nf_bridge); 2999 nf_bridge_put(skb->nf_bridge);
3000 skb->nf_bridge = NULL; 3000 skb->nf_bridge = NULL;
3001#endif 3001#endif
@@ -3016,7 +3016,7 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
3016 nf_conntrack_get(src->nfct); 3016 nf_conntrack_get(src->nfct);
3017 dst->nfctinfo = src->nfctinfo; 3017 dst->nfctinfo = src->nfctinfo;
3018#endif 3018#endif
3019#ifdef CONFIG_BRIDGE_NETFILTER 3019#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3020 dst->nf_bridge = src->nf_bridge; 3020 dst->nf_bridge = src->nf_bridge;
3021 nf_bridge_get(src->nf_bridge); 3021 nf_bridge_get(src->nf_bridge);
3022#endif 3022#endif
@@ -3030,7 +3030,7 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
3030#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 3030#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
3031 nf_conntrack_put(dst->nfct); 3031 nf_conntrack_put(dst->nfct);
3032#endif 3032#endif
3033#ifdef CONFIG_BRIDGE_NETFILTER 3033#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3034 nf_bridge_put(dst->nf_bridge); 3034 nf_bridge_put(dst->nf_bridge);
3035#endif 3035#endif
3036 __nf_copy(dst, src); 3036 __nf_copy(dst, src);
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 47f425464f84..f60558d0254c 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -373,7 +373,7 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
373 return 0; 373 return 0;
374} 374}
375 375
376#ifdef CONFIG_BRIDGE_NETFILTER 376#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
377static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) 377static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
378{ 378{
379 unsigned int seq, hh_alen; 379 unsigned int seq, hh_alen;
diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h
index 931fbf812171..f713b5a31d62 100644
--- a/include/net/netfilter/ipv4/nf_reject.h
+++ b/include/net/netfilter/ipv4/nf_reject.h
@@ -98,7 +98,7 @@ static void nf_send_reset(struct sk_buff *oldskb, int hook)
98 98
99 nf_ct_attach(nskb, oldskb); 99 nf_ct_attach(nskb, oldskb);
100 100
101#ifdef CONFIG_BRIDGE_NETFILTER 101#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
102 /* If we use ip_local_out for bridged traffic, the MAC source on 102 /* If we use ip_local_out for bridged traffic, the MAC source on
103 * the RST will be ours, instead of the destination's. This confuses 103 * the RST will be ours, instead of the destination's. This confuses
104 * some routers/firewalls, and they drop the packet. So we need to 104 * some routers/firewalls, and they drop the packet. So we need to
diff --git a/include/net/netfilter/ipv6/nf_reject.h b/include/net/netfilter/ipv6/nf_reject.h
index 710d17ed70b4..7a10cfcd8e33 100644
--- a/include/net/netfilter/ipv6/nf_reject.h
+++ b/include/net/netfilter/ipv6/nf_reject.h
@@ -147,7 +147,7 @@ static void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
147 147
148 nf_ct_attach(nskb, oldskb); 148 nf_ct_attach(nskb, oldskb);
149 149
150#ifdef CONFIG_BRIDGE_NETFILTER 150#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
151 /* If we use ip6_local_out for bridged traffic, the MAC source on 151 /* If we use ip6_local_out for bridged traffic, the MAC source on
152 * the RST will be ours, instead of the destination's. This confuses 152 * the RST will be ours, instead of the destination's. This confuses
153 * some routers/firewalls, and they drop the packet. So we need to 153 * some routers/firewalls, and they drop the packet. So we need to
diff --git a/net/Kconfig b/net/Kconfig
index 4051fdfa4367..dc5d700d05e7 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -176,10 +176,11 @@ config NETFILTER_ADVANCED
176 If unsure, say Y. 176 If unsure, say Y.
177 177
178config BRIDGE_NETFILTER 178config BRIDGE_NETFILTER
179 bool "Bridged IP/ARP packets filtering" 179 tristate "Bridged IP/ARP packets filtering"
180 depends on BRIDGE && NETFILTER && INET 180 depends on (BRIDGE || BRIDGE=n)
181 depends on NETFILTER && INET
181 depends on NETFILTER_ADVANCED 182 depends on NETFILTER_ADVANCED
182 default y 183 default m
183 ---help--- 184 ---help---
184 Enabling this option will let arptables resp. iptables see bridged 185 Enabling this option will let arptables resp. iptables see bridged
185 ARP resp. IP traffic. If you want a bridging firewall, you probably 186 ARP resp. IP traffic. If you want a bridging firewall, you probably
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 8590b942bffa..5e3eac5dc8b9 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -6,11 +6,12 @@ obj-$(CONFIG_BRIDGE) += bridge.o
6 6
7bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \ 7bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
8 br_ioctl.o br_stp.o br_stp_bpdu.o \ 8 br_ioctl.o br_stp.o br_stp_bpdu.o \
9 br_stp_if.o br_stp_timer.o br_netlink.o 9 br_stp_if.o br_stp_timer.o br_netlink.o \
10 br_nf_core.o
10 11
11bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o 12bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
12 13
13bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o 14obj-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
14 15
15bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o 16bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
16 17
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 1a755a1e5410..44425aff7cba 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -161,7 +161,7 @@ static int __init br_init(void)
161 if (err) 161 if (err)
162 goto err_out1; 162 goto err_out1;
163 163
164 err = br_netfilter_init(); 164 err = br_nf_core_init();
165 if (err) 165 if (err)
166 goto err_out2; 166 goto err_out2;
167 167
@@ -179,11 +179,16 @@ static int __init br_init(void)
179 br_fdb_test_addr_hook = br_fdb_test_addr; 179 br_fdb_test_addr_hook = br_fdb_test_addr;
180#endif 180#endif
181 181
182 pr_info("bridge: automatic filtering via arp/ip/ip6tables has been "
183 "deprecated. Update your scripts to load br_netfilter if you "
184 "need this.\n");
185
182 return 0; 186 return 0;
187
183err_out4: 188err_out4:
184 unregister_netdevice_notifier(&br_device_notifier); 189 unregister_netdevice_notifier(&br_device_notifier);
185err_out3: 190err_out3:
186 br_netfilter_fini(); 191 br_nf_core_fini();
187err_out2: 192err_out2:
188 unregister_pernet_subsys(&br_net_ops); 193 unregister_pernet_subsys(&br_net_ops);
189err_out1: 194err_out1:
@@ -196,20 +201,17 @@ err_out:
196static void __exit br_deinit(void) 201static void __exit br_deinit(void)
197{ 202{
198 stp_proto_unregister(&br_stp_proto); 203 stp_proto_unregister(&br_stp_proto);
199
200 br_netlink_fini(); 204 br_netlink_fini();
201 unregister_netdevice_notifier(&br_device_notifier); 205 unregister_netdevice_notifier(&br_device_notifier);
202 brioctl_set(NULL); 206 brioctl_set(NULL);
203
204 unregister_pernet_subsys(&br_net_ops); 207 unregister_pernet_subsys(&br_net_ops);
205 208
206 rcu_barrier(); /* Wait for completion of call_rcu()'s */ 209 rcu_barrier(); /* Wait for completion of call_rcu()'s */
207 210
208 br_netfilter_fini(); 211 br_nf_core_fini();
209#if IS_ENABLED(CONFIG_ATM_LANE) 212#if IS_ENABLED(CONFIG_ATM_LANE)
210 br_fdb_test_addr_hook = NULL; 213 br_fdb_test_addr_hook = NULL;
211#endif 214#endif
212
213 br_fdb_fini(); 215 br_fdb_fini();
214} 216}
215 217
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 568cccd39a3d..659cac15c0df 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -36,7 +36,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
36 u16 vid = 0; 36 u16 vid = 0;
37 37
38 rcu_read_lock(); 38 rcu_read_lock();
39#ifdef CONFIG_BRIDGE_NETFILTER 39#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
40 if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { 40 if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) {
41 br_nf_pre_routing_finish_bridge_slow(skb); 41 br_nf_pre_routing_finish_bridge_slow(skb);
42 rcu_read_unlock(); 42 rcu_read_unlock();
@@ -167,7 +167,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
167 167
168 dev->mtu = new_mtu; 168 dev->mtu = new_mtu;
169 169
170#ifdef CONFIG_BRIDGE_NETFILTER 170#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
171 /* remember the MTU in the rtable for PMTU */ 171 /* remember the MTU in the rtable for PMTU */
172 dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu); 172 dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
173#endif 173#endif
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 056b67b0e277..992ec49a96aa 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -49,6 +49,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
49 49
50 return 0; 50 return 0;
51} 51}
52EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
52 53
53int br_forward_finish(struct sk_buff *skb) 54int br_forward_finish(struct sk_buff *skb)
54{ 55{
@@ -56,6 +57,7 @@ int br_forward_finish(struct sk_buff *skb)
56 br_dev_queue_push_xmit); 57 br_dev_queue_push_xmit);
57 58
58} 59}
60EXPORT_SYMBOL_GPL(br_forward_finish);
59 61
60static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) 62static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
61{ 63{
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 366c43649079..6fd5522df696 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -140,6 +140,7 @@ drop:
140 kfree_skb(skb); 140 kfree_skb(skb);
141 goto out; 141 goto out;
142} 142}
143EXPORT_SYMBOL_GPL(br_handle_frame_finish);
143 144
144/* note: already called with rcu_read_lock */ 145/* note: already called with rcu_read_lock */
145static int br_handle_local_finish(struct sk_buff *skb) 146static int br_handle_local_finish(struct sk_buff *skb)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 61929a7cd815..97e43937aaca 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -111,66 +111,6 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
111 pppoe_proto(skb) == htons(PPP_IPV6) && \ 111 pppoe_proto(skb) == htons(PPP_IPV6) && \
112 brnf_filter_pppoe_tagged) 112 brnf_filter_pppoe_tagged)
113 113
114static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
115 struct sk_buff *skb, u32 mtu)
116{
117}
118
119static void fake_redirect(struct dst_entry *dst, struct sock *sk,
120 struct sk_buff *skb)
121{
122}
123
124static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
125{
126 return NULL;
127}
128
129static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
130 struct sk_buff *skb,
131 const void *daddr)
132{
133 return NULL;
134}
135
136static unsigned int fake_mtu(const struct dst_entry *dst)
137{
138 return dst->dev->mtu;
139}
140
141static struct dst_ops fake_dst_ops = {
142 .family = AF_INET,
143 .protocol = cpu_to_be16(ETH_P_IP),
144 .update_pmtu = fake_update_pmtu,
145 .redirect = fake_redirect,
146 .cow_metrics = fake_cow_metrics,
147 .neigh_lookup = fake_neigh_lookup,
148 .mtu = fake_mtu,
149};
150
151/*
152 * Initialize bogus route table used to keep netfilter happy.
153 * Currently, we fill in the PMTU entry because netfilter
154 * refragmentation needs it, and the rt_flags entry because
155 * ipt_REJECT needs it. Future netfilter modules might
156 * require us to fill additional fields.
157 */
158static const u32 br_dst_default_metrics[RTAX_MAX] = {
159 [RTAX_MTU - 1] = 1500,
160};
161
162void br_netfilter_rtable_init(struct net_bridge *br)
163{
164 struct rtable *rt = &br->fake_rtable;
165
166 atomic_set(&rt->dst.__refcnt, 1);
167 rt->dst.dev = br->dev;
168 rt->dst.path = &rt->dst;
169 dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
170 rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE;
171 rt->dst.ops = &fake_dst_ops;
172}
173
174static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) 114static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
175{ 115{
176 struct net_bridge_port *port; 116 struct net_bridge_port *port;
@@ -1031,38 +971,42 @@ static struct ctl_table brnf_table[] = {
1031}; 971};
1032#endif 972#endif
1033 973
1034int __init br_netfilter_init(void) 974static int __init br_netfilter_init(void)
1035{ 975{
1036 int ret; 976 int ret;
1037 977
1038 ret = dst_entries_init(&fake_dst_ops); 978 ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1039 if (ret < 0) 979 if (ret < 0)
1040 return ret; 980 return ret;
1041 981
1042 ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1043 if (ret < 0) {
1044 dst_entries_destroy(&fake_dst_ops);
1045 return ret;
1046 }
1047#ifdef CONFIG_SYSCTL 982#ifdef CONFIG_SYSCTL
1048 brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); 983 brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
1049 if (brnf_sysctl_header == NULL) { 984 if (brnf_sysctl_header == NULL) {
1050 printk(KERN_WARNING 985 printk(KERN_WARNING
1051 "br_netfilter: can't register to sysctl.\n"); 986 "br_netfilter: can't register to sysctl.\n");
1052 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 987 ret = -ENOMEM;
1053 dst_entries_destroy(&fake_dst_ops); 988 goto err1;
1054 return -ENOMEM;
1055 } 989 }
1056#endif 990#endif
1057 printk(KERN_NOTICE "Bridge firewalling registered\n"); 991 printk(KERN_NOTICE "Bridge firewalling registered\n");
1058 return 0; 992 return 0;
993err1:
994 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
995 return ret;
1059} 996}
1060 997
1061void br_netfilter_fini(void) 998static void __exit br_netfilter_fini(void)
1062{ 999{
1063 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1000 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1064#ifdef CONFIG_SYSCTL 1001#ifdef CONFIG_SYSCTL
1065 unregister_net_sysctl_table(brnf_sysctl_header); 1002 unregister_net_sysctl_table(brnf_sysctl_header);
1066#endif 1003#endif
1067 dst_entries_destroy(&fake_dst_ops);
1068} 1004}
1005
1006module_init(br_netfilter_init);
1007module_exit(br_netfilter_fini);
1008
1009MODULE_LICENSE("GPL");
1010MODULE_AUTHOR("Lennert Buytenhek <buytenh@gnu.org>");
1011MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
1012MODULE_DESCRIPTION("Linux ethernet netfilter firewall bridge");
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 90a91e137acc..0fa66b83685f 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -602,7 +602,7 @@ out_af:
602 return err; 602 return err;
603} 603}
604 604
605void __exit br_netlink_fini(void) 605void br_netlink_fini(void)
606{ 606{
607 br_mdb_uninit(); 607 br_mdb_uninit();
608 rtnl_af_unregister(&br_af_ops); 608 rtnl_af_unregister(&br_af_ops);
diff --git a/net/bridge/br_nf_core.c b/net/bridge/br_nf_core.c
new file mode 100644
index 000000000000..387cb3bd017c
--- /dev/null
+++ b/net/bridge/br_nf_core.c
@@ -0,0 +1,96 @@
1/*
2 * Handle firewalling core
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 * Bart De Schuymer <bdschuym@pandora.be>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 *
14 * Lennert dedicates this file to Kerstin Wurdinger.
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/in_route.h>
20#include <linux/inetdevice.h>
21#include <net/route.h>
22
23#include "br_private.h"
24#ifdef CONFIG_SYSCTL
25#include <linux/sysctl.h>
26#endif
27
28static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
29 struct sk_buff *skb, u32 mtu)
30{
31}
32
33static void fake_redirect(struct dst_entry *dst, struct sock *sk,
34 struct sk_buff *skb)
35{
36}
37
38static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
39{
40 return NULL;
41}
42
43static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
44 struct sk_buff *skb,
45 const void *daddr)
46{
47 return NULL;
48}
49
50static unsigned int fake_mtu(const struct dst_entry *dst)
51{
52 return dst->dev->mtu;
53}
54
55static struct dst_ops fake_dst_ops = {
56 .family = AF_INET,
57 .protocol = cpu_to_be16(ETH_P_IP),
58 .update_pmtu = fake_update_pmtu,
59 .redirect = fake_redirect,
60 .cow_metrics = fake_cow_metrics,
61 .neigh_lookup = fake_neigh_lookup,
62 .mtu = fake_mtu,
63};
64
65/*
66 * Initialize bogus route table used to keep netfilter happy.
67 * Currently, we fill in the PMTU entry because netfilter
68 * refragmentation needs it, and the rt_flags entry because
69 * ipt_REJECT needs it. Future netfilter modules might
70 * require us to fill additional fields.
71 */
72static const u32 br_dst_default_metrics[RTAX_MAX] = {
73 [RTAX_MTU - 1] = 1500,
74};
75
76void br_netfilter_rtable_init(struct net_bridge *br)
77{
78 struct rtable *rt = &br->fake_rtable;
79
80 atomic_set(&rt->dst.__refcnt, 1);
81 rt->dst.dev = br->dev;
82 rt->dst.path = &rt->dst;
83 dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
84 rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE;
85 rt->dst.ops = &fake_dst_ops;
86}
87
88int __init br_nf_core_init(void)
89{
90 return dst_entries_init(&fake_dst_ops);
91}
92
93void br_nf_core_fini(void)
94{
95 dst_entries_destroy(&fake_dst_ops);
96}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 62a7fa2e3569..d304d752c091 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -221,7 +221,7 @@ struct net_bridge
221 struct pcpu_sw_netstats __percpu *stats; 221 struct pcpu_sw_netstats __percpu *stats;
222 spinlock_t hash_lock; 222 spinlock_t hash_lock;
223 struct hlist_head hash[BR_HASH_SIZE]; 223 struct hlist_head hash[BR_HASH_SIZE];
224#ifdef CONFIG_BRIDGE_NETFILTER 224#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
225 struct rtable fake_rtable; 225 struct rtable fake_rtable;
226 bool nf_call_iptables; 226 bool nf_call_iptables;
227 bool nf_call_ip6tables; 227 bool nf_call_ip6tables;
@@ -751,13 +751,13 @@ static inline int br_vlan_enabled(struct net_bridge *br)
751#endif 751#endif
752 752
753/* br_netfilter.c */ 753/* br_netfilter.c */
754#ifdef CONFIG_BRIDGE_NETFILTER 754#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
755int br_netfilter_init(void); 755int br_nf_core_init(void);
756void br_netfilter_fini(void); 756void br_nf_core_fini(void);
757void br_netfilter_rtable_init(struct net_bridge *); 757void br_netfilter_rtable_init(struct net_bridge *);
758#else 758#else
759#define br_netfilter_init() (0) 759static inline int br_nf_core_init(void) { return 0; }
760#define br_netfilter_fini() do { } while (0) 760static inline void br_nf_core_fini(void) {}
761#define br_netfilter_rtable_init(x) 761#define br_netfilter_rtable_init(x)
762#endif 762#endif
763 763
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index c9e2572b15f4..cb431c6016ee 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -629,7 +629,7 @@ static ssize_t multicast_startup_query_interval_store(
629} 629}
630static DEVICE_ATTR_RW(multicast_startup_query_interval); 630static DEVICE_ATTR_RW(multicast_startup_query_interval);
631#endif 631#endif
632#ifdef CONFIG_BRIDGE_NETFILTER 632#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
633static ssize_t nf_call_iptables_show( 633static ssize_t nf_call_iptables_show(
634 struct device *d, struct device_attribute *attr, char *buf) 634 struct device *d, struct device_attribute *attr, char *buf)
635{ 635{
@@ -763,7 +763,7 @@ static struct attribute *bridge_attrs[] = {
763 &dev_attr_multicast_query_response_interval.attr, 763 &dev_attr_multicast_query_response_interval.attr,
764 &dev_attr_multicast_startup_query_interval.attr, 764 &dev_attr_multicast_startup_query_interval.attr,
765#endif 765#endif
766#ifdef CONFIG_BRIDGE_NETFILTER 766#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
767 &dev_attr_nf_call_iptables.attr, 767 &dev_attr_nf_call_iptables.attr,
768 &dev_attr_nf_call_ip6tables.attr, 768 &dev_attr_nf_call_ip6tables.attr,
769 &dev_attr_nf_call_arptables.attr, 769 &dev_attr_nf_call_arptables.attr,