aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-03-23 22:02:46 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-23 22:02:46 -0400
commit40451fd013878b005ccae767dfebc07dfecf85d9 (patch)
tree671c687b5b9c5f690fa8827c2c71c17d87b1fb0f /net/bridge
parent682f048bd49449f4ab978664a7f69a44a74e3caa (diff)
parente35158e40110270600698f19bda5e21d8ce709d7 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for net-next. Basically, more incremental updates for br_netfilter from Florian Westphal, small nf_tables updates (including one fix for rb-tree locking) and small two-liner to add extra validation for the REJECT6 target. More specifically, they are: 1) Use the conntrack status flags from br_netfilter to know that DNAT is happening. Patch for Florian Westphal. 2) nf_bridge->physoutdev == NULL already indicates that the traffic is bridged, so let's get rid of the BRNF_BRIDGED flag. Also from Florian. 3) Another patch to prepare voidization of seq_printf/seq_puts/seq_putc, from Joe Perches. 4) Consolidation of nf_tables_newtable() error path. 5) Kill nf_bridge_pad used by br_netfilter from ip_fragment(), from Florian Westphal. 6) Access rb-tree root node inside the lock and remove unnecessary locking from the get path (we already hold nfnl_lock there), from Patrick McHardy. 7) You cannot use a NFT_SET_ELEM_INTERVAL_END when the set doesn't support interval, also from Patrick. 8) Enforce IP6T_F_PROTO from ip6t_REJECT to make sure the core is actually restricting matches to TCP. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_netfilter.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index b260a97275db..f3884a1b942f 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -37,17 +37,16 @@
37#include <net/route.h> 37#include <net/route.h>
38#include <net/netfilter/br_netfilter.h> 38#include <net/netfilter/br_netfilter.h>
39 39
40#if IS_ENABLED(CONFIG_NF_CONNTRACK)
41#include <net/netfilter/nf_conntrack.h>
42#endif
43
40#include <asm/uaccess.h> 44#include <asm/uaccess.h>
41#include "br_private.h" 45#include "br_private.h"
42#ifdef CONFIG_SYSCTL 46#ifdef CONFIG_SYSCTL
43#include <linux/sysctl.h> 47#include <linux/sysctl.h>
44#endif 48#endif
45 49
46#define skb_origaddr(skb) (((struct bridge_skb_cb *) \
47 (skb->nf_bridge->data))->daddr.ipv4)
48#define store_orig_dstaddr(skb) (skb_origaddr(skb) = ip_hdr(skb)->daddr)
49#define dnat_took_place(skb) (skb_origaddr(skb) != ip_hdr(skb)->daddr)
50
51#ifdef CONFIG_SYSCTL 50#ifdef CONFIG_SYSCTL
52static struct ctl_table_header *brnf_sysctl_header; 51static struct ctl_table_header *brnf_sysctl_header;
53static int brnf_call_iptables __read_mostly = 1; 52static int brnf_call_iptables __read_mostly = 1;
@@ -154,6 +153,18 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
154 return nf_bridge; 153 return nf_bridge;
155} 154}
156 155
156static unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
157{
158 switch (skb->protocol) {
159 case __cpu_to_be16(ETH_P_8021Q):
160 return VLAN_HLEN;
161 case __cpu_to_be16(ETH_P_PPP_SES):
162 return PPPOE_SES_HLEN;
163 default:
164 return 0;
165 }
166}
167
157static inline void nf_bridge_push_encap_header(struct sk_buff *skb) 168static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
158{ 169{
159 unsigned int len = nf_bridge_encap_header_len(skb); 170 unsigned int len = nf_bridge_encap_header_len(skb);
@@ -322,6 +333,22 @@ free_skb:
322 return 0; 333 return 0;
323} 334}
324 335
336static bool dnat_took_place(const struct sk_buff *skb)
337{
338#if IS_ENABLED(CONFIG_NF_CONNTRACK)
339 enum ip_conntrack_info ctinfo;
340 struct nf_conn *ct;
341
342 ct = nf_ct_get(skb, &ctinfo);
343 if (!ct || nf_ct_is_untracked(ct))
344 return false;
345
346 return test_bit(IPS_DST_NAT_BIT, &ct->status);
347#else
348 return false;
349#endif
350}
351
325/* This requires some explaining. If DNAT has taken place, 352/* This requires some explaining. If DNAT has taken place,
326 * we will need to fix up the destination Ethernet address. 353 * we will need to fix up the destination Ethernet address.
327 * 354 *
@@ -625,7 +652,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
625 return NF_DROP; 652 return NF_DROP;
626 if (!setup_pre_routing(skb)) 653 if (!setup_pre_routing(skb))
627 return NF_DROP; 654 return NF_DROP;
628 store_orig_dstaddr(skb); 655
629 skb->protocol = htons(ETH_P_IP); 656 skb->protocol = htons(ETH_P_IP);
630 657
631 NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, 658 NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
@@ -721,8 +748,6 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
721 if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb)) 748 if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb))
722 return NF_DROP; 749 return NF_DROP;
723 750
724 /* The physdev module checks on this */
725 nf_bridge->mask |= BRNF_BRIDGED;
726 nf_bridge->physoutdev = skb->dev; 751 nf_bridge->physoutdev = skb->dev;
727 if (pf == NFPROTO_IPV4) 752 if (pf == NFPROTO_IPV4)
728 skb->protocol = htons(ETH_P_IP); 753 skb->protocol = htons(ETH_P_IP);
@@ -842,7 +867,12 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
842 struct net_device *realoutdev = bridge_parent(skb->dev); 867 struct net_device *realoutdev = bridge_parent(skb->dev);
843 u_int8_t pf; 868 u_int8_t pf;
844 869
845 if (!nf_bridge || !(nf_bridge->mask & BRNF_BRIDGED)) 870 /* if nf_bridge is set, but ->physoutdev is NULL, this packet came in
871 * on a bridge, but was delivered locally and is now being routed:
872 *
873 * POST_ROUTING was already invoked from the ip stack.
874 */
875 if (!nf_bridge || !nf_bridge->physoutdev)
846 return NF_ACCEPT; 876 return NF_ACCEPT;
847 877
848 if (!realoutdev) 878 if (!realoutdev)