RE: [PATCH iptables 2/2] ebtables-nft: add broute table emulation

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

 



> -----Original Message-----
> From: Florian Westphal <fw@xxxxxxxxx>
> Sent: Tuesday, 4 April 2023 11:46
> To: netfilter-devel@xxxxxxxxxxxxxxx
> Cc: Florian Westphal <fw@xxxxxxxxx>
> Subject: [PATCH iptables 2/2] ebtables-nft: add broute table emulation
> 
> Use new 'meta broute set 1' to emulate -t broute.  If '-t broute' is given,
> automatically translate -j DROP to 'meta broute set 1 accept' internally.
> 
> Reverse translation zaps the broute and pretends verdict was DROP.
> 
> Note that BROUTING is internally handled via PREROUTING, i.e. 'redirect'
> and 'nat' targets are not available, they will need to be emulated via nft
> expressions.

Thank you so much for fixing this, I attempted to update ebtables-nft for broute support but couldn’t understand all the details.
Does this close https://bugzilla.netfilter.org/show_bug.cgi?id=1316?

> 
> Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
> ---
>  iptables/ebtables-nft.8 | 42 +++++++++++++++++++++++++++--------------
>  iptables/nft-bridge.c   | 36 +++++++++++++++++++++++++++++++++++
>  iptables/nft-shared.c   | 39 +++++++++++++++++++++++++++-----------
>  iptables/nft-shared.h   |  3 +++
>  iptables/nft.c          | 13 +++++++++++++
>  iptables/nft.h          |  3 ++-
>  6 files changed, 110 insertions(+), 26 deletions(-)
> 
> diff --git a/iptables/ebtables-nft.8 b/iptables/ebtables-nft.8 index
> d75aae240bc0..d639bdf5e292 100644
> --- a/iptables/ebtables-nft.8
> +++ b/iptables/ebtables-nft.8
> @@ -55,7 +55,7 @@ It is analogous to the  application, but less complicated,
> due to the fact that the Ethernet protocol  is much simpler than the IP protocol.
>  .SS CHAINS
> -There are two ebtables tables with built-in chains in the
> +There are three ebtables tables with built-in chains in the
>  Linux kernel. These tables are used to divide functionality into  different sets of
> rules. Each set of rules is called a chain.
>  Each chain is an ordered list of rules that can match Ethernet frames. If a @@ -
> 81,7 +81,10 @@ an 'extension' (see below) or a jump to a user-defined chain.
>  .B ACCEPT
>  means to let the frame through.
>  .B DROP
> -means the frame has to be dropped.
> +means the frame has to be dropped. In the .BR BROUTING " chain however,
> +the " ACCEPT " and " DROP " target have different"
> +meanings (see the info provided for the .BR -t " option)."
>  .B CONTINUE
>  means the next rule has to be checked. This can be handy, f.e., to know how
> many  frames pass a certain point in the chain, to log those frames or to apply
> multiple @@ -93,17 +96,13 @@ For the extension targets please refer to the
> .B "TARGET EXTENSIONS"
>  section of this man page.
>  .SS TABLES
> -As stated earlier, there are two ebtables tables in the Linux -kernel.  The table
> names are -.BR filter " and " nat .
> -Of these two tables,
> +As stated earlier, the table names are
> +.BR filter ", " nat " and " broute .
> +Of these tables,
>  the filter table is the default table that the command operates on.
> -If you are working with the filter table, then you can drop the '-t filter'
> -argument to the ebtables command.  However, you will need to provide -the -t
> argument for -.B nat -table.  Moreover, the -t argument must be the -first
> argument on the ebtables command line, if used.
> +If you are working with the a table other than filter, you will need to
> +provide the -t argument.  Moreover, the -t argument must be the first
> +argument on the ebtables command line, if used.
>  .TP
>  .B "-t, --table"
>  .br
> @@ -131,6 +130,23 @@ iptables world to ebtables it is easier to have the
> same names. Note that you  can change the name  .BR "" ( -E )  if you don't like
> the default.
> +.br
> +.br
> +.B broute
> +is used to make a brouter, it has one built-in chain:
> +.BR BROUTING .
> +The targets
> +.BR DROP " and " ACCEPT
> +have a special meaning in the broute table (these names are used for
> +compatibility reasons with ebtables-legacy).
> +.B DROP
> +actually means the frame has to be routed, while .B ACCEPT means the
> +frame has to be bridged. The .B BROUTING chain is traversed very early.
> +Normally those frames
> +would be bridged, but you can decide otherwise here.
>  .SH EBTABLES COMMAND LINE ARGUMENTS
>  After the initial ebtables '-t table' command line argument, the remaining
> arguments can be divided into several groups.  These groups @@ -1059,8
> +1075,6 @@ arp message and the hardware address length in the arp header
> is 6 bytes.
>  .BR "" "See " http://netfilter.org/mailinglists.html
>  .SH BUGS
>  The version of ebtables this man page ships with does not support the -.B
> broute -table. Also there is no support for  .B string  match. Further, support for
> atomic-options  .RB ( --atomic-file ", " --atomic-init ", " --atomic-save ", " --
> atomic-commit ) diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c index
> b9983b203f6d..22860d6b91a6 100644
> --- a/iptables/nft-bridge.c
> +++ b/iptables/nft-bridge.c
> @@ -95,8 +95,44 @@ static void add_logical_outiface(struct nft_handle *h,
> struct nftnl_rule *r,
>  		add_cmp_ptr(r, op, iface, iface_len + 1, reg);  }
> 
> +static int add_meta_broute(struct nftnl_rule *r) {
> +	struct nftnl_expr *expr;
> +
> +	expr = nftnl_expr_alloc("immediate");
> +	if (expr == NULL)
> +		return -1;
> +
> +	nftnl_expr_set_u32(expr, NFTNL_EXPR_IMM_DREG, NFT_REG32_01);
> +	nftnl_expr_set_u8(expr, NFTNL_EXPR_IMM_DATA, 1);
> +	nftnl_rule_add_expr(r, expr);
> +
> +	expr = nftnl_expr_alloc("meta");
> +	if (expr == NULL)
> +		return -1;
> +	nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY,
> NFT_META_BRI_BROUTE);
> +	nftnl_expr_set_u32(expr, NFTNL_EXPR_META_SREG, NFT_REG32_01);
> +
> +	nftnl_rule_add_expr(r, expr);
> +	return 0;
> +}
> +
>  static int _add_action(struct nftnl_rule *r, struct iptables_command_state *cs)
> {
> +	const char *table = nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
> +
> +	if (cs->target &&
> +	    table && strcmp(table, "broute") == 0) {
> +		if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0) {
> +			int ret = add_meta_broute(r);
> +
> +			if (ret)
> +				return ret;
> +
> +			cs->jumpto = "ACCEPT";
> +		}
> +	}
> +
>  	return add_action(r, cs, false);
>  }
> 
> diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index
> 1b22eb7afd30..c19d78e46972 100644
> --- a/iptables/nft-shared.c
> +++ b/iptables/nft-shared.c
> @@ -511,8 +511,24 @@ void get_cmp_data(struct nftnl_expr *e, void *data,
> size_t dlen, bool *inv)
>  	*inv = (op == NFT_CMP_NEQ);
>  }
> 
> -static void nft_meta_set_to_target(struct nft_xt_ctx *ctx,
> -				   struct nftnl_expr *e)
> +static bool nft_parse_meta_set_common(struct nft_xt_ctx* ctx,
> +				      struct nft_xt_ctx_reg *sreg)
> +{
> +	if ((sreg->type != NFT_XT_REG_IMMEDIATE)) {
> +		ctx->errmsg = "meta sreg is not an immediate";
> +		return false;
> +	}
> +
> +	if (sreg->immediate.data[0] == 0) {
> +		ctx->errmsg = "meta sreg immediate is 0";
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +static void nft_parse_meta_set(struct nft_xt_ctx *ctx,
> +			       struct nftnl_expr *e)
>  {
>  	struct xtables_target *target;
>  	struct nft_xt_ctx_reg *sreg;
> @@ -528,18 +544,17 @@ static void nft_meta_set_to_target(struct nft_xt_ctx
> *ctx,
> 
>  	switch (nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY)) {
>  	case NFT_META_NFTRACE:
> -		if ((sreg->type != NFT_XT_REG_IMMEDIATE)) {
> -			ctx->errmsg = "meta nftrace but reg not immediate";
> +		if (!nft_parse_meta_set_common(ctx, sreg))
>  			return;
> -		}
> -
> -		if (sreg->immediate.data[0] == 0) {
> -			ctx->errmsg = "trace is cleared";
> -			return;
> -		}
> 
>  		targname = "TRACE";
>  		break;
> +	case NFT_META_BRI_BROUTE:
> +		if (!nft_parse_meta_set_common(ctx, sreg))
> +			return;
> +
> +		ctx->cs->jumpto = "DROP";
> +		return;
>  	default:
>  		ctx->errmsg = "meta sreg key not supported";
>  		return;
> @@ -568,7 +583,7 @@ static void nft_parse_meta(struct nft_xt_ctx *ctx,
> struct nftnl_expr *e)
>          struct nft_xt_ctx_reg *reg;
> 
>  	if (nftnl_expr_is_set(e, NFTNL_EXPR_META_SREG)) {
> -		nft_meta_set_to_target(ctx, e);
> +		nft_parse_meta_set(ctx, e);
>  		return;
>  	}
> 
> @@ -1145,6 +1160,8 @@ static void nft_parse_immediate(struct nft_xt_ctx
> *ctx, struct nftnl_expr *e)
>  	/* Standard target? */
>  	switch(verdict) {
>  	case NF_ACCEPT:
> +		if (cs->jumpto && strcmp(ctx->table, "broute") == 0)
> +			break;
>  		cs->jumpto = "ACCEPT";
>  		break;
>  	case NF_DROP:
> diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index
> b8bc1a6ce2e9..2c4c0d90cd07 100644
> --- a/iptables/nft-shared.h
> +++ b/iptables/nft-shared.h
> @@ -61,6 +61,9 @@ struct nft_xt_ctx_reg {
>  		struct {
>  			uint32_t key;
>  		} meta_dreg;
> +		struct {
> +			uint32_t key;
> +		} meta_sreg;
>  	};
> 
>  	struct {
> diff --git a/iptables/nft.c b/iptables/nft.c index 5ef5335a24c1..1cb104e75ccc
> 100644
> --- a/iptables/nft.c
> +++ b/iptables/nft.c
> @@ -643,6 +643,19 @@ static const struct builtin_table
> xtables_bridge[NFT_TABLE_MAX] = {
>  			},
>  		},
>  	},
> +	[NFT_TABLE_BROUTE] = {
> +		.name = "broute",
> +		.type	= NFT_TABLE_BROUTE,
> +		.chains = {
> +			{
> +				.name   = "BROUTING",
> +				.type   = "filter",
> +				.prio   = NF_BR_PRI_FIRST,
> +				.hook   = NF_BR_PRE_ROUTING,
> +			},
> +		},
> +	},
> +
>  };
> 
>  static int nft_table_builtin_add(struct nft_handle *h, diff --git a/iptables/nft.h
> b/iptables/nft.h index 56005863ed4c..1d18982dc8cf 100644
> --- a/iptables/nft.h
> +++ b/iptables/nft.h
> @@ -14,8 +14,9 @@ enum nft_table_type {
>  	NFT_TABLE_RAW,
>  	NFT_TABLE_FILTER,
>  	NFT_TABLE_NAT,
> +	NFT_TABLE_BROUTE,
>  };
> -#define NFT_TABLE_MAX	(NFT_TABLE_NAT + 1)
> +#define NFT_TABLE_MAX	(NFT_TABLE_BROUTE + 1)
> 
>  struct builtin_chain {
>  	const char *name;
> --
> 2.39.2





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

  Powered by Linux