NFT_META_IBRIFNAME to get packet input bridge interface name NFT_META_OBRIFNAME to get packet output bridge interface name Suggested-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@xxxxxxxxxxxxxxx> --- Hi Pablo, Does that design sounds proper? I added the nft type right away in nft_meta.c to reuse as much as possible, only the evaluation is a bit specific. I haven't tested yet, I will do the support of this meta key for nft tool accordingly. Tomasz include/uapi/linux/netfilter/nf_tables.h | 4 ++ net/netfilter/nft_meta.c | 79 +++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 83c985a..e3c98f9 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -533,6 +533,8 @@ enum nft_exthdr_attributes { * @NFT_META_SECMARK: packet secmark (skb->secmark) * @NFT_META_NFPROTO: netfilter protocol * @NFT_META_L4PROTO: layer 4 protocol number + * @NFT_META_IBRIFNAME: packet input bridge interface name + * @NFT_META_OBRIFNAME: packet output bridge interface name */ enum nft_meta_keys { NFT_META_LEN, @@ -552,6 +554,8 @@ enum nft_meta_keys { NFT_META_SECMARK, NFT_META_NFPROTO, NFT_META_L4PROTO, + NFT_META_IBRIFNAME, + NFT_META_OBRIFNAME, }; /** diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index e8254ad..60a7d63 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -18,6 +18,9 @@ #include <net/sock.h> #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ #include <net/netfilter/nf_tables.h> +#ifdef CONFIG_NF_TABLES_BRIDGE +#include "../br_private.h" +#endif struct nft_meta { enum nft_meta_keys key:8; @@ -141,6 +144,40 @@ err: data[NFT_REG_VERDICT].verdict = NFT_BREAK; } +#ifdef CONFIG_NF_TABLES_BRIDGE +static void nft_meta_bridge_get_eval(const struct nft_expr *expr, + struct nft_data data[NFT_REG_MAX + 1], + const struct nft_pktinfo *pkt) +{ + const struct net_device *in = pkt->in, *out = pkt->out; + struct nft_data *dest = &data[priv->dreg]; + const struct net_bridge_port *p; + + if (pkt->ops->pf != NFPROTO_BRIDGE) + goto out; + + switch (priv->key) { + case NFT_META_IBRIFNAME: + if (in == NULL || (p = br_port_get_rcu(in)) == NULL) + goto err; + break; + case NFT_META_OBRIFNAME: + if (out == NULL || (p = br_port_get_rcu(out)) == NULL) + goto err; + break; + default: + goto out; + } + + strncpy((char *)dest->data, p->br->dev->name, sizeof(dest->data)); + return; +out: + return nft_meta_get_eval(expr, data, pkt); +err: + data[NFT_REG_VERDICT].verdict = NFT_BREAK; +} +#endif + static void nft_meta_set_eval(const struct nft_expr *expr, struct nft_data data[NFT_REG_MAX + 1], const struct nft_pktinfo *pkt) @@ -205,6 +242,10 @@ static int nft_meta_init_validate_get(uint32_t key) #ifdef CONFIG_NETWORK_SECMARK case NFT_META_SECMARK: #endif +#ifdef CONFIG_NF_TABLES_BRIDGE + case NFT_META_IBRIFNAME: + case NFT_META_OBRIFNAME: +#endif return 0; default: return -EOPNOTSUPP; @@ -294,6 +335,17 @@ static const struct nft_expr_ops nft_meta_set_ops = { .dump = nft_meta_set_dump, }; +#ifdef CONFIG_NF_TABLES_BRIDGE +static struct nft_expr_type nft_meta_bridge_type; +static const struct nft_expr_ops nft_meta_bridge_get_ops = { + .type = &nft_meta_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)), + .eval = nft_meta_bridge_get_eval, + .init = nft_meta_init, + .dump = nft_meta_get_dump, +}; +#endif + static const struct nft_expr_ops * nft_meta_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) @@ -304,8 +356,13 @@ nft_meta_select_ops(const struct nft_ctx *ctx, if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG]) return ERR_PTR(-EINVAL); - if (tb[NFTA_META_DREG]) + if (tb[NFTA_META_DREG]) { +#ifdef CONFIG_NF_TABLES_BRIDGE + if (ctx->aif->family == NFPROTO_BRIDGE) + return &nft_meta_bridge_get_ops; +#endif return &nft_meta_get_ops; + } if (tb[NFTA_META_SREG]) return &nft_meta_set_ops; @@ -321,9 +378,27 @@ static struct nft_expr_type nft_meta_type __read_mostly = { .owner = THIS_MODULE, }; +#ifdef CONFIG_NF_TABLES_BRIDGE +static struct nft_expr_type nft_meta_bridge_type __read_mostly = { + .family = NFPROTO_BRIDGE, + .name = "meta", + .select_ops = &nft_meta_select_ops, + .policy = nft_meta_policy, + .maxattr = NFTA_META_MAX, + .owner = THIS_MODULE, +}; +#endif + static int __init nft_meta_module_init(void) { - return nft_register_expr(&nft_meta_type); + int ret; + + ret = nft_register_expr(&nft_meta_type); +#ifdef CONFIG_NF_TABLES_BRIDGE + if (ret == 0) + ret = nft_register_expr(&nft_meta_bridge_type); +#endif + return ret; } static void __exit nft_meta_module_exit(void) -- 1.8.3.2 -- 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