netfilter: nf_tables: add new nft_masq expression
The nft_masq expression is intended to perform NAT in the masquerade flavour. We decided to have the masquerade functionality in a separated expression other than nft_nat. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
		
					parent
					
						
							
								be6b635cd6
							
						
					
				
			
			
				commit
				
					
						9ba1f726be
					
				
			
		
					 11 changed files with 288 additions and 0 deletions
				
			
		
							
								
								
									
										16
									
								
								include/net/netfilter/nft_masq.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								include/net/netfilter/nft_masq.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
#ifndef _NFT_MASQ_H_
 | 
			
		||||
#define _NFT_MASQ_H_
 | 
			
		||||
 | 
			
		||||
struct nft_masq {
 | 
			
		||||
	u32	flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct nla_policy nft_masq_policy[];
 | 
			
		||||
 | 
			
		||||
int nft_masq_init(const struct nft_ctx *ctx,
 | 
			
		||||
		  const struct nft_expr *expr,
 | 
			
		||||
		  const struct nlattr * const tb[]);
 | 
			
		||||
 | 
			
		||||
int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr);
 | 
			
		||||
 | 
			
		||||
#endif /* _NFT_MASQ_H_ */
 | 
			
		||||
| 
						 | 
				
			
			@ -800,4 +800,15 @@ enum nft_nat_attributes {
 | 
			
		|||
};
 | 
			
		||||
#define NFTA_NAT_MAX		(__NFTA_NAT_MAX - 1)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum nft_masq_attributes - nf_tables masquerade expression attributes
 | 
			
		||||
 *
 | 
			
		||||
 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
 | 
			
		||||
 */
 | 
			
		||||
enum nft_masq_attributes {
 | 
			
		||||
	NFTA_MASQ_FLAGS,
 | 
			
		||||
	__NFTA_MASQ_MAX
 | 
			
		||||
};
 | 
			
		||||
#define NFTA_MASQ_MAX		(__NFTA_MASQ_MAX - 1)
 | 
			
		||||
 | 
			
		||||
#endif /* _LINUX_NF_TABLES_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -190,6 +190,12 @@ config NF_NAT_MASQUERADE_IPV4
 | 
			
		|||
	This is the kernel functionality to provide NAT in the masquerade
 | 
			
		||||
	flavour (automatic source address selection).
 | 
			
		||||
 | 
			
		||||
config NFT_MASQ_IPV4
 | 
			
		||||
	tristate "IPv4 masquerading support for nf_tables"
 | 
			
		||||
	depends on NF_TABLES_IPV4
 | 
			
		||||
	depends on NFT_MASQ
 | 
			
		||||
	select NF_NAT_MASQUERADE_IPV4
 | 
			
		||||
 | 
			
		||||
config IP_NF_TARGET_MASQUERADE
 | 
			
		||||
	tristate "MASQUERADE target support"
 | 
			
		||||
	select NF_NAT_MASQUERADE_IPV4
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@ obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
 | 
			
		|||
obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
 | 
			
		||||
obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
 | 
			
		||||
obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
 | 
			
		||||
obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o
 | 
			
		||||
obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
 | 
			
		||||
 | 
			
		||||
# generic IP tables 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										89
									
								
								net/ipv4/netfilter/nft_masq_ipv4.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								net/ipv4/netfilter/nft_masq_ipv4.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/netlink.h>
 | 
			
		||||
#include <linux/netfilter.h>
 | 
			
		||||
#include <linux/netfilter/nf_tables.h>
 | 
			
		||||
#include <net/netfilter/nf_tables.h>
 | 
			
		||||
#include <net/netfilter/nft_masq.h>
 | 
			
		||||
#include <net/netfilter/ipv4/nf_nat_masquerade.h>
 | 
			
		||||
 | 
			
		||||
static void nft_masq_ipv4_eval(const struct nft_expr *expr,
 | 
			
		||||
			       struct nft_data data[NFT_REG_MAX + 1],
 | 
			
		||||
			       const struct nft_pktinfo *pkt)
 | 
			
		||||
{
 | 
			
		||||
	struct nft_masq *priv = nft_expr_priv(expr);
 | 
			
		||||
	struct nf_nat_range range;
 | 
			
		||||
	unsigned int verdict;
 | 
			
		||||
 | 
			
		||||
	range.flags = priv->flags;
 | 
			
		||||
 | 
			
		||||
	verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum,
 | 
			
		||||
					 &range, pkt->out);
 | 
			
		||||
 | 
			
		||||
	data[NFT_REG_VERDICT].verdict = verdict;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nft_masq_ipv4_init(const struct nft_ctx *ctx,
 | 
			
		||||
			      const struct nft_expr *expr,
 | 
			
		||||
			      const struct nlattr * const tb[])
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = nft_masq_init(ctx, expr, tb);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	nf_nat_masquerade_ipv4_register_notifier();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nft_masq_ipv4_destroy(const struct nft_ctx *ctx,
 | 
			
		||||
				  const struct nft_expr *expr)
 | 
			
		||||
{
 | 
			
		||||
	nf_nat_masquerade_ipv4_unregister_notifier();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct nft_expr_type nft_masq_ipv4_type;
 | 
			
		||||
static const struct nft_expr_ops nft_masq_ipv4_ops = {
 | 
			
		||||
	.type		= &nft_masq_ipv4_type,
 | 
			
		||||
	.size		= NFT_EXPR_SIZE(sizeof(struct nft_masq)),
 | 
			
		||||
	.eval		= nft_masq_ipv4_eval,
 | 
			
		||||
	.init		= nft_masq_ipv4_init,
 | 
			
		||||
	.destroy	= nft_masq_ipv4_destroy,
 | 
			
		||||
	.dump		= nft_masq_dump,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
 | 
			
		||||
	.family		= NFPROTO_IPV4,
 | 
			
		||||
	.name		= "masq",
 | 
			
		||||
	.ops		= &nft_masq_ipv4_ops,
 | 
			
		||||
	.policy		= nft_masq_policy,
 | 
			
		||||
	.maxattr	= NFTA_MASQ_MAX,
 | 
			
		||||
	.owner		= THIS_MODULE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int __init nft_masq_ipv4_module_init(void)
 | 
			
		||||
{
 | 
			
		||||
	return nft_register_expr(&nft_masq_ipv4_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __exit nft_masq_ipv4_module_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	nft_unregister_expr(&nft_masq_ipv4_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(nft_masq_ipv4_module_init);
 | 
			
		||||
module_exit(nft_masq_ipv4_module_exit);
 | 
			
		||||
 | 
			
		||||
MODULE_LICENSE("GPL");
 | 
			
		||||
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
 | 
			
		||||
MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "masq");
 | 
			
		||||
| 
						 | 
				
			
			@ -252,6 +252,12 @@ config NF_NAT_MASQUERADE_IPV6
 | 
			
		|||
	 This is the kernel functionality to provide NAT in the masquerade
 | 
			
		||||
	 flavour (automatic source address selection) for IPv6.
 | 
			
		||||
 | 
			
		||||
config NFT_MASQ_IPV6
 | 
			
		||||
	tristate "IPv6 masquerade support for nf_tables"
 | 
			
		||||
	depends on NF_TABLES_IPV6
 | 
			
		||||
	depends on NFT_MASQ
 | 
			
		||||
	select NF_NAT_MASQUERADE_IPV6
 | 
			
		||||
 | 
			
		||||
config IP6_NF_TARGET_MASQUERADE
 | 
			
		||||
	tristate "MASQUERADE target support"
 | 
			
		||||
	select NF_NAT_MASQUERADE_IPV6
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@ obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o
 | 
			
		|||
obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
 | 
			
		||||
obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o
 | 
			
		||||
obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
 | 
			
		||||
obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o
 | 
			
		||||
 | 
			
		||||
# matches
 | 
			
		||||
obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										89
									
								
								net/ipv6/netfilter/nft_masq_ipv6.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								net/ipv6/netfilter/nft_masq_ipv6.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/netlink.h>
 | 
			
		||||
#include <linux/netfilter.h>
 | 
			
		||||
#include <linux/netfilter/nf_tables.h>
 | 
			
		||||
#include <net/netfilter/nf_tables.h>
 | 
			
		||||
#include <net/netfilter/nf_nat.h>
 | 
			
		||||
#include <net/netfilter/nft_masq.h>
 | 
			
		||||
#include <net/netfilter/ipv6/nf_nat_masquerade.h>
 | 
			
		||||
 | 
			
		||||
static void nft_masq_ipv6_eval(const struct nft_expr *expr,
 | 
			
		||||
			       struct nft_data data[NFT_REG_MAX + 1],
 | 
			
		||||
			       const struct nft_pktinfo *pkt)
 | 
			
		||||
{
 | 
			
		||||
	struct nft_masq *priv = nft_expr_priv(expr);
 | 
			
		||||
	struct nf_nat_range range;
 | 
			
		||||
	unsigned int verdict;
 | 
			
		||||
 | 
			
		||||
	range.flags = priv->flags;
 | 
			
		||||
 | 
			
		||||
	verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
 | 
			
		||||
 | 
			
		||||
	data[NFT_REG_VERDICT].verdict = verdict;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nft_masq_ipv6_init(const struct nft_ctx *ctx,
 | 
			
		||||
			      const struct nft_expr *expr,
 | 
			
		||||
			      const struct nlattr * const tb[])
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = nft_masq_init(ctx, expr, tb);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	nf_nat_masquerade_ipv6_register_notifier();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nft_masq_ipv6_destroy(const struct nft_ctx *ctx,
 | 
			
		||||
				  const struct nft_expr *expr)
 | 
			
		||||
{
 | 
			
		||||
	nf_nat_masquerade_ipv6_unregister_notifier();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct nft_expr_type nft_masq_ipv6_type;
 | 
			
		||||
static const struct nft_expr_ops nft_masq_ipv6_ops = {
 | 
			
		||||
	.type		= &nft_masq_ipv6_type,
 | 
			
		||||
	.size		= NFT_EXPR_SIZE(sizeof(struct nft_masq)),
 | 
			
		||||
	.eval		= nft_masq_ipv6_eval,
 | 
			
		||||
	.init		= nft_masq_ipv6_init,
 | 
			
		||||
	.destroy	= nft_masq_ipv6_destroy,
 | 
			
		||||
	.dump		= nft_masq_dump,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
 | 
			
		||||
	.family		= NFPROTO_IPV6,
 | 
			
		||||
	.name		= "masq",
 | 
			
		||||
	.ops		= &nft_masq_ipv6_ops,
 | 
			
		||||
	.policy		= nft_masq_policy,
 | 
			
		||||
	.maxattr	= NFTA_MASQ_MAX,
 | 
			
		||||
	.owner		= THIS_MODULE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int __init nft_masq_ipv6_module_init(void)
 | 
			
		||||
{
 | 
			
		||||
	return nft_register_expr(&nft_masq_ipv6_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __exit nft_masq_ipv6_module_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	nft_unregister_expr(&nft_masq_ipv6_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(nft_masq_ipv6_module_init);
 | 
			
		||||
module_exit(nft_masq_ipv6_module_exit);
 | 
			
		||||
 | 
			
		||||
MODULE_LICENSE("GPL");
 | 
			
		||||
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
 | 
			
		||||
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "masq");
 | 
			
		||||
| 
						 | 
				
			
			@ -496,6 +496,15 @@ config NFT_LIMIT
 | 
			
		|||
	  This option adds the "limit" expression that you can use to
 | 
			
		||||
	  ratelimit rule matchings.
 | 
			
		||||
 | 
			
		||||
config NFT_MASQ
 | 
			
		||||
	depends on NF_TABLES
 | 
			
		||||
	depends on NF_CONNTRACK
 | 
			
		||||
	depends on NF_NAT
 | 
			
		||||
	tristate "Netfilter nf_tables masquerade support"
 | 
			
		||||
	help
 | 
			
		||||
	  This option adds the "masquerade" expression that you can use
 | 
			
		||||
	  to perform NAT in the masquerade flavour.
 | 
			
		||||
 | 
			
		||||
config NFT_NAT
 | 
			
		||||
	depends on NF_TABLES
 | 
			
		||||
	depends on NF_CONNTRACK
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,6 +87,7 @@ obj-$(CONFIG_NFT_RBTREE)	+= nft_rbtree.o
 | 
			
		|||
obj-$(CONFIG_NFT_HASH)		+= nft_hash.o
 | 
			
		||||
obj-$(CONFIG_NFT_COUNTER)	+= nft_counter.o
 | 
			
		||||
obj-$(CONFIG_NFT_LOG)		+= nft_log.o
 | 
			
		||||
obj-$(CONFIG_NFT_MASQ)		+= nft_masq.o
 | 
			
		||||
 | 
			
		||||
# generic X tables 
 | 
			
		||||
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										59
									
								
								net/netfilter/nft_masq.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								net/netfilter/nft_masq.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License version 2 as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/netlink.h>
 | 
			
		||||
#include <linux/netfilter.h>
 | 
			
		||||
#include <linux/netfilter/nf_tables.h>
 | 
			
		||||
#include <net/netfilter/nf_tables.h>
 | 
			
		||||
#include <net/netfilter/nf_nat.h>
 | 
			
		||||
#include <net/netfilter/nft_masq.h>
 | 
			
		||||
 | 
			
		||||
const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
 | 
			
		||||
	[NFTA_MASQ_FLAGS]	= { .type = NLA_U32 },
 | 
			
		||||
};
 | 
			
		||||
EXPORT_SYMBOL_GPL(nft_masq_policy);
 | 
			
		||||
 | 
			
		||||
int nft_masq_init(const struct nft_ctx *ctx,
 | 
			
		||||
		  const struct nft_expr *expr,
 | 
			
		||||
		  const struct nlattr * const tb[])
 | 
			
		||||
{
 | 
			
		||||
	struct nft_masq *priv = nft_expr_priv(expr);
 | 
			
		||||
 | 
			
		||||
	if (tb[NFTA_MASQ_FLAGS] == NULL)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
 | 
			
		||||
	if (priv->flags & ~NF_NAT_RANGE_MASK)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(nft_masq_init);
 | 
			
		||||
 | 
			
		||||
int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr)
 | 
			
		||||
{
 | 
			
		||||
	const struct nft_masq *priv = nft_expr_priv(expr);
 | 
			
		||||
 | 
			
		||||
	if (priv->flags == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
 | 
			
		||||
		goto nla_put_failure;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
nla_put_failure:
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(nft_masq_dump);
 | 
			
		||||
 | 
			
		||||
MODULE_LICENSE("GPL");
 | 
			
		||||
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue