diff options
author | Alvaro Neira <alvaroneay@gmail.com> | 2014-11-26 10:21:36 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-11-27 12:58:05 +0100 |
commit | 68b0faa87d167ec87ba2a26be62241ad94eb449b (patch) | |
tree | 19467fee936ffdb3de713ce73ba48c38823288ca /net | |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/netfilter/nf_tables_bridge.c | 48 | ||||
-rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 52 |
2 files changed, 53 insertions, 47 deletions
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index 074c557ab50..d468c19faec 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c @@ -13,6 +13,54 @@ #include <linux/module.h> #include <linux/netfilter_bridge.h> #include <net/netfilter/nf_tables.h> +#include <net/netfilter/nf_tables_bridge.h> +#include <linux/ip.h> +#include <linux/ipv6.h> + +int nft_bridge_iphdr_validate(struct sk_buff *skb) +{ + struct iphdr *iph; + u32 len; + + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + return 0; + + iph = ip_hdr(skb); + if (iph->ihl < 5 || iph->version != 4) + return 0; + + len = ntohs(iph->tot_len); + if (skb->len < len) + return 0; + else if (len < (iph->ihl*4)) + return 0; + + if (!pskb_may_pull(skb, iph->ihl*4)) + return 0; + + return 1; +} +EXPORT_SYMBOL_GPL(nft_bridge_iphdr_validate); + +int nft_bridge_ip6hdr_validate(struct sk_buff *skb) +{ + struct ipv6hdr *hdr; + u32 pkt_len; + + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + return 0; + + hdr = ipv6_hdr(skb); + if (hdr->version != 6) + return 0; + + pkt_len = ntohs(hdr->payload_len); + if (pkt_len + sizeof(struct ipv6hdr) > skb->len) + return 0; + + return 1; +} +EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate); static unsigned int 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 48da2c54a69..b0330aecbf9 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c @@ -14,6 +14,7 @@ #include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h> #include <net/netfilter/nft_reject.h> +#include <net/netfilter/nf_tables_bridge.h> #include <net/netfilter/ipv4/nf_reject.h> #include <net/netfilter/ipv6/nf_reject.h> #include <linux/ip.h> @@ -35,30 +36,6 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, skb_pull(nskb, ETH_HLEN); } -static int nft_reject_iphdr_validate(struct sk_buff *oldskb) -{ - struct iphdr *iph; - u32 len; - - if (!pskb_may_pull(oldskb, sizeof(struct iphdr))) - return 0; - - iph = ip_hdr(oldskb); - if (iph->ihl < 5 || iph->version != 4) - return 0; - - len = ntohs(iph->tot_len); - if (oldskb->len < len) - return 0; - else if (len < (iph->ihl*4)) - return 0; - - if (!pskb_may_pull(oldskb, iph->ihl*4)) - return 0; - - return 1; -} - static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) { struct sk_buff *nskb; @@ -66,7 +43,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) const struct tcphdr *oth; struct tcphdr _oth; - if (!nft_reject_iphdr_validate(oldskb)) + if (!nft_bridge_iphdr_validate(oldskb)) return; 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, void *payload; __wsum csum; - if (!nft_reject_iphdr_validate(oldskb)) + if (!nft_bridge_iphdr_validate(oldskb)) return; /* IP header checks: fragment. */ @@ -146,25 +123,6 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, br_deliver(br_port_get_rcu(oldskb->dev), nskb); } -static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb) -{ - struct ipv6hdr *hdr; - u32 pkt_len; - - if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr))) - return 0; - - hdr = ipv6_hdr(oldskb); - if (hdr->version != 6) - return 0; - - pkt_len = ntohs(hdr->payload_len); - if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len) - return 0; - - return 1; -} - static void nft_reject_br_send_v6_tcp_reset(struct net *net, struct sk_buff *oldskb, int hook) { @@ -174,7 +132,7 @@ static void nft_reject_br_send_v6_tcp_reset(struct net *net, unsigned int otcplen; struct ipv6hdr *nip6h; - if (!nft_reject_ip6hdr_validate(oldskb)) + if (!nft_bridge_ip6hdr_validate(oldskb)) return; 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, unsigned int len; void *payload; - if (!nft_reject_ip6hdr_validate(oldskb)) + if (!nft_bridge_ip6hdr_validate(oldskb)) return; /* Include "As much of invoking packet as possible without the ICMPv6 |