diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-03-10 05:27:18 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-03-10 10:03:02 -0400 |
commit | 1a4ba64d16a42c1b31d52b671accd7f9103e2626 (patch) | |
tree | f1f61462f14d2017965dae56d82cd05d947cc854 /net | |
parent | a03a8dbe20eff6d57aae3147577bf84b52aba4e6 (diff) |
netfilter: bridge: use rcu hook to resolve br_netfilter dependency
e5de75b ("netfilter: bridge: move DNAT helper to br_netfilter") results
in the following link problem:
net/bridge/br_device.c:29: undefined reference to `br_nf_prerouting_finish_bridge`
Moreover it creates a hard dependency between br_netfilter and the
bridge core, which is what we've been trying to avoid so far.
Resolve this problem by using a hook structure so we reduce #ifdef
pollution and keep bridge netfilter specific code under br_netfilter.c
which was the original intention.
Reported-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_device.c | 7 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 9 | ||||
-rw-r--r-- | net/bridge/br_private.h | 10 |
3 files changed, 18 insertions, 8 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 294cbcc49263..4ff77a16956c 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \ | 25 | #define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \ |
26 | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM) | 26 | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM) |
27 | 27 | ||
28 | const struct nf_br_ops __rcu *nf_br_ops __read_mostly; | ||
29 | EXPORT_SYMBOL_GPL(nf_br_ops); | ||
30 | |||
28 | /* net device transmit always called with BH disabled */ | 31 | /* net device transmit always called with BH disabled */ |
29 | netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | 32 | netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) |
30 | { | 33 | { |
@@ -33,10 +36,12 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
33 | struct net_bridge_fdb_entry *dst; | 36 | struct net_bridge_fdb_entry *dst; |
34 | struct net_bridge_mdb_entry *mdst; | 37 | struct net_bridge_mdb_entry *mdst; |
35 | struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats); | 38 | struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats); |
39 | const struct nf_br_ops *nf_ops; | ||
36 | u16 vid = 0; | 40 | u16 vid = 0; |
37 | 41 | ||
38 | rcu_read_lock(); | 42 | rcu_read_lock(); |
39 | if (br_nf_prerouting_finish_bridge(skb)) { | 43 | nf_ops = rcu_dereference(nf_br_ops); |
44 | if (nf_ops && nf_ops->br_dev_xmit_hook(skb)) { | ||
40 | rcu_read_unlock(); | 45 | rcu_read_unlock(); |
41 | return NETDEV_TX_OK; | 46 | return NETDEV_TX_OK; |
42 | } | 47 | } |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index a8361c7cdf81..b260a97275db 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -914,7 +914,7 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) | |||
914 | br_handle_frame_finish(skb); | 914 | br_handle_frame_finish(skb); |
915 | } | 915 | } |
916 | 916 | ||
917 | int br_nf_prerouting_finish_bridge(struct sk_buff *skb) | 917 | static int br_nf_dev_xmit(struct sk_buff *skb) |
918 | { | 918 | { |
919 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | 919 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { |
920 | br_nf_pre_routing_finish_bridge_slow(skb); | 920 | br_nf_pre_routing_finish_bridge_slow(skb); |
@@ -922,7 +922,10 @@ int br_nf_prerouting_finish_bridge(struct sk_buff *skb) | |||
922 | } | 922 | } |
923 | return 0; | 923 | return 0; |
924 | } | 924 | } |
925 | EXPORT_SYMBOL_GPL(br_nf_prerouting_finish_bridge); | 925 | |
926 | static const struct nf_br_ops br_ops = { | ||
927 | .br_dev_xmit_hook = br_nf_dev_xmit, | ||
928 | }; | ||
926 | 929 | ||
927 | void br_netfilter_enable(void) | 930 | void br_netfilter_enable(void) |
928 | { | 931 | { |
@@ -1061,12 +1064,14 @@ static int __init br_netfilter_init(void) | |||
1061 | return -ENOMEM; | 1064 | return -ENOMEM; |
1062 | } | 1065 | } |
1063 | #endif | 1066 | #endif |
1067 | RCU_INIT_POINTER(nf_br_ops, &br_ops); | ||
1064 | printk(KERN_NOTICE "Bridge firewalling registered\n"); | 1068 | printk(KERN_NOTICE "Bridge firewalling registered\n"); |
1065 | return 0; | 1069 | return 0; |
1066 | } | 1070 | } |
1067 | 1071 | ||
1068 | static void __exit br_netfilter_fini(void) | 1072 | static void __exit br_netfilter_fini(void) |
1069 | { | 1073 | { |
1074 | RCU_INIT_POINTER(nf_br_ops, NULL); | ||
1070 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); | 1075 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); |
1071 | #ifdef CONFIG_SYSCTL | 1076 | #ifdef CONFIG_SYSCTL |
1072 | unregister_net_sysctl_table(brnf_sysctl_header); | 1077 | unregister_net_sysctl_table(brnf_sysctl_header); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f0a0438dbd6d..b46fa0c5b8ec 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -763,17 +763,17 @@ static inline int br_vlan_enabled(struct net_bridge *br) | |||
763 | } | 763 | } |
764 | #endif | 764 | #endif |
765 | 765 | ||
766 | struct nf_br_ops { | ||
767 | int (*br_dev_xmit_hook)(struct sk_buff *skb); | ||
768 | }; | ||
769 | extern const struct nf_br_ops __rcu *nf_br_ops; | ||
770 | |||
766 | /* br_netfilter.c */ | 771 | /* br_netfilter.c */ |
767 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | 772 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
768 | int br_nf_prerouting_finish_bridge(struct sk_buff *skb); | ||
769 | int br_nf_core_init(void); | 773 | int br_nf_core_init(void); |
770 | void br_nf_core_fini(void); | 774 | void br_nf_core_fini(void); |
771 | void br_netfilter_rtable_init(struct net_bridge *); | 775 | void br_netfilter_rtable_init(struct net_bridge *); |
772 | #else | 776 | #else |
773 | static inline int br_nf_prerouting_finish_bridge(struct sk_buff *skb) | ||
774 | { | ||
775 | return 0; | ||
776 | } | ||
777 | static inline int br_nf_core_init(void) { return 0; } | 777 | static inline int br_nf_core_init(void) { return 0; } |
778 | static inline void br_nf_core_fini(void) {} | 778 | static inline void br_nf_core_fini(void) {} |
779 | #define br_netfilter_rtable_init(x) | 779 | #define br_netfilter_rtable_init(x) |