aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlvaro Neira <alvaroneay@gmail.com>2014-11-26 04:21:36 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2014-11-27 06:58:05 -0500
commit68b0faa87d167ec87ba2a26be62241ad94eb449b (patch)
tree19467fee936ffdb3de713ce73ba48c38823288ca
parentc41884ce0562841b98fa9790c9209c9073121a15 (diff)
netfilter: nf_tables_bridge: export nft_reject_ip*hdr_validate functions
This patch exports the functions nft_reject_iphdr_validate and nft_reject_ip6hdr_validate to use it in follow up patches. These functions check if the IPv4/IPv6 header is correct. Signed-off-by: Alvaro Neira Ayuso <alvaroneay@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/net/netfilter/nf_tables_bridge.h7
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c48
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c52
3 files changed, 60 insertions, 47 deletions
diff --git a/include/net/netfilter/nf_tables_bridge.h b/include/net/netfilter/nf_tables_bridge.h
new file mode 100644
index 000000000000..511fb79f6dad
--- /dev/null
+++ b/include/net/netfilter/nf_tables_bridge.h
@@ -0,0 +1,7 @@
1#ifndef _NET_NF_TABLES_BRIDGE_H
2#define _NET_NF_TABLES_BRIDGE_H
3
4int nft_bridge_iphdr_validate(struct sk_buff *skb);
5int nft_bridge_ip6hdr_validate(struct sk_buff *skb);
6
7#endif /* _NET_NF_TABLES_BRIDGE_H */
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index 074c557ab505..d468c19faecd 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -13,6 +13,54 @@
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
20int nft_bridge_iphdr_validate(struct sk_buff *skb)
21{
22 struct iphdr *iph;
23 u32 len;
24
25 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
26 return 0;
27
28 iph = ip_hdr(skb);
29 if (iph->ihl < 5 || iph->version != 4)
30 return 0;
31
32 len = ntohs(iph->tot_len);
33 if (skb->len < len)
34 return 0;
35 else if (len < (iph->ihl*4))
36 return 0;
37
38 if (!pskb_may_pull(skb, iph->ihl*4))
39 return 0;
40
41 return 1;
42}
43EXPORT_SYMBOL_GPL(nft_bridge_iphdr_validate);
44
45int nft_bridge_ip6hdr_validate(struct sk_buff *skb)
46{
47 struct ipv6hdr *hdr;
48 u32 pkt_len;
49
50 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
51 return 0;
52
53 hdr = ipv6_hdr(skb);
54 if (hdr->version != 6)
55 return 0;
56
57 pkt_len = ntohs(hdr->payload_len);
58 if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
59 return 0;
60
61 return 1;
62}
63EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate);
16 64
17static unsigned int 65static unsigned int
18nft_do_chain_bridge(const struct nf_hook_ops *ops, 66nft_do_chain_bridge(const struct nf_hook_ops *ops,
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