> -----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