Netdev Archive on lore.kernel.org
 help / color / Atom feed
From: Martin Willi <martin@strongswan.org>
To: netfilter-devel@vger.kernel.org
Cc: netdev@vger.kernel.org
Subject: [PATCH iptables] extensions: Add new xt_slavedev input interface match extension
Date: Tue, 17 Dec 2019 14:56:16 +0100
Message-ID: <20191217135616.25751-3-martin@strongswan.org> (raw)
In-Reply-To: <20191217135616.25751-1-martin@strongswan.org>

When filtering in INPUT or FORWARD within a VRF domain, input interface
matching is done against the VRF device name instead of the real input
interface. This makes interface based filtering difficult if the interface
is associated to a VRF or some other layer 3 master device. While
PREROUTING can match against the real input interface, using it for
filtering is often inconvenient.

To allow filtering in INPUT/FORWARD against the real input interface,
add a match extension for this specific purpose. It is very similar
to the layer 2 slave device match implemented in xt_physdev to match
against bridge ports, but matches on layer 3 slave devices.

As an option, the user may specify a "strict" flag, limiting matches to
interfaces that strictly are layer 3 slave devices.

Signed-off-by: Martin Willi <martin@strongswan.org>
---
 extensions/libxt_slavedev.c           | 98 +++++++++++++++++++++++++++
 extensions/libxt_slavedev.man         | 19 ++++++
 extensions/libxt_slavedev.t           |  4 ++
 include/linux/netfilter/xt_slavedev.h | 18 +++++
 4 files changed, 139 insertions(+)
 create mode 100644 extensions/libxt_slavedev.c
 create mode 100644 extensions/libxt_slavedev.man
 create mode 100644 extensions/libxt_slavedev.t
 create mode 100644 include/linux/netfilter/xt_slavedev.h

diff --git a/extensions/libxt_slavedev.c b/extensions/libxt_slavedev.c
new file mode 100644
index 000000000000..d957c889e1a1
--- /dev/null
+++ b/extensions/libxt_slavedev.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <string.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_slavedev.h>
+
+enum {
+	O_SLAVEDEV_IN = 0,
+	O_SLAVEDEV_IN_STRICT,
+};
+
+static void slavedev_help(void)
+{
+	printf(
+"slavedev match options:\n"
+" [!] --slavedev-in inputname[+]	input device name ([+] for wildcard)\n"
+"     --slavedev-in-strict		input device must be layer 3 slave device\n");
+}
+
+static const struct xt_option_entry slavedev_opts[] = {
+	{.name = "slavedev-in", .id = O_SLAVEDEV_IN, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(struct xt_slavedev_info, iniface)},
+	{.name = "slavedev-in-strict", .id = O_SLAVEDEV_IN_STRICT,
+	 .type = XTTYPE_NONE},
+	XTOPT_TABLEEND,
+};
+
+static void slavedev_parse(struct xt_option_call *cb)
+{
+	struct xt_slavedev_info *info = cb->data;
+
+	xtables_option_parse(cb);
+	switch (cb->entry->id) {
+	case O_SLAVEDEV_IN:
+		xtables_parse_interface(cb->arg, info->iniface,
+					info->iniface_mask);
+		if (cb->invert)
+			info->flags |= XT_SLAVEDEV_IN_INV;
+		break;
+	case O_SLAVEDEV_IN_STRICT:
+		info->flags |= XT_SLAVEDEV_IN_STRICT;
+		break;
+	}
+}
+
+static bool slavedev_has_iniface(const struct xt_slavedev_info *info)
+{
+	int i;
+
+	for (i = 0; i < sizeof(info->iniface_mask); i++)
+		if (info->iniface_mask[i])
+			return true;
+	return false;
+}
+
+static void
+slavedev_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+	const struct xt_slavedev_info *info = (const void *)match->data;
+
+	printf(" slavedev");
+	if (slavedev_has_iniface(info))
+		printf("%s in %s",
+		       (info->flags & XT_SLAVEDEV_IN_INV) ? " !" : "",
+		       info->iniface);
+	if (info->flags & XT_SLAVEDEV_IN_STRICT)
+		printf(" in-strict");
+}
+
+static void slavedev_save(const void *ip, const struct xt_entry_match *match)
+{
+	const struct xt_slavedev_info *info = (const void *)match->data;
+
+	if (slavedev_has_iniface(info))
+		printf("%s --slavedev-in %s",
+		       (info->flags & XT_SLAVEDEV_IN_INV) ? " !" : "",
+		       info->iniface);
+	if (info->flags & XT_SLAVEDEV_IN_STRICT)
+		printf(" --slavedev-in-strict");
+}
+
+static struct xtables_match slavedev_match = {
+	.family		= NFPROTO_UNSPEC,
+	.name		= "slavedev",
+	.version	= XTABLES_VERSION,
+	.size		= XT_ALIGN(sizeof(struct xt_slavedev_info)),
+	.userspacesize	= XT_ALIGN(sizeof(struct xt_slavedev_info)),
+	.help		= slavedev_help,
+	.print		= slavedev_print,
+	.save		= slavedev_save,
+	.x6_parse	= slavedev_parse,
+	.x6_options	= slavedev_opts,
+};
+
+void _init(void)
+{
+	xtables_register_match(&slavedev_match);
+}
diff --git a/extensions/libxt_slavedev.man b/extensions/libxt_slavedev.man
new file mode 100644
index 000000000000..127eab4872f4
--- /dev/null
+++ b/extensions/libxt_slavedev.man
@@ -0,0 +1,19 @@
+This module matches on the real input interface enslaved to layer 3 master
+devices. For devices associated to VRF interfaces, the standard matching in
+\fBINPUT\fP and \fBFORWARD\fP chains can match against the VRF interface
+name, only. The slavedev match can match against the real input interface
+instead.
+.PP
+The slavedef match is valid in the \fBINPUT\fP and \fBFORWARD\fP chains
+only, as \fBPREROUTING\fP always matches against the real input interface.
+.TP
+[\fB!\fP] \fB\-\-slavedev\-in\fP \fIname\fP
+Name of a slave device the packet has been received on. If the interface name
+ends in a "+", then any interface which begins with this name will match.
+Not specifying an input interface can be used to match any packet that
+was received over a layer 3 slave device if the strict flag below is given.
+.TP
+\fB\-\-slavedev\-in\-strict\fP
+Matches only if the input interface is actually a layer 3 slave device,
+i.e. is associated to a VRF domain. If this flag is omitted, it also
+matches input interfaces without a layer 3 master device.
diff --git a/extensions/libxt_slavedev.t b/extensions/libxt_slavedev.t
new file mode 100644
index 000000000000..80b0ff3b4264
--- /dev/null
+++ b/extensions/libxt_slavedev.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD
+-m slavedev --slavedev-in lo;=;OK
+-m slavedev --slavedev-in-strict;=;OK
+-m slavedev --slavedev-in eth+ --slavedev-in-strict;=;OK
diff --git a/include/linux/netfilter/xt_slavedev.h b/include/linux/netfilter/xt_slavedev.h
new file mode 100644
index 000000000000..d35785b04c4b
--- /dev/null
+++ b/include/linux/netfilter/xt_slavedev.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_XT_SLAVEDEV_H
+#define _UAPI_XT_SLAVEDEV_H
+
+#include <linux/types.h>
+#include <linux/if.h>
+
+#define XT_SLAVEDEV_IN_INV	0x01	/* invert interface match */
+#define XT_SLAVEDEV_IN_STRICT	0x02	/* require iif to be enslaved */
+#define XT_SLAVEDEV_MASK	(0x04 - 1)
+
+struct xt_slavedev_info {
+	char iniface[IFNAMSIZ];
+	unsigned char iniface_mask[IFNAMSIZ];
+	__u8 flags;
+};
+
+#endif /* _UAPI_XT_SLAVEDEV_H */
-- 
2.20.1


  parent reply index

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-17 13:56 [PATCH netfilter/iptables] Add new slavedev " Martin Willi
2019-12-17 13:56 ` [PATCH nf-next] netfilter: xt_slavedev: Add new L3master slave input device match Martin Willi
2019-12-17 13:56 ` Martin Willi [this message]
2020-01-10 16:34 ` [PATCH netfilter/iptables] Add new slavedev match extension Martin Willi
2020-01-16 19:59   ` Pablo Neira Ayuso
2020-01-17 12:00     ` Martin Willi

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191217135616.25751-3-martin@strongswan.org \
    --to=martin@strongswan.org \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Netdev Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/netdev/0 netdev/git/0.git
	git clone --mirror https://lore.kernel.org/netdev/1 netdev/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 netdev netdev/ https://lore.kernel.org/netdev \
		netdev@vger.kernel.org
	public-inbox-index netdev

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.netdev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git