[PATCH iptables-nft] nft: disscect basic icmp type/code match

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

 



Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
---
 iptables/nft-shared.c                         | 114 ++++++++++++++++--
 .../nft-only/0010-iptables-nft-save.txt       |   6 +-
 2 files changed, 105 insertions(+), 15 deletions(-)

diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 996cff996c15..34e4053e60a9 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -876,6 +876,9 @@ static void nft_parse_th_port(struct nft_xt_ctx *ctx,
 	case IPPROTO_TCP:
 		nft_parse_tcp(ctx, cs, sport, dport, op);
 		break;
+	default:
+		ctx->errmsg = "unknown l4 proto";
+		break;
 	}
 }
 
@@ -910,6 +913,80 @@ static void nft_parse_tcp_flags(struct nft_xt_ctx *ctx,
 	tcp->flg_mask = mask;
 }
 
+static void nft_parse_icmp(struct nft_xt_ctx *ctx,
+			   struct nft_xt_ctx_reg *sreg,
+			   struct nftnl_expr *e,
+			   struct iptables_command_state *cs,
+			   const char *name)
+{
+	struct xtables_rule_match *m;
+	struct xtables_match *match;
+	struct ipt_icmp *icmp;
+	const uint8_t *v;
+	unsigned int len;
+	int op;
+
+	v = nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
+	switch (sreg->payload.offset) {
+	case 0:
+		if (len == 1 || len == 2)
+			break;
+		return;
+	case 1:
+		if (len == 1)
+			break;
+		return;
+	default:
+		ctx->errmsg = "unhandled icmp offset";
+		return;
+	}
+
+	for (m = cs->matches; m; m = m->next) {
+		match = m->match;
+
+		if (strcmp(match->m->u.user.name, name) == 0) {
+			icmp = (void *)match->m->data;
+			goto found;
+		}
+	}
+
+	match = nft_create_match(ctx, cs, name);
+	if (!match) {
+		ctx->errmsg = "failed to add icmp match";
+		return;
+	}
+	icmp = (void*)match->m->data;
+found:
+	op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
+
+	switch (sreg->payload.offset) {
+	case 0:
+		icmp->type = *v;
+		if (len == 1)
+			break;
+		v++;
+	case 1:
+		if (op == NFT_CMP_LTE) {
+			icmp->code[1] = *v;
+			break;
+		}
+
+		icmp->code[0] = *v;
+
+		if (op == NFT_CMP_GTE)
+			break;
+
+		icmp->code[1] = *v;
+		break;
+	default:
+		ctx->errmsg = "unhandled icmp offset";
+		break;
+	}
+
+	if (op == NFT_CMP_NEQ)
+		icmp->invflags |= IPT_ICMP_INV;
+}
+
 static void nft_parse_transport(struct nft_xt_ctx *ctx,
 				struct nftnl_expr *e,
 				struct iptables_command_state *cs)
@@ -921,18 +998,6 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
 	uint8_t proto, op;
 	unsigned int len;
 
-	switch (ctx->h->family) {
-	case NFPROTO_IPV4:
-		proto = ctx->cs->fw.ip.proto;
-		break;
-	case NFPROTO_IPV6:
-		proto = ctx->cs->fw6.ipv6.proto;
-		break;
-	default:
-		proto = 0;
-		break;
-	}
-
 	nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
 	op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
 
@@ -946,6 +1011,22 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
 		return;
 	}
 
+	switch (ctx->h->family) {
+	case NFPROTO_IPV4:
+		proto = ctx->cs->fw.ip.proto;
+		if (proto == IPPROTO_ICMP)
+			return nft_parse_icmp(ctx, sreg, e, cs, "icmp");
+		break;
+	case NFPROTO_IPV6:
+		proto = ctx->cs->fw6.ipv6.proto;
+		if (proto == IPPROTO_ICMPV6)
+			return nft_parse_icmp(ctx, sreg, e, cs, "icmp6");
+		break;
+	default:
+		proto = 0;
+		break;
+	}
+
 	switch(sreg->payload.offset) {
 	case 0: /* th->sport */
 		switch (len) {
@@ -957,6 +1038,9 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
 			sdport = ntohl(nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_DATA));
 			nft_parse_th_port(ctx, cs, proto, sdport >> 16, sdport & 0xffff, op);
 			return;
+		default:
+			ctx->errmsg = "unhandled th slen";
+			break;
 		}
 		break;
 	case 2: /* th->dport */
@@ -965,6 +1049,9 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
 			port = ntohs(nftnl_expr_get_u16(e, NFTNL_EXPR_CMP_DATA));
 			nft_parse_th_port(ctx, cs, proto, -1, port, op);
 			return;
+		default:
+			ctx->errmsg = "unhandled th dlen";
+			break;
 		}
 		break;
 	case 13: /* th->flags */
@@ -978,6 +1065,9 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
 			nft_parse_tcp_flags(ctx, cs, op, flags, mask);
 		}
 		return;
+	default:
+		ctx->errmsg = "unhandled l4 offset";
+		break;
 	}
 }
 
diff --git a/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt b/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt
index 73d7108c5094..5ee4c23113aa 100644
--- a/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt
+++ b/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt
@@ -13,9 +13,9 @@
 -A INPUT -d 0.0.0.0/2 -m ttl --ttl-gt 2 -j ACCEPT
 -A INPUT -d 0.0.0.0/3 -m ttl --ttl-lt 254 -j ACCEPT
 -A INPUT -d 0.0.0.0/4 -m ttl ! --ttl-eq 255 -j DROP
--A INPUT -d 8.0.0.0/5 -p icmp -j ACCEPT
--A INPUT -d 8.0.0.0/6 -p icmp -j ACCEPT
--A INPUT -d 10.0.0.0/7 -p icmp -j ACCEPT
+-A INPUT -d 8.0.0.0/5 -p icmp -m icmp --icmp-type 1 -j ACCEPT
+-A INPUT -d 8.0.0.0/6 -p icmp -m icmp --icmp-type 2/3 -j ACCEPT
+-A INPUT -d 10.0.0.0/7 -p icmp -m icmp --icmp-type 8 -j ACCEPT
 -A INPUT -m pkttype --pkt-type broadcast -j ACCEPT
 -A INPUT -m pkttype ! --pkt-type unicast -j DROP
 -A INPUT -p tcp
-- 
2.37.3




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux