Skip to contentSkip to conversation

src: add redirect support

PATCH New Arturo Borrero Gonzalez 1 participant 1 message Nov 3, 2014 netfilter

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 src: add redirect support

This patch adds redirect support for nft.

The syntax is:

% nft add rule nat prerouting redirect [port|nat_flags]

---
v2: include regression tests-files

 include/statement.h             |   10 ++++++++
 src/evaluate.c                  |   40 ++++++++++++++++++++++++++++++
 src/netlink_delinearize.c       |   52 +++++++++++++++++++++++++++++++++++++++
 src/netlink_linearize.c         |   49 +++++++++++++++++++++++++++++++++++++
 src/parser.y                    |   23 ++++++++++++++++-
 src/scanner.l                   |    1 +
 src/statement.c                 |   29 ++++++++++++++++++++++
 tests/regression/ip/redirect.t  |   41 +++++++++++++++++++++++++++++++
 tests/regression/ip6/redirect.t |   42 ++++++++++++++++++++++++++++++++
 9 files changed, 285 insertions(+), 2 deletions(-)
 create mode 100644 tests/regression/ip/redirect.t
 create mode 100644 tests/regression/ip6/redirect.t
include/statement.h +10 -0
index 35c1b7a..d143121 100644
@@ -79,6 +79,13 @@ struct masq_stmt {
 
 extern struct stmt *masq_stmt_alloc(const struct location *loc);
 
+struct redir_stmt {
+	struct expr		*proto;
+	uint32_t		flags;
+};
+
+extern struct stmt *redir_stmt_alloc(const struct location *loc);
+
 struct queue_stmt {
 	struct expr		*queue;
 	uint16_t		flags;
@@ -110,6 +117,7 @@ extern struct stmt *ct_stmt_alloc(const struct location *loc,
  * @STMT_REJECT:	REJECT statement
  * @STMT_NAT:		NAT statement
  * @STMT_MASQ:		masquerade statement
+ * @STMT_REDIR:		redirect statement
  * @STMT_QUEUE:		QUEUE statement
  * @STMT_CT:		conntrack statement
  */
@@ -124,6 +132,7 @@ enum stmt_types {
 	STMT_REJECT,
 	STMT_NAT,
 	STMT_MASQ,
+	STMT_REDIR,
 	STMT_QUEUE,
 	STMT_CT,
 };
@@ -172,6 +181,7 @@ struct stmt {
 		struct reject_stmt	reject;
 		struct nat_stmt		nat;
 		struct masq_stmt	masq;
+		struct redir_stmt	redir;
 		struct queue_stmt	queue;
 		struct ct_stmt		ct;
 	};
src/evaluate.c +40 -0
index b722567..3eeb614 100644
@@ -1546,6 +1546,44 @@ out:
 	return 0;
 }
 
+static int stmt_evaluate_redir(struct eval_ctx *ctx, struct stmt *stmt)
+{
+	int err;
+	struct proto_ctx *pctx = &ctx->pctx;
+
+	if (!pctx)
+		goto out;
+
+	switch (pctx->family) {
+	case AF_INET:
+		expr_set_context(&ctx->ectx, &ipaddr_type,
+				4 * BITS_PER_BYTE);
+		break;
+	case AF_INET6:
+		expr_set_context(&ctx->ectx, &ip6addr_type,
+				 16 * BITS_PER_BYTE);
+		break;
+	default:
+		return stmt_error(ctx, stmt, "ip and ip6 support only");
+	}
+
+	if (stmt->redir.proto != NULL) {
+		if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL)
+			return stmt_binary_error(ctx, stmt->redir.proto, stmt,
+						 "missing transport protocol match");
+
+		expr_set_context(&ctx->ectx, &inet_service_type,
+				 2 * BITS_PER_BYTE);
+		err = expr_evaluate(ctx, &stmt->redir.proto);
+		if (err < 0)
+			return err;
+	}
+
+out:
+	stmt->flags |= STMT_F_TERMINAL;
+	return 0;
+}
+
 static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
 {
 	expr_set_context(&ctx->ectx, stmt->ct.tmpl->dtype,
@@ -1608,6 +1646,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
 		return stmt_evaluate_nat(ctx, stmt);
 	case STMT_MASQ:
 		return stmt_evaluate_masq(ctx, stmt);
+	case STMT_REDIR:
+		return stmt_evaluate_redir(ctx, stmt);
 	case STMT_QUEUE:
 		return stmt_evaluate_queue(ctx, stmt);
 	case STMT_CT:
src/netlink_delinearize.c +52 -0

70 lines not on this page · raw message

src/netlink_linearize.c +49 -0

61 lines not on this page · raw message

src/parser.y +21 -2
index 9e9a839..6209e9e 100644
@@ -375,6 +375,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token SNAT			"snat"
 %token DNAT			"dnat"
 %token MASQUERADE		"masquerade"
+%token REDIRECT			"redirect"
 %token RANDOM			"random"
 %token RANDOM_FULLY		"random-fully"
 %token PERSISTENT		"persistent"
@@ -440,8 +441,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <val>			time_unit
 %type <stmt>			reject_stmt reject_stmt_alloc
 %destructor { stmt_free($$); }	reject_stmt reject_stmt_alloc
-%type <stmt>			nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc
-%destructor { stmt_free($$); }	nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc
+%type <stmt>			nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
+%destructor { stmt_free($$); }	nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
 %type <val>			nf_nat_flags nf_nat_flag
 %type <stmt>			queue_stmt queue_stmt_alloc
 %destructor { stmt_free($$); }	queue_stmt queue_stmt_alloc
@@ -1186,6 +1187,7 @@ stmt			:	verdict_stmt
 			|	queue_stmt
 			|	ct_stmt
 			|	masq_stmt
+			|	redir_stmt
 			;
 
 verdict_stmt		:	verdict_expr
@@ -1420,6 +1422,23 @@ masq_stmt		:	masq_stmt_alloc
 masq_stmt_alloc		:	MASQUERADE 	{ $$ = masq_stmt_alloc(&@$); }
 			;
 
+redir_stmt		:	redir_stmt_alloc	redir_stmt_arg
+			|	redir_stmt_alloc
+			;
+
+redir_stmt_alloc	:	REDIRECT	{ $$ = redir_stmt_alloc(&@$); }
+			;
+
+redir_stmt_arg		:	COLON	expr
+			{
+				$<stmt>0->redir.proto = $2;
+			}
+			|	nf_nat_flags
+			{
+				$<stmt>0->redir.flags = $1;
+			}
+			;
+
 nf_nat_flags		:	nf_nat_flag
 			|	nf_nat_flags	COMMA	nf_nat_flag
 			{
src/scanner.l +1 -0
index 32e59d9..e36c3b1 100644
@@ -317,6 +317,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "snat"			{ return SNAT; }
 "dnat"			{ return DNAT; }
 "masquerade"		{ return MASQUERADE; }
+"redirect"		{ return REDIRECT; }
 "random"		{ return RANDOM; }
 "random-fully"		{ return RANDOM_FULLY; }
 "persistent"		{ return PERSISTENT; }
src/statement.c +29 -0
index 0ae616a..2587d27 100644
@@ -348,3 +348,32 @@ struct stmt *masq_stmt_alloc(const struct location *loc)
 {
 	return stmt_alloc(loc, &masq_stmt_ops);
 }
+
+static void redir_stmt_print(const struct stmt *stmt)
+{
+	printf("redirect");
+
+	if (stmt->redir.proto) {
+		printf(" :");
+		expr_print(stmt->redir.proto);
+	}
+
+	print_nf_nat_flags(stmt->redir.flags);
+}
+
+static void redir_stmt_destroy(struct stmt *stmt)
+{
+	expr_free(stmt->redir.proto);
+}
+
+static const struct stmt_ops redir_stmt_ops = {
+	.type		= STMT_REDIR,
+	.name		= "redir",
+	.print		= redir_stmt_print,
+	.destroy	= redir_stmt_destroy,
+};
+
+struct stmt *redir_stmt_alloc(const struct location *loc)
+{
+	return stmt_alloc(loc, &redir_stmt_ops);
+}
tests/regression/ip/redirect.t new file +41 -0

41 lines not on this page · raw message

tests/regression/ip6/redirect.t new file +42 -0

42 lines not on this page · raw message