aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-12-05 23:56:46 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-05 23:56:46 -0500
commit244ebd9f8fa8beb7b37bdeebd6c5308b61f98aef (patch)
tree8b0a72056747f0bb9232fdafb480b0501dc83734 /net/bridge
parentddd5c50f9bec7ffab5d28c5dd244db8a4c3f27e7 (diff)
parentcac3763967362ace7996532ad3933f493a928a1b (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 batch contains netfilter updates for net-next. Basically, enhancements for xt_recent, skip zeroing of timer in conntrack, fix linking problem with recent redirect support for nf_tables, ipset updates and a couple of cleanups. More specifically, they are: 1) Rise maximum number per IP address to be remembered in xt_recent while retaining backward compatibility, from Florian Westphal. 2) Skip zeroing timer area in nf_conn objects, also from Florian. 3) Inspect IPv4 and IPv6 traffic from the bridge to allow filtering using using meta l4proto and transport layer header, from Alvaro Neira. 4) Fix linking problems in the new redirect support when CONFIG_IPV6=n and IP6_NF_IPTABLES=n. And ipset updates from Jozsef Kadlecsik: 5) Support updating element extensions when the set is full (fixes netfilter bugzilla id 880). 6) Fix set match with 32-bits userspace / 64-bits kernel. 7) Indicate explicitly when /0 networks are supported in ipset. 8) Simplify cidr handling for hash:*net* types. 9) Allocate the proper size of memory when /0 networks are supported. 10) Explicitly add padding elements to hash:net,net and hash:net,port, because the elements must be u32 sized for the used hash function. Jozsef is also cooking ipset RCU conversion which should land soon if they reach the merge window in time. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c88
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c52
2 files changed, 92 insertions, 48 deletions
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index 074c557ab505..19473a9371b8 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -13,6 +13,82 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/netfilter_bridge.h> 14#include <linux/netfilter_bridge.h>
15#include <net/netfilter/nf_tables.h> 15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nf_tables_bridge.h>
17#include <linux/ip.h>
18#include <linux/ipv6.h>
19#include <net/netfilter/nf_tables_ipv4.h>
20#include <net/netfilter/nf_tables_ipv6.h>
21
22int nft_bridge_iphdr_validate(struct sk_buff *skb)
23{
24 struct iphdr *iph;
25 u32 len;
26
27 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
28 return 0;
29
30 iph = ip_hdr(skb);
31 if (iph->ihl < 5 || iph->version != 4)
32 return 0;
33
34 len = ntohs(iph->tot_len);
35 if (skb->len < len)
36 return 0;
37 else if (len < (iph->ihl*4))
38 return 0;
39
40 if (!pskb_may_pull(skb, iph->ihl*4))
41 return 0;
42
43 return 1;
44}
45EXPORT_SYMBOL_GPL(nft_bridge_iphdr_validate);
46
47int nft_bridge_ip6hdr_validate(struct sk_buff *skb)
48{
49 struct ipv6hdr *hdr;
50 u32 pkt_len;
51
52 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
53 return 0;
54
55 hdr = ipv6_hdr(skb);
56 if (hdr->version != 6)
57 return 0;
58
59 pkt_len = ntohs(hdr->payload_len);
60 if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
61 return 0;
62
63 return 1;
64}
65EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate);
66
67static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
68 const struct nf_hook_ops *ops,
69 struct sk_buff *skb,
70 const struct net_device *in,
71 const struct net_device *out)
72{
73 if (nft_bridge_iphdr_validate(skb))
74 nft_set_pktinfo_ipv4(pkt, ops, skb, in, out);
75 else
76 nft_set_pktinfo(pkt, ops, skb, in, out);
77}
78
79static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
80 const struct nf_hook_ops *ops,
81 struct sk_buff *skb,
82 const struct net_device *in,
83 const struct net_device *out)
84{
85#if IS_ENABLED(CONFIG_IPV6)
86 if (nft_bridge_ip6hdr_validate(skb) &&
87 nft_set_pktinfo_ipv6(pkt, ops, skb, in, out) == 0)
88 return;
89#endif
90 nft_set_pktinfo(pkt, ops, skb, in, out);
91}
16 92
17static unsigned int 93static unsigned int
18nft_do_chain_bridge(const struct nf_hook_ops *ops, 94nft_do_chain_bridge(const struct nf_hook_ops *ops,
@@ -23,7 +99,17 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops,
23{ 99{
24 struct nft_pktinfo pkt; 100 struct nft_pktinfo pkt;
25 101
26 nft_set_pktinfo(&pkt, ops, skb, in, out); 102 switch (eth_hdr(skb)->h_proto) {
103 case htons(ETH_P_IP):
104 nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
105 break;
106 case htons(ETH_P_IPV6):
107 nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
108 break;
109 default:
110 nft_set_pktinfo(&pkt, ops, skb, in, out);
111 break;
112 }
27 113
28 return nft_do_chain(&pkt, ops); 114 return nft_do_chain(&pkt, ops);
29} 115}
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index 48da2c54a69e..b0330aecbf97 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -14,6 +14,7 @@
14#include <linux/netfilter/nf_tables.h> 14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h> 15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nft_reject.h> 16#include <net/netfilter/nft_reject.h>
17#include <net/netfilter/nf_tables_bridge.h>
17#include <net/netfilter/ipv4/nf_reject.h> 18#include <net/netfilter/ipv4/nf_reject.h>
18#include <net/netfilter/ipv6/nf_reject.h> 19#include <net/netfilter/ipv6/nf_reject.h>
19#include <linux/ip.h> 20#include <linux/ip.h>
@@ -35,30 +36,6 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb,
35 skb_pull(nskb, ETH_HLEN); 36 skb_pull(nskb, ETH_HLEN);
36} 37}
37 38
38static int nft_reject_iphdr_validate(struct sk_buff *oldskb)
39{
40 struct iphdr *iph;
41 u32 len;
42
43 if (!pskb_may_pull(oldskb, sizeof(struct iphdr)))
44 return 0;
45
46 iph = ip_hdr(oldskb);
47 if (iph->ihl < 5 || iph->version != 4)
48 return 0;
49
50 len = ntohs(iph->tot_len);
51 if (oldskb->len < len)
52 return 0;
53 else if (len < (iph->ihl*4))
54 return 0;
55
56 if (!pskb_may_pull(oldskb, iph->ihl*4))
57 return 0;
58
59 return 1;
60}
61
62static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) 39static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook)
63{ 40{
64 struct sk_buff *nskb; 41 struct sk_buff *nskb;
@@ -66,7 +43,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook)
66 const struct tcphdr *oth; 43 const struct tcphdr *oth;
67 struct tcphdr _oth; 44 struct tcphdr _oth;
68 45
69 if (!nft_reject_iphdr_validate(oldskb)) 46 if (!nft_bridge_iphdr_validate(oldskb))
70 return; 47 return;
71 48
72 oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook); 49 oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook);
@@ -101,7 +78,7 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook,
101 void *payload; 78 void *payload;
102 __wsum csum; 79 __wsum csum;
103 80
104 if (!nft_reject_iphdr_validate(oldskb)) 81 if (!nft_bridge_iphdr_validate(oldskb))
105 return; 82 return;
106 83
107 /* IP header checks: fragment. */ 84 /* IP header checks: fragment. */
@@ -146,25 +123,6 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook,
146 br_deliver(br_port_get_rcu(oldskb->dev), nskb); 123 br_deliver(br_port_get_rcu(oldskb->dev), nskb);
147} 124}
148 125
149static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb)
150{
151 struct ipv6hdr *hdr;
152 u32 pkt_len;
153
154 if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr)))
155 return 0;
156
157 hdr = ipv6_hdr(oldskb);
158 if (hdr->version != 6)
159 return 0;
160
161 pkt_len = ntohs(hdr->payload_len);
162 if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len)
163 return 0;
164
165 return 1;
166}
167
168static void nft_reject_br_send_v6_tcp_reset(struct net *net, 126static void nft_reject_br_send_v6_tcp_reset(struct net *net,
169 struct sk_buff *oldskb, int hook) 127 struct sk_buff *oldskb, int hook)
170{ 128{
@@ -174,7 +132,7 @@ static void nft_reject_br_send_v6_tcp_reset(struct net *net,
174 unsigned int otcplen; 132 unsigned int otcplen;
175 struct ipv6hdr *nip6h; 133 struct ipv6hdr *nip6h;
176 134
177 if (!nft_reject_ip6hdr_validate(oldskb)) 135 if (!nft_bridge_ip6hdr_validate(oldskb))
178 return; 136 return;
179 137
180 oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook); 138 oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook);
@@ -207,7 +165,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net,
207 unsigned int len; 165 unsigned int len;
208 void *payload; 166 void *payload;
209 167
210 if (!nft_reject_ip6hdr_validate(oldskb)) 168 if (!nft_bridge_ip6hdr_validate(oldskb))
211 return; 169 return;
212 170
213 /* Include "As much of invoking packet as possible without the ICMPv6 171 /* Include "As much of invoking packet as possible without the ICMPv6