Re: [iptables PATCH 2/2] ebtables-nft: Support user-defined chain policies

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

 



Phil Sutter <phil@xxxxxx> wrote:
> > after "ebtables -P FOOBAR RETURN".
> > Reverting this hunk shows "RETURN" as expected.
> 
> Oh. I missed that case. Of course that's not a real solution, otherwise
> user-defined chain policies will always show up as RETURN. I'll find a
> real fix.

Disregard that, I was low on caffeeine.

Attached patch makes things work much better for me (no need to take
this, consider it a bit more verbose bug report).

Not perfect, and one major issue remains.

When someone munges the chain using native nft, ebtables-nft shows:

Bridge chain: FOOBAR, entries: 1, policy: DROP
-d 01:02:03:04:05:06 -j CONTINUE

What it should show instead:
Bridge chain: FOOBAR, entries: 1, policy: RETURN
-j DROP
-d 01:02:03:04:05:06 -j CONTINUE

(because thats whats the actual state -- the last rule is unreachable).

Not a huge deal if we're only interested in "ebtables-nft only".

diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -358,7 +358,7 @@ static void nft_bridge_print_header(unsigned int format, const char *chain,
 				    bool basechain, uint32_t refs, uint32_t entries)
 {
 	printf("Bridge chain: %s, entries: %u, policy: %s\n",
-	       chain, entries, pol);
+	       chain, entries, pol ? pol : "RETURN");
 }
 
 static void print_matches_and_watchers(const struct iptables_command_state *cs,
diff --git a/iptables/nft.c b/iptables/nft.c
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1324,6 +1324,11 @@ retry:
 
 #define EBT_POLICY_COMMENT "XTABLES_EB_INTERNAL_POLICY_RULE"
 
+struct nftnl_rule_list_cb_data {
+	struct nft_handle *handle;
+	struct nftnl_chain *chain;
+};
+
 static bool nft_rule_is_policy_rule(struct nftnl_rule *r)
 {
 	const void *data;
@@ -1341,47 +1346,56 @@ static bool nft_rule_is_policy_rule(struct nftnl_rule *r)
 	return true;
 }
 
-struct nftnl_rule_list_cb_data {
-	struct nft_handle *handle;
-	struct nftnl_chain *chain;
-};
-
-static int nft_convert_policy_rule(struct nft_handle *h,
-				   struct nftnl_chain *c, struct nftnl_rule *r)
+static void nft_bridge_chain_rule_add_tail(struct nft_handle *h,
+					   struct nftnl_rule *r, struct nftnl_chain *c)
 {
 	struct nftnl_expr_iter *iter;
 	int verdict = NFT_RETURN;
 	struct nftnl_expr *expr;
 
+	if (!nft_rule_is_policy_rule(r))
+		goto out_add;
+
 	iter = nftnl_expr_iter_create(r);
 	if (iter == NULL)
-		return 0;
+		goto out_add;
 
 	expr = nftnl_expr_iter_next(iter);
-	while (expr != NULL) {
-		if (strcmp("immediate",
-			   nftnl_expr_get_str(expr, NFTNL_EXPR_NAME))) {
-			expr = nftnl_expr_iter_next(iter);
-			continue;
-		}
-		verdict = nftnl_expr_get_u32(expr, NFTNL_EXPR_IMM_VERDICT);
-		break;
-	}
+	if (!expr)
+		goto out_iter;
+
+	if (strcmp("counter", nftnl_expr_get_str(expr, NFTNL_EXPR_NAME)))
+	       goto out_iter;
+
+	expr = nftnl_expr_iter_next(iter);
+	if (strcmp("immediate", nftnl_expr_get_str(expr, NFTNL_EXPR_NAME)))
+		goto out_iter;
+
 	nftnl_expr_iter_destroy(iter);
 
+	/* rule must only consist of verdict (else its not unconditional) */
+	if (!nftnl_expr_is_set(expr, NFTNL_EXPR_IMM_VERDICT))
+		goto out_iter;
+
+	verdict = nftnl_expr_get_u32(expr, NFTNL_EXPR_IMM_VERDICT);
+
 	switch (verdict) {
 	case NF_ACCEPT:
 	case NF_DROP:
 		nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, verdict);
 		break;
+	default:
+		goto out_add;
 	}
 
-	if (batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r) < 0) {
+	if (batch_rule_add(h, NFT_COMPAT_RULE_DELETE, r) < 0)
 		printf("%s: failed to delete old policy rule\n", __func__);
-		return -1;
-	}
 
-	return 0;
+	return;
+out_iter:
+	nftnl_expr_iter_destroy(iter);
+out_add:
+	nftnl_chain_rule_add_tail(r, c);
 }
 
 static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
@@ -1400,9 +1414,8 @@ static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data)
 		return MNL_CB_OK;
 	}
 
-	if (h->family == NFPROTO_BRIDGE &&
-	    nft_rule_is_policy_rule(r))
-		nft_convert_policy_rule(h, c, r);
+	if (h->family == NFPROTO_BRIDGE)
+		nft_bridge_chain_rule_add_tail(h, r, c);
 	else
 		nftnl_chain_rule_add_tail(r, c);
 
@@ -2758,7 +2771,9 @@ static int nft_action(struct nft_handle *h, int action)
 static int ebt_add_policy_rule(struct nftnl_chain *c, void *data)
 {
 	uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
-	struct iptables_command_state cs = {};
+	struct iptables_command_state cs = {
+		.eb.bitmask = 0x2,
+	};
 	struct nftnl_udata_buf *udata;
 	struct nft_handle *h = data;
 	struct nftnl_rule *r;



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

  Powered by Linux