* [PATCH nf 1/2 v2] bridge: export nft_reject_ip*hdr_validate functions
@ 2014-11-24 19:15 Alvaro Neira Ayuso
2014-11-24 19:15 ` [PATCH nf 2/2 v2] bridge: set the pktinfo for IPv4/IPv6 traffic Alvaro Neira Ayuso
0 siblings, 1 reply; 3+ messages in thread
From: Alvaro Neira Ayuso @ 2014-11-24 19:15 UTC (permalink / raw)
To: netfilter-devel
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 ethernet header is correct.
Signed-off-by: Alvaro Neira Ayuso <alvaroneay@gmail.com>
---
[no changes in v2]
include/net/netfilter/nf_tables_bridge.h | 7 ++++
net/bridge/netfilter/nf_tables_bridge.c | 48 +++++++++++++++++++++++++++
net/bridge/netfilter/nft_reject_bridge.c | 52 +++---------------------------
3 files changed, 60 insertions(+), 47 deletions(-)
create mode 100644 include/net/netfilter/nf_tables_bridge.h
diff --git a/include/net/netfilter/nf_tables_bridge.h b/include/net/netfilter/nf_tables_bridge.h
new file mode 100644
index 0000000..511fb79
--- /dev/null
+++ b/include/net/netfilter/nf_tables_bridge.h
@@ -0,0 +1,7 @@
+#ifndef _NET_NF_TABLES_BRIDGE_H
+#define _NET_NF_TABLES_BRIDGE_H
+
+int nft_bridge_iphdr_validate(struct sk_buff *skb);
+int nft_bridge_ip6hdr_validate(struct sk_buff *skb);
+
+#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 074c557..d468c19 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 48da2c5..b0330ae 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
--
1.7.10.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH nf 2/2 v2] bridge: set the pktinfo for IPv4/IPv6 traffic
2014-11-24 19:15 [PATCH nf 1/2 v2] bridge: export nft_reject_ip*hdr_validate functions Alvaro Neira Ayuso
@ 2014-11-24 19:15 ` Alvaro Neira Ayuso
2014-11-24 23:22 ` Pablo Neira Ayuso
0 siblings, 1 reply; 3+ messages in thread
From: Alvaro Neira Ayuso @ 2014-11-24 19:15 UTC (permalink / raw)
To: netfilter-devel
This patch sets the pktinfo for IPv4/IPv6 traffic. Therefore, we can check the
meta l4proto for IPv4/IPv6 traffic in bridge, before we don't have enough
information to do it. Example:
nft add rule bridge filter input ether type {ip, ip6} meta l4proto udp counter
and
nft add rule bridge filter input ether type {ip, ip6} meta l4proto tcp counter
With this patch, we can filter the traffic using the transport context that we
want.
Signed-off-by: Alvaro Neira Ayuso <alvaroneay@gmail.com>
---
[changes in v2]
* Refactor the code to make it more clear
* Make sure that IPv6 is enabled
net/bridge/netfilter/nf_tables_bridge.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index d468c19..f4471d7 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -16,6 +16,8 @@
#include <net/netfilter/nf_tables_bridge.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <net/netfilter/nf_tables_ipv4.h>
+#include <net/netfilter/nf_tables_ipv6.h>
int nft_bridge_iphdr_validate(struct sk_buff *skb)
{
@@ -71,7 +73,24 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops,
{
struct nft_pktinfo pkt;
- nft_set_pktinfo(&pkt, ops, skb, in, out);
+ switch (eth_hdr(skb)->h_proto) {
+ case htons(ETH_P_IP):
+ if (!nft_bridge_iphdr_validate(skb))
+ nft_set_pktinfo(&pkt, ops, skb, in, out);
+ else
+ nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+ break;
+ case htons(ETH_P_IPV6):
+ #if IS_ENABLED(CONFIG_IPV6)
+ if (!nft_bridge_ip6hdr_validate(skb) ||
+ nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
+ nft_set_pktinfo(&pkt, ops, skb, in, out);
+ break;
+ #endif
+ default:
+ nft_set_pktinfo(&pkt, ops, skb, in, out);
+ break;
+ }
return nft_do_chain(&pkt, ops);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH nf 2/2 v2] bridge: set the pktinfo for IPv4/IPv6 traffic
2014-11-24 19:15 ` [PATCH nf 2/2 v2] bridge: set the pktinfo for IPv4/IPv6 traffic Alvaro Neira Ayuso
@ 2014-11-24 23:22 ` Pablo Neira Ayuso
0 siblings, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2014-11-24 23:22 UTC (permalink / raw)
To: Alvaro Neira Ayuso; +Cc: netfilter-devel
On Mon, Nov 24, 2014 at 08:15:50PM +0100, Alvaro Neira Ayuso wrote:
> This patch sets the pktinfo for IPv4/IPv6 traffic. Therefore, we can check the
> meta l4proto for IPv4/IPv6 traffic in bridge, before we don't have enough
> information to do it. Example:
I suggest:
"This patch adds the missing bits to allow to match per meta l4proto
from the bridge. Example:"
> nft add rule bridge filter input ether type {ip, ip6} meta l4proto udp counter
> and
> nft add rule bridge filter input ether type {ip, ip6} meta l4proto tcp counter
One example is enough. These two look too similar.
> With this patch, we can filter the traffic using the transport context that we
> want.
>
> Signed-off-by: Alvaro Neira Ayuso <alvaroneay@gmail.com>
> ---
> [changes in v2]
> * Refactor the code to make it more clear
> * Make sure that IPv6 is enabled
>
> net/bridge/netfilter/nf_tables_bridge.c | 21 ++++++++++++++++++++-
> 1 file changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
> index d468c19..f4471d7 100644
> --- a/net/bridge/netfilter/nf_tables_bridge.c
> +++ b/net/bridge/netfilter/nf_tables_bridge.c
> @@ -16,6 +16,8 @@
> #include <net/netfilter/nf_tables_bridge.h>
> #include <linux/ip.h>
> #include <linux/ipv6.h>
> +#include <net/netfilter/nf_tables_ipv4.h>
> +#include <net/netfilter/nf_tables_ipv6.h>
>
> int nft_bridge_iphdr_validate(struct sk_buff *skb)
> {
> @@ -71,7 +73,24 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops,
> {
> struct nft_pktinfo pkt;
>
> - nft_set_pktinfo(&pkt, ops, skb, in, out);
> + switch (eth_hdr(skb)->h_proto) {
> + case htons(ETH_P_IP):
> + if (!nft_bridge_iphdr_validate(skb))
> + nft_set_pktinfo(&pkt, ops, skb, in, out);
> + else
> + nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
> + break;
> + case htons(ETH_P_IPV6):
> + #if IS_ENABLED(CONFIG_IPV6)
Never indent #if's and #endif.
In case of doubt, just check around to see how this is done in other
code, so you don't need to figure out how to make it.
Thanks.
> + if (!nft_bridge_ip6hdr_validate(skb) ||
> + nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
> + nft_set_pktinfo(&pkt, ops, skb, in, out);
> + break;
> + #endif
> + default:
> + nft_set_pktinfo(&pkt, ops, skb, in, out);
> + break;
> + }
>
> return nft_do_chain(&pkt, ops);
> }
> --
> 1.7.10.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-11-24 23:20 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-24 19:15 [PATCH nf 1/2 v2] bridge: export nft_reject_ip*hdr_validate functions Alvaro Neira Ayuso
2014-11-24 19:15 ` [PATCH nf 2/2 v2] bridge: set the pktinfo for IPv4/IPv6 traffic Alvaro Neira Ayuso
2014-11-24 23:22 ` Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).