Re: [PATCH v2 nf-next] netfilter: nft: add support for native socket matching

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

 



On Wed, May 30, 2018 at 12:13:22PM +0200, Máté Eckl wrote:
> Now it can only match the transparent flag of an ip/ipv6 socket.
> 
> Signed-off-by: Máté Eckl <ecklm94@xxxxxxxxx>
> ---
>  include/uapi/linux/netfilter/nf_tables.h |  28 +++++
>  net/netfilter/Kconfig                    |   9 ++
>  net/netfilter/Makefile                   |   1 +
>  net/netfilter/nft_socket.c               | 143 +++++++++++++++++++++++
>  4 files changed, 181 insertions(+)
>  create mode 100644 net/netfilter/nft_socket.c
> 
> diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
> index 9c71f024f9cc..96ab31539bf6 100644
> --- a/include/uapi/linux/netfilter/nf_tables.h
> +++ b/include/uapi/linux/netfilter/nf_tables.h
> @@ -904,6 +904,34 @@ enum nft_rt_attributes {
>  };
>  #define NFTA_RT_MAX		(__NFTA_RT_MAX - 1)
>  
> +/**
> + * enum nft_socket_attributes - nf_tables socket expression netlink attributes
> + *
> + * @NFTA_SOCKET_KEY: socket key to match
> + * @NFTA_SOCKET_DREG: destination register
> + */
> +enum nft_socket_attributes {
> +	NFTA_SOCKET_UNSPEC,
> +
> +	NFTA_SOCKET_KEY,
> +	NFTA_SOCKET_DREG,
> +
> +	__NFTA_SOCKET_MAX
> +};
> +#define NFTA_SOCKET_MAX		(__NFTA_SOCKET_MAX - 1)
> +
> +/*
> + * enum nft_socket_keys - nf_tables socket expression keys
> + *
> + * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option_
> + */
> +enum nft_socket_keys {
> +	NFT_SOCKET_TRANSPARENT,
> +
> +	__NFT_SOCKET_MAX
> +};
> +#define NFT_SOCKET_MAX	(__NFT_SOCKET_MAX - 1)
> +
>  /**
>   * enum nft_ct_keys - nf_tables ct expression keys
>   *
> diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
> index 3ec8886850b2..276e1e32f44e 100644
> --- a/net/netfilter/Kconfig
> +++ b/net/netfilter/Kconfig
> @@ -613,6 +613,15 @@ config NFT_FIB_INET
>  	  The lookup will be delegated to the IPv4 or IPv6 FIB depending
>  	  on the protocol of the packet.
>  
> +config NFT_SOCKET
> +	tristate "Netfilter nf_tables socket match support"
> +	depends on IPV6 || IPV6=n
> +	select NF_SOCKET_IPV4
> +	select NF_SOCKET_IPV6 if IPV6
> +	help
> +	  This option allows matching for the presence or absence of a
> +	  corresponding socket and its attributes.
> +
>  if NF_TABLES_NETDEV
>  
>  config NF_DUP_NETDEV
> diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
> index 9b3434360d49..eec169555731 100644
> --- a/net/netfilter/Makefile
> +++ b/net/netfilter/Makefile
> @@ -102,6 +102,7 @@ obj-$(CONFIG_NFT_FIB)		+= nft_fib.o
>  obj-$(CONFIG_NFT_FIB_INET)	+= nft_fib_inet.o
>  obj-$(CONFIG_NFT_FIB_NETDEV)	+= nft_fib_netdev.o
>  obj-$(CONFIG_NF_OSF)		+= nf_osf.o
> +obj-$(CONFIG_NFT_SOCKET)	+= nft_socket.o
>  
>  # nf_tables netdev
>  obj-$(CONFIG_NFT_DUP_NETDEV)	+= nft_dup_netdev.o
> diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
> new file mode 100644
> index 000000000000..dd389b37334a
> --- /dev/null
> +++ b/net/netfilter/nft_socket.c
> @@ -0,0 +1,143 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/module.h>
> +#include <linux/netfilter/nf_tables.h>
> +#include <net/netfilter/nf_tables.h>
> +#include <net/netfilter/nf_tables_core.h>
> +#include <net/netfilter/nf_socket.h>
> +#include <net/inet_sock.h>
> +
> +struct nft_socket {
> +	enum nft_socket_keys	key:8;
> +	union {
> +		enum nft_registers	dreg:8;
> +	};
> +};
> +
> +static void nft_socket_eval(const struct nft_expr *expr,
> +			    struct nft_regs *regs,
> +			    const struct nft_pktinfo *pkt)
> +{
> +	const struct nft_socket *priv = nft_expr_priv(expr);
> +	struct sk_buff *skb = pkt->skb;
> +	struct sock *sk = skb->sk;
> +	u32 *dest = &regs->data[priv->dreg];
> +
> +	if (!sk)
> +		switch(nft_pf(pkt)) {
> +		case NFPROTO_IPV4:
> +			sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, nft_in(pkt));
> +			break;
> +#if IS_ENABLED(CONFIG_NF_SOCKET_IPV6)
> +		case NFPROTO_IPV6:
> +			sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, nft_in(pkt));
> +			break;
> +#endif
> +		default:
> +			WARN_ON_ONCE(1);
> +			regs->verdict.code = NFT_BREAK;
> +			return;
> +		}
> +
> +	if(!sk) {
> +		nft_reg_store8(dest, 0);
> +		return;
> +	}
> +
> +	skb->sk = sk; // So that subsequent socket matching not to require other lookups

Remove this comment.

> +
> +	switch(priv->key) {
> +	case NFT_SOCKET_TRANSPARENT:
> +		nft_reg_store8(dest, nf_sk_is_transparent(sk));
> +		break;
> +	default:
> +		WARN_ON(1);
> +		regs->verdict.code = NFT_BREAK;
> +	}
> +}
> +
> +static const struct nla_policy nft_socket_policy[NFTA_SOCKET_MAX + 1] = {
> +	[NFTA_SOCKET_KEY]		= { .type = NLA_U32 },
> +	[NFTA_SOCKET_DREG]		= { .type = NLA_U32 },
> +};
> +
> +static int nft_socket_init(const struct nft_ctx *ctx,
> +			   const struct nft_expr *expr,
> +			   const struct nlattr * const tb[])
> +{
> +	struct nft_socket *priv = nft_expr_priv(expr);
> +	unsigned int len;
> +
> +	if (!tb[NFTA_SOCKET_DREG] || !tb[NFTA_SOCKET_KEY])
> +		return -EINVAL;
> +
> +	switch(ctx->family) {
> +	case NFPROTO_IPV4:
> +#if IS_ENABLED(CONFIG_NF_SOCKET_IPV6)
> +	case NFPROTO_IPV6:
> +#endif
> +	case NFPROTO_INET:
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	priv->key = ntohl(nla_get_u32(tb[NFTA_SOCKET_KEY]));
> +	switch(priv->key) {
> +	case NFT_SOCKET_TRANSPARENT:
> +		len = sizeof(u8);
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	priv->dreg = nft_parse_register(tb[NFTA_SOCKET_DREG]);
> +	return nft_validate_register_store(ctx, priv->dreg, NULL,
> +					   NFT_DATA_VALUE, len);
> +}
> +
> +static int nft_socket_dump(struct sk_buff *skb,
> +			   const struct nft_expr *expr)
> +{
> +	const struct nft_socket *priv = nft_expr_priv(expr);
> +
> +	if (nla_put_u32(skb, NFTA_SOCKET_KEY, htonl(priv->key)))
> +		return -1;
> +	if (nft_dump_register(skb, NFTA_SOCKET_DREG, priv->dreg))
> +		return -1;
> +	return 0;
> +}
> +
> +struct nft_expr_type nft_socket_type;
   ^
static missing here.

> +static const struct nft_expr_ops nft_socket_ops = {
> +	.type		= &nft_socket_type,
> +	.size		= NFT_EXPR_SIZE(sizeof(struct nft_socket)),
> +	.eval		= nft_socket_eval,
> +	.init		= nft_socket_init,
> +	.dump		= nft_socket_dump,
> +};
> +
> +struct nft_expr_type nft_socket_type __read_mostly = {
   ^
static missing here.

Thanks!

> +	.name		= "socket",
> +	.ops		= &nft_socket_ops,
> +	.policy		= nft_socket_policy,
> +	.maxattr	= NFTA_SOCKET_MAX,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static int __init nft_socket_module_init(void)
> +{
> +	return nft_register_expr(&nft_socket_type);
> +}
> +
> +static void __exit nft_socket_module_exit(void)
> +{
> +	nft_unregister_expr(&nft_socket_type);
> +}
> +
> +module_init(nft_socket_module_init);
> +module_exit(nft_socket_module_exit);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Máté Eckl");
> +MODULE_DESCRIPTION("nf_tables socket match module");
> -- 
> ecklm
> 
> --
> 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
--
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



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

  Powered by Linux