* [PATCH 1/1] netfilter: Added vlan matching extension
@ 2015-05-25 20:37 Eddie Linder
2015-05-25 21:51 ` Florian Westphal
0 siblings, 1 reply; 5+ messages in thread
From: Eddie Linder @ 2015-05-25 20:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: Eddie Linder
Signed-off-by: Eddie Linder <eddi@guardicore.com>
---
include/uapi/linux/netfilter/Kbuild | 1 +
include/uapi/linux/netfilter/xt_vlan.h | 11 ++++
net/netfilter/Makefile | 1 +
net/netfilter/xt_vlan.c | 91 ++++++++++++++++++++++++++++++++++
4 files changed, 104 insertions(+)
create mode 100644 include/uapi/linux/netfilter/xt_vlan.h
create mode 100644 net/netfilter/xt_vlan.c
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
index 1d973d2..2ca36db 100644
--- a/include/uapi/linux/netfilter/Kbuild
+++ b/include/uapi/linux/netfilter/Kbuild
@@ -85,3 +85,4 @@ header-y += xt_tcpmss.h
header-y += xt_tcpudp.h
header-y += xt_time.h
header-y += xt_u32.h
+header-y += xt_vlan.h
diff --git a/include/uapi/linux/netfilter/xt_vlan.h b/include/uapi/linux/netfilter/xt_vlan.h
new file mode 100644
index 0000000..3c31b6b
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_vlan.h
@@ -0,0 +1,11 @@
+#ifndef _XT_VLAN_H
+#define _XT_VLAN_H
+
+
+struct xt_vlan_info {
+ unsigned short vlan_id;
+ unsigned char vlan_pcp;
+ unsigned char invert;
+};
+#endif /*_XT_VLAN_H */
+
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a87d8b8..37ecfb0 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -169,6 +169,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_VLAN) += xt_vlan.o
# ipset
obj-$(CONFIG_IP_SET) += ipset/
diff --git a/net/netfilter/xt_vlan.c b/net/netfilter/xt_vlan.c
new file mode 100644
index 0000000..c583d48
--- /dev/null
+++ b/net/netfilter/xt_vlan.c
@@ -0,0 +1,91 @@
+/* Kernel module to match VLAN tag parameters.
+ * (C) 2015 Eddie Linder <eddi@guardicore.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/xt_vlan.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eddie Linder <eddi@guardicore.com>");
+MODULE_DESCRIPTION("Xtables: VLAN tag match");
+MODULE_ALIAS("ipt_vlan");
+MODULE_ALIAS("ip6t_vlan");
+MODULE_ALIAS("ipt_VLAN");
+MODULE_ALIAS("ip6t_VLAN");
+
+static bool parse_vlan(const struct sk_buff *skb, u16 *vlan_tci)
+{
+ struct vlan_hdr *vhdr;
+
+ if (skb->data - VLAN_HLEN < skb->head)
+ return false;
+ vhdr = (struct vlan_hdr *)(skb->data - VLAN_HLEN);
+ *vlan_tci = ntohs(vhdr->h_vlan_TCI);
+ return true;
+}
+
+static bool vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+ const struct xt_vlan_info *info = par->matchinfo;
+ u16 vlan_tci = ~VLAN_TAG_PRESENT;
+ bool ret;
+
+ if (skb->vlan_tci & VLAN_TAG_PRESENT)
+ /* Strip the 4096 bit (invalid vlan) from the vlan tci bits */
+ vlan_tci = skb->vlan_tci;
+ else {
+ if (unlikely(skb->len < VLAN_ETH_HLEN &&
+ skb->protocol == htons(ETH_P_8021Q)))
+ if (unlikely(!parse_vlan(skb, &vlan_tci)))
+ return false;
+ else
+ return false;
+ }
+
+ if ((vlan_tci & VLAN_VID_MASK) == info->vlan_id)
+ ret = true;
+
+ ret ^= info->invert;
+
+ if (ret && info->vlan_pcp) {
+ unsigned char vlan_pcp =
+ (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+
+ ret &= (vlan_pcp == info->vlan_pcp);
+ }
+
+ return ret;
+}
+
+static struct xt_match vlan_mt_reg __read_mostly = {
+ .name = "vlan",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = vlan_mt,
+ .matchsize = sizeof(struct xt_vlan_info),
+ .me = THIS_MODULE,
+};
+
+static int __init vlan_mt_init(void)
+{
+ return xt_register_match(&vlan_mt_reg);
+}
+
+static void __exit vlan_mt_exit(void)
+{
+ xt_unregister_match(&vlan_mt_reg);
+}
+
+module_init(vlan_mt_init);
+module_exit(vlan_mt_exit);
+
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/1] netfilter: Added vlan matching extension
2015-05-25 20:37 [PATCH 1/1] netfilter: Added vlan matching extension Eddie Linder
@ 2015-05-25 21:51 ` Florian Westphal
2015-05-26 14:24 ` Eddi Linder
0 siblings, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2015-05-25 21:51 UTC (permalink / raw)
To: Eddie Linder; +Cc: netfilter-devel
Eddie Linder <eddi@guardicore.com> wrote:
> Signed-off-by: Eddie Linder <eddi@guardicore.com>
Why do we need a vlan tag match in iptables?
For bridged traffic we have ebtables' net/bridge/netfilter/ebt_vlan.c .
And for routed traffic you'd just use -i vlan.id.0 or whatever?
What is this match being used for, and more importantly where/how?
(Is this for call-iptables=1 invocation from bridge netfilter?)
Nevertheless, a couple of comments below.
> diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
> index 1d973d2..2ca36db 100644
> --- a/include/uapi/linux/netfilter/Kbuild
> +++ b/include/uapi/linux/netfilter/Kbuild
> @@ -85,3 +85,4 @@ header-y += xt_tcpmss.h
> header-y += xt_tcpudp.h
> header-y += xt_time.h
> header-y += xt_u32.h
> +header-y += xt_vlan.h
> diff --git a/include/uapi/linux/netfilter/xt_vlan.h b/include/uapi/linux/netfilter/xt_vlan.h
> new file mode 100644
> index 0000000..3c31b6b
> --- /dev/null
> +++ b/include/uapi/linux/netfilter/xt_vlan.h
> @@ -0,0 +1,11 @@
> +#ifndef _XT_VLAN_H
> +#define _XT_VLAN_H
> +
> +
> +struct xt_vlan_info {
> + unsigned short vlan_id;
> + unsigned char vlan_pcp;
Please consider using explicit types for all of these, i.e.
__u16 vlan_id;
__u8 vlan_pcp;
> +MODULE_ALIAS("ipt_vlan");
> +MODULE_ALIAS("ip6t_vlan");
> +MODULE_ALIAS("ipt_VLAN");
> +MODULE_ALIAS("ip6t_VLAN");
_VLAN aliases are only needed for -j VLAN target, which isn't
added here, please remove them.
> +static bool vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
> +{
> + const struct xt_vlan_info *info = par->matchinfo;
> + u16 vlan_tci = ~VLAN_TAG_PRESENT;
> + bool ret;
> +
> + if (skb->vlan_tci & VLAN_TAG_PRESENT)
> + /* Strip the 4096 bit (invalid vlan) from the vlan tci bits */
> + vlan_tci = skb->vlan_tci;
if (skb_vlan_tag_present(skb))
vlan_tci = skb_vlan_tag_get(skb);
> + else {
> + if (unlikely(skb->len < VLAN_ETH_HLEN &&
This is weird. Why test len < VLAN_ETH_HLEN (> ? >= ? )
> + skb->protocol == htons(ETH_P_8021Q)))
> + if (unlikely(!parse_vlan(skb, &vlan_tci)))
> + return false;
> + else
> + return false;
> + }
Why call parse_vlan? We always return false without looking at
vlan_tci...
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/1] netfilter: Added vlan matching extension
@ 2015-05-26 9:13 Eddie Linder
0 siblings, 0 replies; 5+ messages in thread
From: Eddie Linder @ 2015-05-26 9:13 UTC (permalink / raw)
To: netfilter-devel; +Cc: Eddie Linder
Signed-off-by: Eddie Linder <eddi@guardicore.com>
---
include/uapi/linux/netfilter/Kbuild | 1 +
include/uapi/linux/netfilter/xt_vlan.h | 10 ++++
net/netfilter/Makefile | 1 +
net/netfilter/xt_vlan.c | 88 ++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+)
create mode 100644 include/uapi/linux/netfilter/xt_vlan.h
create mode 100644 net/netfilter/xt_vlan.c
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
index 1d973d2..2ca36db 100644
--- a/include/uapi/linux/netfilter/Kbuild
+++ b/include/uapi/linux/netfilter/Kbuild
@@ -85,3 +85,4 @@ header-y += xt_tcpmss.h
header-y += xt_tcpudp.h
header-y += xt_time.h
header-y += xt_u32.h
+header-y += xt_vlan.h
diff --git a/include/uapi/linux/netfilter/xt_vlan.h b/include/uapi/linux/netfilter/xt_vlan.h
new file mode 100644
index 0000000..71e8089
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_vlan.h
@@ -0,0 +1,10 @@
+#ifndef _XT_VLAN_H
+#define _XT_VLAN_H
+
+
+struct xt_vlan_info {
+ __u16 vlan_id;
+ __u8 vlan_pcp;
+ __u8 invert;
+};
+#endif /*_XT_VLAN_H */
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a87d8b8..37ecfb0 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -169,6 +169,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_VLAN) += xt_vlan.o
# ipset
obj-$(CONFIG_IP_SET) += ipset/
diff --git a/net/netfilter/xt_vlan.c b/net/netfilter/xt_vlan.c
new file mode 100644
index 0000000..1441eed
--- /dev/null
+++ b/net/netfilter/xt_vlan.c
@@ -0,0 +1,88 @@
+/* Kernel module to match VLAN tag parameters.
+ * (C) 2015 Eddie Linder <eddi@guardicore.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter/xt_vlan.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eddie Linder <eddi@guardicore.com>");
+MODULE_DESCRIPTION("Xtables: VLAN tag match");
+MODULE_ALIAS("ipt_vlan");
+MODULE_ALIAS("ip6t_vlan");
+
+static bool parse_vlan(const struct sk_buff *skb, u16 *vlan_tci)
+{
+ struct vlan_hdr *vhdr;
+
+ if (skb->data - VLAN_HLEN < skb->head)
+ return false;
+ vhdr = (struct vlan_hdr *)(skb->data - VLAN_HLEN);
+ *vlan_tci = ntohs(vhdr->h_vlan_TCI);
+ return true;
+}
+
+static bool vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+ const struct xt_vlan_info *info = par->matchinfo;
+ u16 vlan_tci = ~VLAN_TAG_PRESENT;
+ bool ret;
+
+ if (skb_vlan_tag_present(skb)) {
+ vlan_tci = skb_vlan_tag_get(skb);
+ } else {
+ if (unlikely(skb->len < VLAN_ETH_HLEN))
+ return false;
+ if (skb->protocol != htons(ETH_P_8021Q))
+ return false;
+ if (unlikely(!parse_vlan(skb, &vlan_tci)))
+ return false;
+ }
+
+ if ((vlan_tci & VLAN_VID_MASK) == info->vlan_id)
+ ret = true;
+
+ ret ^= info->invert;
+
+ if (ret && info->vlan_pcp) {
+ unsigned char vlan_pcp =
+ (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+
+ ret &= (vlan_pcp == info->vlan_pcp);
+ }
+
+ return ret;
+}
+
+static struct xt_match vlan_mt_reg __read_mostly = {
+ .name = "vlan",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .match = vlan_mt,
+ .matchsize = sizeof(struct xt_vlan_info),
+ .me = THIS_MODULE,
+};
+
+static int __init vlan_mt_init(void)
+{
+ return xt_register_match(&vlan_mt_reg);
+}
+
+static void __exit vlan_mt_exit(void)
+{
+ xt_unregister_match(&vlan_mt_reg);
+}
+
+module_init(vlan_mt_init);
+module_exit(vlan_mt_exit);
+
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/1] netfilter: Added vlan matching extension
2015-05-25 21:51 ` Florian Westphal
@ 2015-05-26 14:24 ` Eddi Linder
2015-05-27 12:35 ` Pablo Neira Ayuso
0 siblings, 1 reply; 5+ messages in thread
From: Eddi Linder @ 2015-05-26 14:24 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
Thanks for answering so fast Florian,
Yes, I do plan to use it with a bridge, but I don't think ebtables is
the proper solution, as I'd like to be able to use the matches and the
targets provided by the iptables extensions.
I plan to use vlan matching on an hypervisor that uses vlans for
tenant separation, and by using the iptables multiport extension I
plan to block unwanted traffic per tenant (which means per vlan).
I'll send my fixes shortly.
Thanks, Eddie
On Tue, May 26, 2015 at 12:51 AM, Florian Westphal <fw@strlen.de> wrote:
> Eddie Linder <eddi@guardicore.com> wrote:
>> Signed-off-by: Eddie Linder <eddi@guardicore.com>
>
> Why do we need a vlan tag match in iptables?
> For bridged traffic we have ebtables' net/bridge/netfilter/ebt_vlan.c .
>
> And for routed traffic you'd just use -i vlan.id.0 or whatever?
>
> What is this match being used for, and more importantly where/how?
> (Is this for call-iptables=1 invocation from bridge netfilter?)
>
> Nevertheless, a couple of comments below.
>
>> diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
>> index 1d973d2..2ca36db 100644
>> --- a/include/uapi/linux/netfilter/Kbuild
>> +++ b/include/uapi/linux/netfilter/Kbuild
>> @@ -85,3 +85,4 @@ header-y += xt_tcpmss.h
>> header-y += xt_tcpudp.h
>> header-y += xt_time.h
>> header-y += xt_u32.h
>> +header-y += xt_vlan.h
>> diff --git a/include/uapi/linux/netfilter/xt_vlan.h b/include/uapi/linux/netfilter/xt_vlan.h
>> new file mode 100644
>> index 0000000..3c31b6b
>> --- /dev/null
>> +++ b/include/uapi/linux/netfilter/xt_vlan.h
>> @@ -0,0 +1,11 @@
>> +#ifndef _XT_VLAN_H
>> +#define _XT_VLAN_H
>> +
>> +
>> +struct xt_vlan_info {
>> + unsigned short vlan_id;
>> + unsigned char vlan_pcp;
>
> Please consider using explicit types for all of these, i.e.
> __u16 vlan_id;
> __u8 vlan_pcp;
>
>> +MODULE_ALIAS("ipt_vlan");
>> +MODULE_ALIAS("ip6t_vlan");
>> +MODULE_ALIAS("ipt_VLAN");
>> +MODULE_ALIAS("ip6t_VLAN");
>
> _VLAN aliases are only needed for -j VLAN target, which isn't
> added here, please remove them.
>
>> +static bool vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
>> +{
>> + const struct xt_vlan_info *info = par->matchinfo;
>> + u16 vlan_tci = ~VLAN_TAG_PRESENT;
>> + bool ret;
>> +
>> + if (skb->vlan_tci & VLAN_TAG_PRESENT)
>> + /* Strip the 4096 bit (invalid vlan) from the vlan tci bits */
>> + vlan_tci = skb->vlan_tci;
>
> if (skb_vlan_tag_present(skb))
> vlan_tci = skb_vlan_tag_get(skb);
>
>> + else {
>> + if (unlikely(skb->len < VLAN_ETH_HLEN &&
>
> This is weird. Why test len < VLAN_ETH_HLEN (> ? >= ? )
>
>> + skb->protocol == htons(ETH_P_8021Q)))
>> + if (unlikely(!parse_vlan(skb, &vlan_tci)))
>> + return false;
>> + else
>> + return false;
>> + }
>
> Why call parse_vlan? We always return false without looking at
> vlan_tci...
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/1] netfilter: Added vlan matching extension
2015-05-26 14:24 ` Eddi Linder
@ 2015-05-27 12:35 ` Pablo Neira Ayuso
0 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2015-05-27 12:35 UTC (permalink / raw)
To: Eddi Linder; +Cc: Florian Westphal, netfilter-devel
On Tue, May 26, 2015 at 05:24:56PM +0300, Eddi Linder wrote:
[...]
> Yes, I do plan to use it with a bridge, but I don't think ebtables is
> the proper solution, as I'd like to be able to use the matches and the
> targets provided by the iptables extensions.
If we follow this path, we'll open the door to get more patches to
bloat iptables with features that actually belong to the bridge
family, just because you don't want to use ebtables for this.
We have the chance to resolve this situation from nf_tables.
Sorry, I'm not applying this.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-05-27 12:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-25 20:37 [PATCH 1/1] netfilter: Added vlan matching extension Eddie Linder
2015-05-25 21:51 ` Florian Westphal
2015-05-26 14:24 ` Eddi Linder
2015-05-27 12:35 ` Pablo Neira Ayuso
-- strict thread matches above, loose matches on Subject: below --
2015-05-26 9:13 Eddie Linder
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).