new file mode 100644
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _NFT_REJECT_IPV4_H_
+#define _NFT_REJECT_IPV4_H_
+
+void nft_reject_ipv4_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+
+#endif
new file mode 100644
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _NFT_REJECT_IPV6_H_
+#define _NFT_REJECT_IPV6_H_
+
+void nft_reject_ipv6_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt);
+
+#endif
@@ -26,5 +26,8 @@ int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr);
int nft_reject_icmp_code(u8 code);
int nft_reject_icmpv6_code(u8 code);
+int nft_reject_generic_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data);
#endif
@@ -16,9 +16,9 @@
#include <net/netfilter/ipv4/nf_reject.h>
#include <net/netfilter/nft_reject.h>
-static void nft_reject_ipv4_eval(const struct nft_expr *expr,
- struct nft_regs *regs,
- const struct nft_pktinfo *pkt)
+void nft_reject_ipv4_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
{
struct nft_reject *priv = nft_expr_priv(expr);
@@ -29,12 +29,18 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr,
case NFT_REJECT_TCP_RST:
nf_send_reset(nft_net(pkt), pkt->skb, nft_hook(pkt));
break;
+ case NFT_REJECT_ICMPX_UNREACH:
+ nf_send_unreach(pkt->skb,
+ nft_reject_icmp_code(priv->icmp_code),
+ nft_hook(pkt));
+ break;
default:
break;
}
regs->verdict.code = NF_DROP;
}
+EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval);
static struct nft_expr_type nft_reject_ipv4_type;
static const struct nft_expr_ops nft_reject_ipv4_ops = {
@@ -15,13 +15,17 @@
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nft_reject.h>
#include <net/netfilter/ipv6/nf_reject.h>
+#include <net/ipv6.h>
-static void nft_reject_ipv6_eval(const struct nft_expr *expr,
- struct nft_regs *regs,
- const struct nft_pktinfo *pkt)
+void nft_reject_ipv6_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
{
struct nft_reject *priv = nft_expr_priv(expr);
+ if (!ipv6_mod_enabled())
+ return;
+
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
nf_send_unreach6(nft_net(pkt), pkt->skb, priv->icmp_code,
@@ -30,12 +34,18 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr,
case NFT_REJECT_TCP_RST:
nf_send_reset6(nft_net(pkt), pkt->skb, nft_hook(pkt));
break;
+ case NFT_REJECT_ICMPX_UNREACH:
+ nf_send_unreach6(nft_net(pkt), pkt->skb,
+ nft_reject_icmpv6_code(priv->icmp_code),
+ nft_hook(pkt));
+ break;
default:
break;
}
regs->verdict.code = NF_DROP;
}
+EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval);
static struct nft_expr_type nft_reject_ipv6_type;
static const struct nft_expr_ops nft_reject_ipv6_ops = {
@@ -26,6 +26,20 @@ EXPORT_SYMBOL_GPL(nft_reject_policy);
int nft_reject_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
+{
+ struct nft_reject *priv = nft_expr_priv(expr);
+
+ if (priv->type != NFT_REJECT_ICMP_UNREACH &&
+ priv->type != NFT_REJECT_TCP_RST)
+ return -EINVAL;
+
+ return nft_reject_generic_validate(ctx, expr, data);
+}
+EXPORT_SYMBOL_GPL(nft_reject_validate);
+
+int nft_reject_generic_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data)
{
return nft_chain_validate_hooks(ctx->chain,
(1 << NF_INET_LOCAL_IN) |
@@ -33,13 +47,14 @@ int nft_reject_validate(const struct nft_ctx *ctx,
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_PRE_ROUTING));
}
-EXPORT_SYMBOL_GPL(nft_reject_validate);
+EXPORT_SYMBOL_GPL(nft_reject_generic_validate);
int nft_reject_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
struct nft_reject *priv = nft_expr_priv(expr);
+ int icmp_code;
if (tb[NFTA_REJECT_TYPE] == NULL)
return -EINVAL;
@@ -47,15 +62,22 @@ int nft_reject_init(const struct nft_ctx *ctx,
priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
+ case NFT_REJECT_ICMPX_UNREACH:
if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
return -EINVAL;
- priv->icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
+
+ icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
+ if (priv->type == NFT_REJECT_ICMPX_UNREACH &&
+ icmp_code > NFT_REJECT_ICMPX_MAX)
+ return -EINVAL;
+
+ priv->icmp_code = icmp_code;
+ break;
case NFT_REJECT_TCP_RST:
break;
default:
return -EINVAL;
}
-
return 0;
}
EXPORT_SYMBOL_GPL(nft_reject_init);
@@ -69,6 +91,7 @@ int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
+ case NFT_REJECT_ICMPX_UNREACH:
if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
goto nla_put_failure;
break;
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2014 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2020 Laura Garcia Liebana <nevola@gmail.com>
*/
#include <linux/kernel.h>
@@ -11,107 +12,21 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nft_reject.h>
-#include <net/netfilter/ipv4/nf_reject.h>
-#include <net/netfilter/ipv6/nf_reject.h>
+#include <net/netfilter/ipv4/nft_reject_ipv4.h>
+#include <net/netfilter/ipv6/nft_reject_ipv6.h>
static void nft_reject_inet_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
- struct nft_reject *priv = nft_expr_priv(expr);
-
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
- switch (priv->type) {
- case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach(pkt->skb, priv->icmp_code,
- nft_hook(pkt));
- break;
- case NFT_REJECT_TCP_RST:
- nf_send_reset(nft_net(pkt), pkt->skb, nft_hook(pkt));
- break;
- case NFT_REJECT_ICMPX_UNREACH:
- nf_send_unreach(pkt->skb,
- nft_reject_icmp_code(priv->icmp_code),
- nft_hook(pkt));
- break;
- }
+ nft_reject_ipv4_eval(expr, regs, pkt);
break;
case NFPROTO_IPV6:
- switch (priv->type) {
- case NFT_REJECT_ICMP_UNREACH:
- nf_send_unreach6(nft_net(pkt), pkt->skb,
- priv->icmp_code, nft_hook(pkt));
- break;
- case NFT_REJECT_TCP_RST:
- nf_send_reset6(nft_net(pkt), pkt->skb, nft_hook(pkt));
- break;
- case NFT_REJECT_ICMPX_UNREACH:
- nf_send_unreach6(nft_net(pkt), pkt->skb,
- nft_reject_icmpv6_code(priv->icmp_code),
- nft_hook(pkt));
- break;
- }
- break;
- }
-
- regs->verdict.code = NF_DROP;
-}
-
-static int nft_reject_inet_init(const struct nft_ctx *ctx,
- const struct nft_expr *expr,
- const struct nlattr * const tb[])
-{
- struct nft_reject *priv = nft_expr_priv(expr);
- int icmp_code;
-
- if (tb[NFTA_REJECT_TYPE] == NULL)
- return -EINVAL;
-
- priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
- switch (priv->type) {
- case NFT_REJECT_ICMP_UNREACH:
- case NFT_REJECT_ICMPX_UNREACH:
- if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
- return -EINVAL;
-
- icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
- if (priv->type == NFT_REJECT_ICMPX_UNREACH &&
- icmp_code > NFT_REJECT_ICMPX_MAX)
- return -EINVAL;
-
- priv->icmp_code = icmp_code;
+ nft_reject_ipv6_eval(expr, regs, pkt);
break;
- case NFT_REJECT_TCP_RST:
- break;
- default:
- return -EINVAL;
}
- return 0;
-}
-
-static int nft_reject_inet_dump(struct sk_buff *skb,
- const struct nft_expr *expr)
-{
- const struct nft_reject *priv = nft_expr_priv(expr);
-
- if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
- goto nla_put_failure;
-
- switch (priv->type) {
- case NFT_REJECT_ICMP_UNREACH:
- case NFT_REJECT_ICMPX_UNREACH:
- if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
- goto nla_put_failure;
- break;
- default:
- break;
- }
-
- return 0;
-
-nla_put_failure:
- return -1;
}
static struct nft_expr_type nft_reject_inet_type;
@@ -119,9 +34,9 @@ static const struct nft_expr_ops nft_reject_inet_ops = {
.type = &nft_reject_inet_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
.eval = nft_reject_inet_eval,
- .init = nft_reject_inet_init,
- .dump = nft_reject_inet_dump,
- .validate = nft_reject_validate,
+ .init = nft_reject_init,
+ .dump = nft_reject_dump,
+ .validate = nft_reject_generic_validate,
};
static struct nft_expr_type nft_reject_inet_type __read_mostly = {
Within REJECT modules there are duplicated code for different families, so this patch re-structures the source code in order to reuse as much as possible. The refactoring produces ~30 lines removed in total and prepares the code to be added the ingress support of REJECT. Signed-off-by: Laura Garcia Liebana <nevola@gmail.com> --- include/net/netfilter/ipv4/nft_reject_ipv4.h | 9 ++ include/net/netfilter/ipv6/nft_reject_ipv6.h | 9 ++ include/net/netfilter/nft_reject.h | 3 + net/ipv4/netfilter/nft_reject_ipv4.c | 12 ++- net/ipv6/netfilter/nft_reject_ipv6.c | 16 ++- net/netfilter/nft_reject.c | 29 +++++- net/netfilter/nft_reject_inet.c | 101 ++----------------- 7 files changed, 77 insertions(+), 102 deletions(-) create mode 100644 include/net/netfilter/ipv4/nft_reject_ipv4.h create mode 100644 include/net/netfilter/ipv6/nft_reject_ipv6.h