Merge tag 'vfio-v5.11-rc1' of git://github.com/awilliam/linux-vfio
[linux-2.6-microblaze.git] / net / netfilter / nft_reject_inet.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 Patrick McHardy <kaber@trash.net>
4  */
5
6 #include <linux/kernel.h>
7 #include <linux/init.h>
8 #include <linux/module.h>
9 #include <linux/netlink.h>
10 #include <linux/netfilter.h>
11 #include <linux/netfilter/nf_tables.h>
12 #include <net/netfilter/nf_tables.h>
13 #include <net/netfilter/nft_reject.h>
14 #include <net/netfilter/ipv4/nf_reject.h>
15 #include <net/netfilter/ipv6/nf_reject.h>
16
17 static void nft_reject_inet_eval(const struct nft_expr *expr,
18                                  struct nft_regs *regs,
19                                  const struct nft_pktinfo *pkt)
20 {
21         struct nft_reject *priv = nft_expr_priv(expr);
22
23         switch (nft_pf(pkt)) {
24         case NFPROTO_IPV4:
25                 switch (priv->type) {
26                 case NFT_REJECT_ICMP_UNREACH:
27                         nf_send_unreach(pkt->skb, priv->icmp_code,
28                                         nft_hook(pkt));
29                         break;
30                 case NFT_REJECT_TCP_RST:
31                         nf_send_reset(nft_net(pkt), pkt->xt.state->sk,
32                                       pkt->skb, nft_hook(pkt));
33                         break;
34                 case NFT_REJECT_ICMPX_UNREACH:
35                         nf_send_unreach(pkt->skb,
36                                         nft_reject_icmp_code(priv->icmp_code),
37                                         nft_hook(pkt));
38                         break;
39                 }
40                 break;
41         case NFPROTO_IPV6:
42                 switch (priv->type) {
43                 case NFT_REJECT_ICMP_UNREACH:
44                         nf_send_unreach6(nft_net(pkt), pkt->skb,
45                                          priv->icmp_code, nft_hook(pkt));
46                         break;
47                 case NFT_REJECT_TCP_RST:
48                         nf_send_reset6(nft_net(pkt), pkt->xt.state->sk,
49                                        pkt->skb, nft_hook(pkt));
50                         break;
51                 case NFT_REJECT_ICMPX_UNREACH:
52                         nf_send_unreach6(nft_net(pkt), pkt->skb,
53                                          nft_reject_icmpv6_code(priv->icmp_code),
54                                          nft_hook(pkt));
55                         break;
56                 }
57                 break;
58         }
59
60         regs->verdict.code = NF_DROP;
61 }
62
63 static int nft_reject_inet_validate(const struct nft_ctx *ctx,
64                                     const struct nft_expr *expr,
65                                     const struct nft_data **data)
66 {
67         return nft_chain_validate_hooks(ctx->chain,
68                                         (1 << NF_INET_LOCAL_IN) |
69                                         (1 << NF_INET_FORWARD) |
70                                         (1 << NF_INET_LOCAL_OUT) |
71                                         (1 << NF_INET_PRE_ROUTING) |
72                                         (1 << NF_INET_INGRESS));
73 }
74
75 static struct nft_expr_type nft_reject_inet_type;
76 static const struct nft_expr_ops nft_reject_inet_ops = {
77         .type           = &nft_reject_inet_type,
78         .size           = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
79         .eval           = nft_reject_inet_eval,
80         .init           = nft_reject_init,
81         .dump           = nft_reject_dump,
82         .validate       = nft_reject_inet_validate,
83 };
84
85 static struct nft_expr_type nft_reject_inet_type __read_mostly = {
86         .family         = NFPROTO_INET,
87         .name           = "reject",
88         .ops            = &nft_reject_inet_ops,
89         .policy         = nft_reject_policy,
90         .maxattr        = NFTA_REJECT_MAX,
91         .owner          = THIS_MODULE,
92 };
93
94 static int __init nft_reject_inet_module_init(void)
95 {
96         return nft_register_expr(&nft_reject_inet_type);
97 }
98
99 static void __exit nft_reject_inet_module_exit(void)
100 {
101         nft_unregister_expr(&nft_reject_inet_type);
102 }
103
104 module_init(nft_reject_inet_module_init);
105 module_exit(nft_reject_inet_module_exit);
106
107 MODULE_LICENSE("GPL");
108 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
109 MODULE_ALIAS_NFT_AF_EXPR(1, "reject");
110 MODULE_DESCRIPTION("Netfilter nftables reject inet support");