diff options
| author | David S. Miller <davem@davemloft.net> | 2015-03-23 22:02:46 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-23 22:02:46 -0400 |
| commit | 40451fd013878b005ccae767dfebc07dfecf85d9 (patch) | |
| tree | 671c687b5b9c5f690fa8827c2c71c17d87b1fb0f /net/bridge | |
| parent | 682f048bd49449f4ab978664a7f69a44a74e3caa (diff) | |
| parent | e35158e40110270600698f19bda5e21d8ce709d7 (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.c | 48 |
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 |
| 52 | static struct ctl_table_header *brnf_sysctl_header; | 51 | static struct ctl_table_header *brnf_sysctl_header; |
| 53 | static int brnf_call_iptables __read_mostly = 1; | 52 | static 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 | ||
| 156 | static 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 | |||
| 157 | static inline void nf_bridge_push_encap_header(struct sk_buff *skb) | 168 | static 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 | ||
| 336 | static 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) |
