[PATCH nft 1/2] src: fix routing header support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We can't use nft_exthdr_op to encode routign header, it breaks
ipv6 extension header support.

When encountering RT header, userspace did now set a new
ipv6 exthdr mode, but old kernel doesn't know about this, else
this now faile with -EOPNOTSUPP.

Revert that part and use NFT_EXTHDR_OP_IPV6.
When decoding a routing extension header, try the various route
types until we find a match.

Note this patch isn't complete:

'srh tag 127' creates following expressions:
  [ exthdr load 2b @ 43 + 6 => reg 1 ]
  [ cmp eq reg 1 0x00007f00 ]

It should instead insert a dependency test ("rt type 4"):
  [ exthdr load 1b @ 43 + 2 => reg 1 ]
  [ cmp eq reg 1 0x00000004 ]
  [ exthdr load 2b @ 43 + 6 => reg 1 ]
  [ cmp eq reg 1 0x00007e00 ]

nft should then use this to infer the routing header type.

While add it, document the srh option.

Cc: Ahmed Abdelsalam <amsalam20@xxxxxxxxx>
Fixes: 1400288f6d39d ("src: handle rt0 and rt2 properly")
Reported-by: Phil Sutter <phil@xxxxxx>
Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
---
 NB: Kernel change that introduced RT0, 2 , 4 can be reverted now.

 doc/nft.xml                         | 13 +++++++++
 include/linux/netfilter/nf_tables.h |  3 --
 src/exthdr.c                        | 55 ++++++++++++++++++++++---------------
 3 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/doc/nft.xml b/doc/nft.xml
index 07f4f2770a4a..962e29339bb9 100644
--- a/doc/nft.xml
+++ b/doc/nft.xml
@@ -4074,6 +4074,15 @@ input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh
 					<arg>type</arg>
 				</group>
 			</cmdsynopsis>
+			<cmdsynopsis>
+				<command>srh</command>
+				<group choice="req">
+					<arg>flags</arg>
+					<arg>tag</arg>
+					<arg>sid</arg>
+					<arg>seg-left</arg>
+				</group>
+			</cmdsynopsis>
 			<cmdsynopsis>
 				<command>tcp option</command>
 				<group choice="req">
@@ -4154,6 +4163,10 @@ input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh
 								<entry>mh</entry>
 								<entry>Mobility Header</entry>
 							</row>
+							<row>
+								<entry>srh</entry>
+								<entry>Segment Routing Header</entry>
+							</row>
 						</tbody>
 					</tgroup>
 				</table>
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 1a98f03a550b..517a39a00e3d 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -731,9 +731,6 @@ enum nft_exthdr_flags {
 enum nft_exthdr_op {
 	NFT_EXTHDR_OP_IPV6,
 	NFT_EXTHDR_OP_TCPOPT,
-	NFT_EXTHDR_OP_RT0,
-	NFT_EXTHDR_OP_RT2,
-	NFT_EXTHDR_OP_RT4,
 	__NFT_EXTHDR_OP_MAX
 };
 #define NFT_EXTHDR_OP_MAX	(__NFT_EXTHDR_OP_MAX - 1)
diff --git a/src/exthdr.c b/src/exthdr.c
index cbe0da86a156..06a82070a6bb 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -93,19 +93,6 @@ struct expr *exthdr_expr_alloc(const struct location *loc,
 			  BYTEORDER_BIG_ENDIAN, tmpl->len);
 	expr->exthdr.desc = desc;
 	expr->exthdr.tmpl = tmpl;
-	if (desc != NULL && desc->proto_key >= 0) {
-		switch (desc->proto_key) {
-		case 0:
-			expr->exthdr.op = NFT_EXTHDR_OP_RT0;
-			break;
-		case 2:
-			expr->exthdr.op = NFT_EXTHDR_OP_RT2;
-			break;
-		case 4:
-			expr->exthdr.op = NFT_EXTHDR_OP_RT4;
-			break;
-		}
-	}
 	return expr;
 }
 
@@ -148,6 +135,24 @@ const struct exthdr_desc *exthdr_find_proto(uint8_t proto)
 	return exthdr_protocols[proto];
 }
 
+static const struct proto_hdr_template *
+exthdr_rt_find(struct expr *expr, const struct exthdr_desc *desc)
+{
+	const struct proto_hdr_template *tmpl;
+	unsigned int i;
+
+	for (i = 0; i < array_size(desc->templates); i++) {
+		tmpl = &desc->templates[i];
+		if (tmpl->offset == expr->exthdr.offset &&
+		    tmpl->len == expr->len) {
+			expr->exthdr.desc = desc;
+			return tmpl;
+		}
+	}
+
+	return NULL;
+}
+
 void exthdr_init_raw(struct expr *expr, uint8_t type,
 		     unsigned int offset, unsigned int len,
 		     enum nft_exthdr_op op, uint32_t flags)
@@ -164,13 +169,7 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
 	expr->exthdr.offset = offset;
 	expr->exthdr.desc = NULL;
 
-	if (op == NFT_EXTHDR_OP_RT0)
-		expr->exthdr.desc = &exthdr_rt0;
-	else if (op == NFT_EXTHDR_OP_RT2)
-		expr->exthdr.desc = &exthdr_rt2;
-	else if (op == NFT_EXTHDR_OP_RT4)
-		expr->exthdr.desc = &exthdr_rt4;
-	else if (type < array_size(exthdr_protocols))
+	if (type < array_size(exthdr_protocols))
 		expr->exthdr.desc = exthdr_protocols[type];
 
 	if (expr->exthdr.desc == NULL)
@@ -182,6 +181,18 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
 			goto out;
 	}
 
+	if (expr->exthdr.desc == &exthdr_rt) {
+		tmpl = exthdr_rt_find(expr, &exthdr_rt4);
+		if (tmpl)
+			goto out;
+		tmpl = exthdr_rt_find(expr, &exthdr_rt0);
+		if (tmpl)
+			goto out;
+		tmpl =	exthdr_rt_find(expr, &exthdr_rt2);
+		if (tmpl)
+			goto out;
+	}
+
 	tmpl = &exthdr_unknown_template;
  out:
 	expr->exthdr.tmpl = tmpl;
@@ -274,7 +285,7 @@ const struct exthdr_desc exthdr_rt0 = {
 	.templates	= {
 		[RT0HDR_RESERVED]	= RT0_FIELD("reserved", ip6r0_reserved, &integer_type),
 		[RT0HDR_ADDR_1]		= RT0_FIELD("addr[1]", ip6r0_addr[0], &ip6addr_type),
-		[RT0HDR_ADDR_1 + 1]	= RT0_FIELD("addr[2]", ip6r0_addr[0], &ip6addr_type),
+		[RT0HDR_ADDR_1 + 1]	= RT0_FIELD("addr[2]", ip6r0_addr[1], &ip6addr_type),
 		// ...
 	},
 };
@@ -291,7 +302,7 @@ const struct exthdr_desc exthdr_rt4 = {
 		[RT4HDR_FLAGS]		= RT4_FIELD("flags", ip6r4_flags, &integer_type),
 		[RT4HDR_TAG]		= RT4_FIELD("tag", ip6r4_tag, &integer_type),
 		[RT4HDR_SID_1]		= RT4_FIELD("sid[1]", ip6r4_segments[0], &ip6addr_type),
-		[RT4HDR_SID_1 + 1]	= RT4_FIELD("sid[1]", ip6r4_segments[0], &ip6addr_type),
+		[RT4HDR_SID_1 + 1]	= RT4_FIELD("sid[2]", ip6r4_segments[1], &ip6addr_type),
 		// ...
 	},
 };
-- 
2.16.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux