Skip to content

Commit

Permalink
netfilter: nft_reject_inet: allow to use reject from inet ingress
Browse files Browse the repository at this point in the history
Enhance validation to support for reject from inet ingress chains.

Note that, reject from inet ingress and netdev ingress differ.

Reject packets from inet ingress are sent through ip_local_out() since
inet reject emulates the IP layer receive path. So the reject packet
follows to classic IP output and postrouting paths.

The reject action from netdev ingress assumes the packet not yet entered
the IP layer, so the reject packet is sent through dev_queue_xmit().
Therefore, reject packets from netdev ingress do not follow the classic
IP output and postrouting paths.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Pablo Neira Ayuso committed Nov 1, 2020
1 parent 35b7ee3 commit 117ca1f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
6 changes: 4 additions & 2 deletions net/ipv4/netfilter/nf_reject_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
if (!oth)
return;

if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(oldskb))
if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) &&
nf_reject_fill_skb_dst(oldskb) < 0)
return;

if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
Expand Down Expand Up @@ -315,7 +316,8 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
if (iph->frag_off & htons(IP_OFFSET))
return;

if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(skb_in))
if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) &&
nf_reject_fill_skb_dst(skb_in) < 0)
return;

if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {
Expand Down
5 changes: 3 additions & 2 deletions net/ipv6/netfilter/nf_reject_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
fl6.fl6_sport = otcph->dest;
fl6.fl6_dport = otcph->source;

if (hook == NF_INET_PRE_ROUTING) {
if (hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) {
nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
if (!dst)
return;
Expand Down Expand Up @@ -402,7 +402,8 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
skb_in->dev = net->loopback_dev;

if (hooknum == NF_INET_PRE_ROUTING && nf_reject6_fill_skb_dst(skb_in))
if ((hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_INGRESS) &&
nf_reject6_fill_skb_dst(skb_in) < 0)
return;

icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
Expand Down
14 changes: 13 additions & 1 deletion net/netfilter/nft_reject_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,26 @@ static void nft_reject_inet_eval(const struct nft_expr *expr,
regs->verdict.code = NF_DROP;
}

static int nft_reject_inet_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) |
(1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT) |
(1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_INGRESS));
}

static struct nft_expr_type nft_reject_inet_type;
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_init,
.dump = nft_reject_dump,
.validate = nft_reject_validate,
.validate = nft_reject_inet_validate,
};

static struct nft_expr_type nft_reject_inet_type __read_mostly = {
Expand Down

0 comments on commit 117ca1f

Please sign in to comment.