netfilter: nf_tables: nat: merge nft_redir protocol specific modules

before:
 text	   data	    bss	    dec	    hex	filename
 990	    832	      0	   1822	    71e nft_redir.ko
 697	    896	      0	   1593	    639 nft_redir_ipv4.ko
 713	    896	      0	   1609	    649	nft_redir_ipv6.ko

after:
 text	   data	    bss	    dec	    hex	filename
 1910	    960	      0	   2870	    b36	nft_redir.ko

size is reduced, all helpers from nft_redir.ko can be made static.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal 2019-02-28 12:02:50 +01:00 committed by Pablo Neira Ayuso
parent 20fdaf6e1e
commit c78efc99c7
9 changed files with 143 additions and 217 deletions

View file

@ -1,22 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NFT_REDIR_H_
#define _NFT_REDIR_H_
struct nft_redir {
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
u16 flags;
};
extern const struct nla_policy nft_redir_policy[];
int nft_redir_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[]);
int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr);
int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data);
#endif /* _NFT_REDIR_H_ */

View file

@ -115,14 +115,6 @@ config NFT_MASQ_IPV4
This is the expression that provides IPv4 masquerading support for This is the expression that provides IPv4 masquerading support for
nf_tables. nf_tables.
config NFT_REDIR_IPV4
tristate "IPv4 redirect support for nf_tables"
depends on NF_TABLES_IPV4
depends on NFT_REDIR
select NF_NAT_REDIRECT
help
This is the expression that provides IPv4 redirect support for
nf_tables.
endif # NF_TABLES endif # NF_TABLES
config NF_NAT_SNMP_BASIC config NF_NAT_SNMP_BASIC

View file

@ -29,7 +29,6 @@ obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
obj-$(CONFIG_NFT_FIB_IPV4) += nft_fib_ipv4.o obj-$(CONFIG_NFT_FIB_IPV4) += nft_fib_ipv4.o
obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o
obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redir_ipv4.o
obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o obj-$(CONFIG_NFT_DUP_IPV4) += nft_dup_ipv4.o
# flow table support # flow table support

View file

@ -1,82 +0,0 @@
/*
* Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* 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/nf_nat_redirect.h>
#include <net/netfilter/nft_redir.h>
static void nft_redir_ipv4_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct nft_redir *priv = nft_expr_priv(expr);
struct nf_nat_ipv4_multi_range_compat mr;
memset(&mr, 0, sizeof(mr));
if (priv->sreg_proto_min) {
mr.range[0].min.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_min]);
mr.range[0].max.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_max]);
mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
}
mr.range[0].flags |= priv->flags;
regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt));
}
static void
nft_redir_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
nf_ct_netns_put(ctx->net, NFPROTO_IPV4);
}
static struct nft_expr_type nft_redir_ipv4_type;
static const struct nft_expr_ops nft_redir_ipv4_ops = {
.type = &nft_redir_ipv4_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
.eval = nft_redir_ipv4_eval,
.init = nft_redir_init,
.destroy = nft_redir_ipv4_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
};
static struct nft_expr_type nft_redir_ipv4_type __read_mostly = {
.family = NFPROTO_IPV4,
.name = "redir",
.ops = &nft_redir_ipv4_ops,
.policy = nft_redir_policy,
.maxattr = NFTA_REDIR_MAX,
.owner = THIS_MODULE,
};
static int __init nft_redir_ipv4_module_init(void)
{
return nft_register_expr(&nft_redir_ipv4_type);
}
static void __exit nft_redir_ipv4_module_exit(void)
{
nft_unregister_expr(&nft_redir_ipv4_type);
}
module_init(nft_redir_ipv4_module_init);
module_exit(nft_redir_ipv4_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");

View file

@ -49,14 +49,6 @@ config NFT_MASQ_IPV6
This is the expression that provides IPv4 masquerading support for This is the expression that provides IPv4 masquerading support for
nf_tables. nf_tables.
config NFT_REDIR_IPV6
tristate "IPv6 redirect support for nf_tables"
depends on NFT_REDIR
select NF_NAT_REDIRECT
help
This is the expression that provides IPv4 redirect support for
nf_tables.
endif # NF_NAT endif # NF_NAT
config NFT_REJECT_IPV6 config NFT_REJECT_IPV6

View file

@ -31,7 +31,6 @@ 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_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o
obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o
obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redir_ipv6.o
obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o obj-$(CONFIG_NFT_DUP_IPV6) += nft_dup_ipv6.o
obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o obj-$(CONFIG_NFT_FIB_IPV6) += nft_fib_ipv6.o

View file

@ -1,83 +0,0 @@
/*
* Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
*
* 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_redir.h>
#include <net/netfilter/nf_nat_redirect.h>
static void nft_redir_ipv6_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct nft_redir *priv = nft_expr_priv(expr);
struct nf_nat_range2 range;
memset(&range, 0, sizeof(range));
if (priv->sreg_proto_min) {
range.min_proto.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_min]);
range.max_proto.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_max]);
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
}
range.flags |= priv->flags;
regs->verdict.code =
nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt));
}
static void
nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
nf_ct_netns_put(ctx->net, NFPROTO_IPV6);
}
static struct nft_expr_type nft_redir_ipv6_type;
static const struct nft_expr_ops nft_redir_ipv6_ops = {
.type = &nft_redir_ipv6_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
.eval = nft_redir_ipv6_eval,
.init = nft_redir_init,
.destroy = nft_redir_ipv6_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
};
static struct nft_expr_type nft_redir_ipv6_type __read_mostly = {
.family = NFPROTO_IPV6,
.name = "redir",
.ops = &nft_redir_ipv6_ops,
.policy = nft_redir_policy,
.maxattr = NFTA_REDIR_MAX,
.owner = THIS_MODULE,
};
static int __init nft_redir_ipv6_module_init(void)
{
return nft_register_expr(&nft_redir_ipv6_type);
}
static void __exit nft_redir_ipv6_module_exit(void)
{
nft_unregister_expr(&nft_redir_ipv6_type);
}
module_init(nft_redir_ipv6_module_init);
module_exit(nft_redir_ipv6_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");

View file

@ -541,6 +541,7 @@ config NFT_REDIR
depends on NF_CONNTRACK depends on NF_CONNTRACK
depends on NF_NAT depends on NF_NAT
tristate "Netfilter nf_tables redirect support" tristate "Netfilter nf_tables redirect support"
select NF_NAT_REDIRECT
help help
This options adds the "redirect" expression that you can use This options adds the "redirect" expression that you can use
to perform NAT in the redirect flavour. to perform NAT in the redirect flavour.

View file

@ -13,19 +13,24 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_nat.h> #include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_redirect.h>
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
#include <net/netfilter/nft_redir.h>
const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = { struct nft_redir {
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
u16 flags;
};
static const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = {
[NFTA_REDIR_REG_PROTO_MIN] = { .type = NLA_U32 }, [NFTA_REDIR_REG_PROTO_MIN] = { .type = NLA_U32 },
[NFTA_REDIR_REG_PROTO_MAX] = { .type = NLA_U32 }, [NFTA_REDIR_REG_PROTO_MAX] = { .type = NLA_U32 },
[NFTA_REDIR_FLAGS] = { .type = NLA_U32 }, [NFTA_REDIR_FLAGS] = { .type = NLA_U32 },
}; };
EXPORT_SYMBOL_GPL(nft_redir_policy);
int nft_redir_validate(const struct nft_ctx *ctx, static int nft_redir_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nft_data **data) const struct nft_data **data)
{ {
int err; int err;
@ -37,11 +42,10 @@ int nft_redir_validate(const struct nft_ctx *ctx,
(1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_OUT)); (1 << NF_INET_LOCAL_OUT));
} }
EXPORT_SYMBOL_GPL(nft_redir_validate);
int nft_redir_init(const struct nft_ctx *ctx, static int nft_redir_init(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nlattr * const tb[]) const struct nlattr * const tb[])
{ {
struct nft_redir *priv = nft_expr_priv(expr); struct nft_redir *priv = nft_expr_priv(expr);
unsigned int plen; unsigned int plen;
@ -77,7 +81,6 @@ int nft_redir_init(const struct nft_ctx *ctx,
return nf_ct_netns_get(ctx->net, ctx->family); return nf_ct_netns_get(ctx->net, ctx->family);
} }
EXPORT_SYMBOL_GPL(nft_redir_init);
int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr) int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr)
{ {
@ -101,7 +104,134 @@ int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr)
nla_put_failure: nla_put_failure:
return -1; return -1;
} }
EXPORT_SYMBOL_GPL(nft_redir_dump);
static void nft_redir_ipv4_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct nft_redir *priv = nft_expr_priv(expr);
struct nf_nat_ipv4_multi_range_compat mr;
memset(&mr, 0, sizeof(mr));
if (priv->sreg_proto_min) {
mr.range[0].min.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_min]);
mr.range[0].max.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_max]);
mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
}
mr.range[0].flags |= priv->flags;
regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr, nft_hook(pkt));
}
static void
nft_redir_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
nf_ct_netns_put(ctx->net, NFPROTO_IPV4);
}
static struct nft_expr_type nft_redir_ipv4_type;
static const struct nft_expr_ops nft_redir_ipv4_ops = {
.type = &nft_redir_ipv4_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
.eval = nft_redir_ipv4_eval,
.init = nft_redir_init,
.destroy = nft_redir_ipv4_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
};
static struct nft_expr_type nft_redir_ipv4_type __read_mostly = {
.family = NFPROTO_IPV4,
.name = "redir",
.ops = &nft_redir_ipv4_ops,
.policy = nft_redir_policy,
.maxattr = NFTA_REDIR_MAX,
.owner = THIS_MODULE,
};
#ifdef CONFIG_NF_TABLES_IPV6
static void nft_redir_ipv6_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct nft_redir *priv = nft_expr_priv(expr);
struct nf_nat_range2 range;
memset(&range, 0, sizeof(range));
if (priv->sreg_proto_min) {
range.min_proto.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_min]);
range.max_proto.all = (__force __be16)nft_reg_load16(
&regs->data[priv->sreg_proto_max]);
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
}
range.flags |= priv->flags;
regs->verdict.code =
nf_nat_redirect_ipv6(pkt->skb, &range, nft_hook(pkt));
}
static void
nft_redir_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
{
nf_ct_netns_put(ctx->net, NFPROTO_IPV6);
}
static struct nft_expr_type nft_redir_ipv6_type;
static const struct nft_expr_ops nft_redir_ipv6_ops = {
.type = &nft_redir_ipv6_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
.eval = nft_redir_ipv6_eval,
.init = nft_redir_init,
.destroy = nft_redir_ipv6_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
};
static struct nft_expr_type nft_redir_ipv6_type __read_mostly = {
.family = NFPROTO_IPV6,
.name = "redir",
.ops = &nft_redir_ipv6_ops,
.policy = nft_redir_policy,
.maxattr = NFTA_REDIR_MAX,
.owner = THIS_MODULE,
};
#endif
static int __init nft_redir_module_init(void)
{
int ret = nft_register_expr(&nft_redir_ipv4_type);
if (ret)
return ret;
#ifdef CONFIG_NF_TABLES_IPV6
ret = nft_register_expr(&nft_redir_ipv6_type);
if (ret) {
nft_unregister_expr(&nft_redir_ipv4_type);
return ret;
}
#endif
return ret;
}
static void __exit nft_redir_module_exit(void)
{
nft_unregister_expr(&nft_redir_ipv4_type);
#ifdef CONFIG_NF_TABLES_IPV6
nft_unregister_expr(&nft_redir_ipv6_type);
#endif
}
module_init(nft_redir_module_init);
module_exit(nft_redir_module_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>"); MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET4, "redir");
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");