netfilter: Add MODULE_DESCRIPTION entries to kernel modules
[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->skb, nft_hook(pkt));
32                         break;
33                 case NFT_REJECT_ICMPX_UNREACH:
34                         nf_send_unreach(pkt->skb,
35                                         nft_reject_icmp_code(priv->icmp_code),
36                                         nft_hook(pkt));
37                         break;
38                 }
39                 break;
40         case NFPROTO_IPV6:
41                 switch (priv->type) {
42                 case NFT_REJECT_ICMP_UNREACH:
43                         nf_send_unreach6(nft_net(pkt), pkt->skb,
44                                          priv->icmp_code, nft_hook(pkt));
45                         break;
46                 case NFT_REJECT_TCP_RST:
47                         nf_send_reset6(nft_net(pkt), pkt->skb, nft_hook(pkt));
48                         break;
49                 case NFT_REJECT_ICMPX_UNREACH:
50                         nf_send_unreach6(nft_net(pkt), pkt->skb,
51                                          nft_reject_icmpv6_code(priv->icmp_code),
52                                          nft_hook(pkt));
53                         break;
54                 }
55                 break;
56         }
57
58         regs->verdict.code = NF_DROP;
59 }
60
61 static int nft_reject_inet_init(const struct nft_ctx *ctx,
62                                 const struct nft_expr *expr,
63                                 const struct nlattr * const tb[])
64 {
65         struct nft_reject *priv = nft_expr_priv(expr);
66         int icmp_code;
67
68         if (tb[NFTA_REJECT_TYPE] == NULL)
69                 return -EINVAL;
70
71         priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
72         switch (priv->type) {
73         case NFT_REJECT_ICMP_UNREACH:
74         case NFT_REJECT_ICMPX_UNREACH:
75                 if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
76                         return -EINVAL;
77
78                 icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
79                 if (priv->type == NFT_REJECT_ICMPX_UNREACH &&
80                     icmp_code > NFT_REJECT_ICMPX_MAX)
81                         return -EINVAL;
82
83                 priv->icmp_code = icmp_code;
84                 break;
85         case NFT_REJECT_TCP_RST:
86                 break;
87         default:
88                 return -EINVAL;
89         }
90         return 0;
91 }
92
93 static int nft_reject_inet_dump(struct sk_buff *skb,
94                                 const struct nft_expr *expr)
95 {
96         const struct nft_reject *priv = nft_expr_priv(expr);
97
98         if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
99                 goto nla_put_failure;
100
101         switch (priv->type) {
102         case NFT_REJECT_ICMP_UNREACH:
103         case NFT_REJECT_ICMPX_UNREACH:
104                 if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
105                         goto nla_put_failure;
106                 break;
107         default:
108                 break;
109         }
110
111         return 0;
112
113 nla_put_failure:
114         return -1;
115 }
116
117 static struct nft_expr_type nft_reject_inet_type;
118 static const struct nft_expr_ops nft_reject_inet_ops = {
119         .type           = &nft_reject_inet_type,
120         .size           = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
121         .eval           = nft_reject_inet_eval,
122         .init           = nft_reject_inet_init,
123         .dump           = nft_reject_inet_dump,
124         .validate       = nft_reject_validate,
125 };
126
127 static struct nft_expr_type nft_reject_inet_type __read_mostly = {
128         .family         = NFPROTO_INET,
129         .name           = "reject",
130         .ops            = &nft_reject_inet_ops,
131         .policy         = nft_reject_policy,
132         .maxattr        = NFTA_REJECT_MAX,
133         .owner          = THIS_MODULE,
134 };
135
136 static int __init nft_reject_inet_module_init(void)
137 {
138         return nft_register_expr(&nft_reject_inet_type);
139 }
140
141 static void __exit nft_reject_inet_module_exit(void)
142 {
143         nft_unregister_expr(&nft_reject_inet_type);
144 }
145
146 module_init(nft_reject_inet_module_init);
147 module_exit(nft_reject_inet_module_exit);
148
149 MODULE_LICENSE("GPL");
150 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
151 MODULE_ALIAS_NFT_AF_EXPR(1, "reject");
152 MODULE_DESCRIPTION("Netfilter nftables reject inet support");