diff mbox series

[nft,2/2] src: add ipip support

Message ID 20221005224833.24056-3-pablo@netfilter.org
State Changes Requested
Delegated to: Pablo Neira
Headers show
Series gre and ipip tunnel support | expand

Commit Message

Pablo Neira Ayuso Oct. 5, 2022, 10:48 p.m. UTC
This generates an implicit dependency on NFT_META_L4PROTO for IPPROTO_IP.
This does _not_ generate a dependendy for NFT_META_PROTOCOL on 0x800 (ip)
because the tunnel protocol driver "ip6tnl" in the tree uses IPPROTO_IP
for IPv4 over IPv6 (ipip6).

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/proto.h           |  2 ++
 src/netlink_delinearize.c |  4 ++++
 src/parser_bison.y        | 22 ++++++++++++++++++++--
 src/proto.c               | 18 ++++++++++++++++++
 src/scanner.l             |  1 +
 5 files changed, 45 insertions(+), 2 deletions(-)

Comments

Pablo Neira Ayuso Oct. 5, 2022, 10:53 p.m. UTC | #1
On Thu, Oct 06, 2022 at 12:48:33AM +0200, Pablo Neira Ayuso wrote:
> This generates an implicit dependency on NFT_META_L4PROTO for IPPROTO_IP.

s/IPPROTO_IP/IPPROTO_IPIP

> This does _not_ generate a dependendy for NFT_META_PROTOCOL on 0x800 (ip)
> because the tunnel protocol driver "ip6tnl" in the tree uses IPPROTO_IP

again:

s/IPPROTO_IP/IPPROTO_IPIP

> for IPv4 over IPv6 (ipip6).
diff mbox series

Patch

diff --git a/include/proto.h b/include/proto.h
index 2a82c385c330..14e25e0aefa4 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -98,6 +98,7 @@  enum proto_desc_id {
 	PROTO_DESC_ETHER,
 	PROTO_DESC_VXLAN,
 	PROTO_DESC_GRE,
+	PROTO_DESC_IPIP,
 	__PROTO_DESC_MAX
 };
 #define PROTO_DESC_MAX	(__PROTO_DESC_MAX - 1)
@@ -410,6 +411,7 @@  enum gre_hdr_fields {
 
 extern const struct proto_desc proto_vxlan;
 extern const struct proto_desc proto_gre;
+extern const struct proto_desc proto_ipip;
 
 extern const struct proto_desc proto_icmp;
 extern const struct proto_desc proto_igmp;
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 68185d477cc1..d411ae8e37c5 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1980,6 +1980,10 @@  static bool meta_outer_may_dependency_kill(struct rule_pp_ctx *ctx,
 		if (expr->left->payload.inner_desc == &proto_gre)
 			return true;
 		break;
+	case IPPROTO_IPIP:
+		if (expr->left->payload.inner_desc == &proto_ipip)
+			return true;
+		break;
 	default:
 		break;
 	}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 52fb17a83879..ca7e14b7d613 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -432,6 +432,7 @@  int nft_lex(void *, void *, void *);
 %token VNI			"vni"
 
 %token GRE			"gre"
+%token IPIP			"ipip"
 
 %token SCTP			"sctp"
 %token CHUNK			"chunk"
@@ -891,8 +892,8 @@  int nft_lex(void *, void *, void *);
 %type <val>			tcpopt_field_maxseg	tcpopt_field_mptcp	tcpopt_field_sack	 tcpopt_field_tsopt	tcpopt_field_window
 %type <tcp_kind_field>		tcp_hdr_option_kind_and_field
 
-%type <expr>			inner_eth_expr inner_inet_expr inner_expr vxlan_hdr_expr gre_hdr_expr
-%destructor { expr_free($$); }	inner_eth_expr inner_inet_expr inner_expr vxlan_hdr_expr gre_hdr_expr
+%type <expr>			inner_eth_expr inner_inet_expr inner_expr vxlan_hdr_expr gre_hdr_expr ipip_hdr_expr
+%destructor { expr_free($$); }	inner_eth_expr inner_inet_expr inner_expr vxlan_hdr_expr gre_hdr_expr ipip_hdr_expr
 %type <val>			vxlan_hdr_field gre_hdr_field
 
 %type <stmt>			optstrip_stmt
@@ -4849,6 +4850,15 @@  primary_rhs_expr	:	symbol_expr		{ $$ = $1; }
 			|	GRE
 			{
 				uint8_t data = IPPROTO_GRE;
+
+				$$ = constant_expr_alloc(&@$, &inet_protocol_type,
+							 BYTEORDER_HOST_ENDIAN,
+							 sizeof(data) * BITS_PER_BYTE, &data);
+			}
+			|	IPIP
+			{
+				uint8_t data = IPPROTO_IPIP;
+
 				$$ = constant_expr_alloc(&@$, &inet_protocol_type,
 							 BYTEORDER_HOST_ENDIAN,
 							 sizeof(data) * BITS_PER_BYTE, &data);
@@ -5310,6 +5320,7 @@  payload_expr		:	payload_raw_expr
 			|	th_hdr_expr
 			|	vxlan_hdr_expr
 			|	gre_hdr_expr
+			|	ipip_hdr_expr
 			;
 
 payload_raw_expr	:	AT	payload_base_spec	COMMA	NUM	COMMA	NUM	close_scope_at
@@ -5625,6 +5636,13 @@  gre_hdr_field		:	FLAGS			{ $$ = GREHDR_FLAGS; }
 			|	PROTOCOL		{ $$ = GREHDR_PROTOCOL; }
 			;
 
+ipip_hdr_expr		:	IPIP	inner_expr
+			{
+				$$ = $2;
+				$$->payload.inner_desc = &proto_ipip;
+			}
+			;
+
 optstrip_stmt		:	RESET	TCP	OPTION	tcp_hdr_option_type	close_scope_tcp
 			{
 				$$ = optstrip_stmt_alloc(&@$, tcpopt_expr_alloc(&@$,
diff --git a/src/proto.c b/src/proto.c
index 10454d405888..72e9e4a542a3 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -91,6 +91,7 @@  int proto_find_num(const struct proto_desc *base,
 static const struct proto_desc *inner_protocols[] = {
 	&proto_vxlan,
 	&proto_gre,
+	&proto_ipip,
 };
 
 const struct proto_desc *proto_find_inner(uint32_t type, uint32_t hdrsize,
@@ -800,6 +801,20 @@  const struct proto_desc proto_gre = {
 #define IPHDR_ADDR(__name, __member) \
 	HDR_TYPE(__name, &ipaddr_type, struct iphdr, __member)
 
+const struct proto_desc proto_ipip = {
+	.name		= "ipip",
+	.id		= PROTO_DESC_IPIP,
+	.base		= PROTO_BASE_TRANSPORT_HDR,
+	.templates	= {
+		[0]	= PROTO_META_TEMPLATE("l4proto", &inet_protocol_type, NFT_META_L4PROTO, 8),
+	},
+	.inner		= {
+		.hdrsize	= 0,
+		.flags		= NFT_INNER_NH | NFT_INNER_TH,
+		.type		= NFT_INNER_GENEVE + 2,
+	},
+};
+
 const struct proto_desc proto_ip = {
 	.name		= "ip",
 	.id		= PROTO_DESC_IP,
@@ -819,6 +834,7 @@  const struct proto_desc proto_ip = {
 		PROTO_LINK(IPPROTO_DCCP,	&proto_dccp),
 		PROTO_LINK(IPPROTO_SCTP,	&proto_sctp),
 		PROTO_LINK(IPPROTO_GRE,		&proto_gre),
+		PROTO_LINK(IPPROTO_IPIP,	&proto_ipip),
 	},
 	.templates	= {
 		[0]	= PROTO_META_TEMPLATE("l4proto", &inet_protocol_type, NFT_META_L4PROTO, 8),
@@ -1011,6 +1027,7 @@  const struct proto_desc proto_inet_service = {
 		PROTO_LINK(IPPROTO_IGMP,	&proto_igmp),
 		PROTO_LINK(IPPROTO_ICMPV6,	&proto_icmp6),
 		PROTO_LINK(IPPROTO_GRE,		&proto_gre),
+		PROTO_LINK(IPPROTO_IPIP,	&proto_ipip),
 	},
 	.templates	= {
 		[0]	= PROTO_META_TEMPLATE("l4proto", &inet_protocol_type, NFT_META_L4PROTO, 8),
@@ -1253,6 +1270,7 @@  static const struct proto_desc *proto_definitions[PROTO_DESC_MAX + 1] = {
 	[PROTO_DESC_ETHER]	= &proto_eth,
 	[PROTO_DESC_VXLAN]	= &proto_vxlan,
 	[PROTO_DESC_GRE]	= &proto_gre,
+	[PROTO_DESC_IPIP]	= &proto_ipip,
 };
 
 const struct proto_desc *proto_find_desc(enum proto_desc_id desc_id)
diff --git a/src/scanner.l b/src/scanner.l
index 2fc4c6c5e64a..b5b42be95689 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -624,6 +624,7 @@  addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "vni"			{ return VNI; }
 
 "gre"			{ return GRE; }
+"ipip"			{ return IPIP; }
 
 "tcp"			{ scanner_push_start_cond(yyscanner, SCANSTATE_TCP); return TCP; }