netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2-next 0/2] tc: add ipt ematch
@ 2018-02-23 11:12 Eyal Birger
  2018-02-23 11:12 ` [PATCH iproute2-next 1/2] tc: ematch: add parse_eopt_argv() method for providing ematches with argv parameters Eyal Birger
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Eyal Birger @ 2018-02-23 11:12 UTC (permalink / raw)
  To: netdev; +Cc: dsahern, shmulik, Eyal Birger

This patchset extends tc to support the ipt ematch.

The first patch adds the ability for ematch cmdline parsers
to receive argc,argv parameters.
The second patch adds the em_ipt module.

Eyal Birger (2):
  tc: ematch: add parse_eopt_argv() method for providing ematches with
    argv parameters
  tc: add em_ipt ematch for calling xtables matches from tc matching
    context

 etc/iproute2/ematch_map |   1 +
 man/man8/tc-ematch.8    |  15 ++++
 tc/Makefile             |   7 ++
 tc/em_ipt.c             | 208 ++++++++++++++++++++++++++++++++++++++++++++++++
 tc/m_ematch.c           |  27 ++++++-
 tc/m_ematch.h           |   2 +
 6 files changed, 259 insertions(+), 1 deletion(-)
 create mode 100644 tc/em_ipt.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH iproute2-next 1/2] tc: ematch: add parse_eopt_argv() method for providing ematches with argv parameters
  2018-02-23 11:12 [PATCH iproute2-next 0/2] tc: add ipt ematch Eyal Birger
@ 2018-02-23 11:12 ` Eyal Birger
  2018-02-23 11:12 ` [PATCH iproute2-next 2/2] tc: add em_ipt ematch for calling xtables matches from tc matching context Eyal Birger
  2018-02-27 17:45 ` [PATCH iproute2-next 0/2] tc: add ipt ematch David Ahern
  2 siblings, 0 replies; 4+ messages in thread
From: Eyal Birger @ 2018-02-23 11:12 UTC (permalink / raw)
  To: netdev; +Cc: dsahern, shmulik, Eyal Birger

ematche uses YACC to parse ematch arguments and places them in struct bstr
linked lists.

It is useful to be able to receive parameters as argc,argv in order to use
getopt (and alike) argument parsers.

Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
---
 tc/m_ematch.c | 27 ++++++++++++++++++++++++++-
 tc/m_ematch.h |  2 ++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/tc/m_ematch.c b/tc/m_ematch.c
index 7dbc2e7..61f8fb3 100644
--- a/tc/m_ematch.c
+++ b/tc/m_ematch.c
@@ -169,6 +169,31 @@ static struct ematch_util *get_ematch_kind_num(__u16 kind)
 	return get_ematch_kind(name);
 }
 
+static int em_parse_call(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
+			 struct ematch_util *e, struct ematch *t)
+{
+	if (e->parse_eopt_argv) {
+		int argc = 0, i = 0, ret;
+		struct bstr *args;
+		char **argv;
+
+		for (args = t->args; args; args = bstr_next(args))
+			argc++;
+		argv = calloc(argc, sizeof(char *));
+		if (!argv)
+			return -1;
+		for (args = t->args; args; args = bstr_next(args))
+			argv[i++] = args->data;
+
+		ret = e->parse_eopt_argv(n, hdr, argc, argv);
+
+		free(argv);
+		return ret;
+	}
+
+	return e->parse_eopt(n, hdr, t->args->next);
+}
+
 static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
 {
 	int index = 1;
@@ -212,7 +237,7 @@ static int parse_tree(struct nlmsghdr *n, struct ematch *tree)
 			}
 
 			hdr.kind = num;
-			if (e->parse_eopt(n, &hdr, t->args->next) < 0)
+			if (em_parse_call(n, &hdr, e, t) < 0)
 				return -1;
 		}
 
diff --git a/tc/m_ematch.h b/tc/m_ematch.h
index fa6e214..f634f19 100644
--- a/tc/m_ematch.h
+++ b/tc/m_ematch.h
@@ -88,6 +88,8 @@ struct ematch_util
 	int			kind_num;
 	int	(*parse_eopt)(struct nlmsghdr *,struct tcf_ematch_hdr *,
 			      struct bstr *);
+	int	(*parse_eopt_argv)(struct nlmsghdr *, struct tcf_ematch_hdr *,
+				   int, char **);
 	int	(*print_eopt)(FILE *, struct tcf_ematch_hdr *, void *, int);
 	void	(*print_usage)(FILE *);
 	struct ematch_util	*next;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH iproute2-next 2/2] tc: add em_ipt ematch for calling xtables matches from tc matching context
  2018-02-23 11:12 [PATCH iproute2-next 0/2] tc: add ipt ematch Eyal Birger
  2018-02-23 11:12 ` [PATCH iproute2-next 1/2] tc: ematch: add parse_eopt_argv() method for providing ematches with argv parameters Eyal Birger
@ 2018-02-23 11:12 ` Eyal Birger
  2018-02-27 17:45 ` [PATCH iproute2-next 0/2] tc: add ipt ematch David Ahern
  2 siblings, 0 replies; 4+ messages in thread
From: Eyal Birger @ 2018-02-23 11:12 UTC (permalink / raw)
  To: netdev; +Cc: dsahern, shmulik, Eyal Birger

The commit calls a new tc ematch for using netfilter xtable matches.

This allows early classification as well as mirroning/redirecting traffic
based on logic implemented in netfilter extensions.

Current supported use case is classification based on the incoming IPSec
state used during decpsulation using the 'policy' iptables extension
(xt_policy).

The matcher uses libxtables for parsing the input parameters.

Example use for matching an IPSec state with reqid 1:

tc qdisc add dev eth0 ingress
tc filter add dev eth0 protocol ip parent ffff: \
    basic match 'ipt(-m policy --dir in --pol ipsec --reqid 1)' \
    action drop

This is the user-space counter part of kernel commit ccc007e4a746
("net: sched: add em_ipt ematch for calling xtables matches")

Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
---
 etc/iproute2/ematch_map |   1 +
 man/man8/tc-ematch.8    |  15 ++++
 tc/Makefile             |   7 ++
 tc/em_ipt.c             | 208 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 231 insertions(+)
 create mode 100644 tc/em_ipt.c

diff --git a/etc/iproute2/ematch_map b/etc/iproute2/ematch_map
index 1823983..4d6bb2f 100644
--- a/etc/iproute2/ematch_map
+++ b/etc/iproute2/ematch_map
@@ -5,3 +5,4 @@
 4	meta
 7	canid
 8	ipset
+9	ipt
diff --git a/man/man8/tc-ematch.8 b/man/man8/tc-ematch.8
index b9bf70c..042f840 100644
--- a/man/man8/tc-ematch.8
+++ b/man/man8/tc-ematch.8
@@ -98,6 +98,17 @@ When using the ipset ematch with the "ip_set_hash:net,iface" set type,
 the interface can be queried using "src,dst (source ip address, outgoing interface) or
 "src,src" (source ip address, incoming interface) syntax.
 
+.SS ipt
+test packet against xtables matches
+
+.IR ipt "( " [-6] " "-m " " MATCH_NAME " " FLAGS " )
+
+.IR MATCH_NAME " := " string
+
+.IR FLAGS " := { " FLAG " [, " FLAGS "] }
+
+The flag options are the same as those used by the xtable match used.
+
 .SH CAVEATS
 
 The ematch syntax uses '(' and ')' to group expressions. All braces need to be
@@ -127,6 +138,10 @@ Check if packet source ip and the interface the packet arrived on is member of "
 
 # 'ipset(interactive src,src)'
 
+Check if packet matches an IPSec state with reqid 1:
+
+# 'ipt(-m policy --dir in --pol ipsec --reqid 1)'
+
 .SH "AUTHOR"
 
 The extended match infrastructure was added by Thomas Graf.
diff --git a/tc/Makefile b/tc/Makefile
index 3716dd6..dfd0026 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -80,6 +80,7 @@ endif
 ifneq ($(TC_CONFIG_NO_XT),y)
   ifeq ($(TC_CONFIG_XT),y)
     TCSO += m_xt.so
+    TCMODULES += em_ipt.o
     ifeq ($(TC_CONFIG_IPSET),y)
       TCMODULES += em_ipset.o
     endif
@@ -163,6 +164,12 @@ m_xt_old.so: m_xt_old.c
 
 em_ipset.o: CFLAGS += $$($(PKG_CONFIG) xtables --cflags)
 
+em_ipt.o: CFLAGS += $$($(PKG_CONFIG) xtables --cflags)
+
+ifeq ($(TC_CONFIG_XT),y)
+  LDFLAGS += $$($(PKG_CONFIG) xtables --libs)
+endif
+
 %.yacc.c: %.y
 	$(QUIET_YACC)$(YACC) $(YACCFLAGS) -o $@ $<
 
diff --git a/tc/em_ipt.c b/tc/em_ipt.c
new file mode 100644
index 0000000..9d2b2f9
--- /dev/null
+++ b/tc/em_ipt.c
@@ -0,0 +1,208 @@
+/*
+ * em_ipt.c		IPtables extenstions matching Ematch
+ *
+ * (C) 2018 Eyal Birger <eyal.birger@gmail.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 <getopt.h>
+
+#include <linux/tc_ematch/tc_em_ipt.h>
+#include <linux/pkt_cls.h>
+#include <xtables.h>
+#include "m_ematch.h"
+
+static void em_ipt_print_usage(FILE *fd)
+{
+	fprintf(fd,
+		"Usage: ipt([-6] -m MATCH_NAME [MATCH_OPTS])\n"
+		"Example: 'ipt(-m policy --reqid 1 --pol ipsec --dir in)'\n");
+}
+
+static struct option original_opts[] = {
+	{
+		.name = "match",
+		.has_arg = 1,
+		.val = 'm'
+	},
+	{
+		.name = "ipv6",
+		.val = '6'
+	},
+	{}
+};
+
+static struct xtables_globals em_tc_ipt_globals = {
+	.option_offset = 0,
+	.program_name = "tc-em-ipt",
+	.program_version = "0.1",
+	.orig_opts = original_opts,
+	.opts = original_opts,
+	.compat_rev = xtables_compatible_revision,
+};
+
+static struct xt_entry_match *fake_xt_entry_match(int data_size, void *data)
+{
+	struct xt_entry_match *m;
+
+	m = xtables_calloc(1, XT_ALIGN(sizeof(*m)) + data_size);
+	if (!m)
+		return NULL;
+
+	if (data)
+		memcpy(m->data, data, data_size);
+
+	m->u.user.match_size = data_size;
+	return m;
+}
+
+static void scrub_match(struct xtables_match *match)
+{
+	match->mflags = 0;
+	free(match->m);
+	match->m = NULL;
+}
+
+/* IPv4 and IPv6 share the same hooking enumeration */
+#define HOOK_PRE_ROUTING 0
+#define HOOK_POST_ROUTING 4
+
+static __u32 em_ipt_hook(struct nlmsghdr *n)
+{
+	struct tcmsg *t = NLMSG_DATA(n);
+
+	if (t->tcm_parent != TC_H_ROOT &&
+	    t->tcm_parent == TC_H_MAJ(TC_H_INGRESS))
+		return HOOK_PRE_ROUTING;
+
+	return HOOK_POST_ROUTING;
+}
+
+static int em_ipt_parse_eopt_argv(struct nlmsghdr *n,
+				  struct tcf_ematch_hdr *hdr,
+				  int argc, char **argv)
+{
+	struct xtables_globals tmp_tcipt_globals = em_tc_ipt_globals;
+	struct xtables_match *match = NULL;
+	__u8 nfproto = NFPROTO_IPV4;
+
+	while (1) {
+		struct option *opts;
+		int c;
+
+		c = getopt_long(argc, argv, "6m:", tmp_tcipt_globals.opts,
+				NULL);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'm':
+			xtables_init_all(&tmp_tcipt_globals, nfproto);
+
+			match = xtables_find_match(optarg, XTF_TRY_LOAD, NULL);
+			if (!match || !match->x6_parse) {
+				fprintf(stderr, " failed to find match %s\n\n",
+					optarg);
+				return -1;
+			}
+
+			match->m = fake_xt_entry_match(match->size, NULL);
+			if (!match->m) {
+				printf(" %s error\n", match->name);
+				return -1;
+			}
+
+			if (match->init)
+				match->init(match->m);
+
+			opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts,
+						    tmp_tcipt_globals.opts,
+						    match->x6_options,
+						    &match->option_offset);
+			if (!opts) {
+				scrub_match(match);
+				return -1;
+			}
+
+			tmp_tcipt_globals.opts = opts;
+			break;
+
+		case '6':
+			nfproto = NFPROTO_IPV6;
+			break;
+
+		default:
+			if (!match) {
+				fprintf(stderr, "failed to find match %s\n\n",
+					optarg);
+				return -1;
+
+			}
+			xtables_option_mpcall(c, argv, 0, match, NULL);
+			break;
+		}
+	}
+
+	if (!match) {
+		fprintf(stderr, " failed to parse parameters (%s)\n", *argv);
+		return -1;
+	}
+
+	/* check that we passed the correct parameters to the match */
+	xtables_option_mfcall(match);
+
+	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
+	addattr32(n, MAX_MSG, TCA_EM_IPT_HOOK, em_ipt_hook(n));
+	addattrstrz(n, MAX_MSG, TCA_EM_IPT_MATCH_NAME, match->name);
+	addattr8(n, MAX_MSG, TCA_EM_IPT_MATCH_REVISION, match->revision);
+	addattr8(n, MAX_MSG, TCA_EM_IPT_NFPROTO, nfproto);
+	addattr_l(n, MAX_MSG, TCA_EM_IPT_MATCH_DATA, match->m->data,
+		  match->size);
+
+	xtables_free_opts(1);
+
+	scrub_match(match);
+	return 0;
+}
+
+static int em_ipt_print_epot(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
+			     int data_len)
+{
+	struct rtattr *tb[TCA_EM_IPT_MAX + 1];
+	struct xtables_match *match;
+	const char *mname;
+	__u8 nfproto;
+
+	if (parse_rtattr(tb, TCA_EM_IPT_MAX, data, data_len) < 0)
+		return -1;
+
+	nfproto = rta_getattr_u8(tb[TCA_EM_IPT_NFPROTO]);
+
+	xtables_init_all(&em_tc_ipt_globals, nfproto);
+
+	mname = rta_getattr_str(tb[TCA_EM_IPT_MATCH_NAME]);
+	match = xtables_find_match(mname, XTF_TRY_LOAD, NULL);
+	if (!match)
+		return -1;
+
+	match->m = fake_xt_entry_match(RTA_PAYLOAD(tb[TCA_EM_IPT_MATCH_DATA]),
+				       RTA_DATA(tb[TCA_EM_IPT_MATCH_DATA]));
+	if (!match->m)
+		return -1;
+
+	match->print(NULL, match->m, 0);
+
+	scrub_match(match);
+	return 0;
+}
+
+struct ematch_util ipt_ematch_util = {
+	.kind = "ipt",
+	.kind_num = TCF_EM_IPT,
+	.parse_eopt_argv = em_ipt_parse_eopt_argv,
+	.print_eopt = em_ipt_print_epot,
+	.print_usage = em_ipt_print_usage
+};
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH iproute2-next 0/2] tc: add ipt ematch
  2018-02-23 11:12 [PATCH iproute2-next 0/2] tc: add ipt ematch Eyal Birger
  2018-02-23 11:12 ` [PATCH iproute2-next 1/2] tc: ematch: add parse_eopt_argv() method for providing ematches with argv parameters Eyal Birger
  2018-02-23 11:12 ` [PATCH iproute2-next 2/2] tc: add em_ipt ematch for calling xtables matches from tc matching context Eyal Birger
@ 2018-02-27 17:45 ` David Ahern
  2 siblings, 0 replies; 4+ messages in thread
From: David Ahern @ 2018-02-27 17:45 UTC (permalink / raw)
  To: Eyal Birger, netdev; +Cc: dsahern, shmulik

On 2/23/18 4:12 AM, Eyal Birger wrote:
> This patchset extends tc to support the ipt ematch.
> 
> The first patch adds the ability for ematch cmdline parsers
> to receive argc,argv parameters.
> The second patch adds the em_ipt module.
> 
> Eyal Birger (2):
>   tc: ematch: add parse_eopt_argv() method for providing ematches with
>     argv parameters
>   tc: add em_ipt ematch for calling xtables matches from tc matching
>     context
> 
>  etc/iproute2/ematch_map |   1 +
>  man/man8/tc-ematch.8    |  15 ++++
>  tc/Makefile             |   7 ++
>  tc/em_ipt.c             | 208 ++++++++++++++++++++++++++++++++++++++++++++++++
>  tc/m_ematch.c           |  27 ++++++-
>  tc/m_ematch.h           |   2 +
>  6 files changed, 259 insertions(+), 1 deletion(-)
>  create mode 100644 tc/em_ipt.c
> 

series applied to iproute2-next.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-02-27 17:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-23 11:12 [PATCH iproute2-next 0/2] tc: add ipt ematch Eyal Birger
2018-02-23 11:12 ` [PATCH iproute2-next 1/2] tc: ematch: add parse_eopt_argv() method for providing ematches with argv parameters Eyal Birger
2018-02-23 11:12 ` [PATCH iproute2-next 2/2] tc: add em_ipt ematch for calling xtables matches from tc matching context Eyal Birger
2018-02-27 17:45 ` [PATCH iproute2-next 0/2] tc: add ipt ematch David Ahern

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).