diff options
author | Alvaro Neira <alvaroneay@gmail.com> | 2014-11-26 04:21:36 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-11-27 06:58:05 -0500 |
commit | 68b0faa87d167ec87ba2a26be62241ad94eb449b (patch) | |
tree | 19467fee936ffdb3de713ce73ba48c38823288ca | |
parent | c41884ce0562841b98fa9790c9209c9073121a15 (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.h | 7 | ||||
-rw-r--r-- | net/bridge/netfilter/nf_tables_bridge.c | 48 | ||||
-rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 52 |
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 | |||
4 | int nft_bridge_iphdr_validate(struct sk_buff *skb); | ||
5 | int 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 | |||
20 | int 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 | } | ||
43 | EXPORT_SYMBOL_GPL(nft_bridge_iphdr_validate); | ||
44 | |||
45 | int 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 | } | ||
63 | EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate); | ||
16 | 64 | ||
17 | static unsigned int | 65 | static unsigned int |
18 | nft_do_chain_bridge(const struct nf_hook_ops *ops, | 66 | nft_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 | ||
38 | static 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 | |||
62 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | 39 | static 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 | ||
149 | static 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 | |||
168 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, | 126 | static 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 |