arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / net / netfilter / nft_masq.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo@debian.org>
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/nf_nat.h>
14 #include <net/netfilter/nf_nat_masquerade.h>
15
16 struct nft_masq {
17         u32                     flags;
18         u8                      sreg_proto_min;
19         u8                      sreg_proto_max;
20 };
21
22 static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
23         [NFTA_MASQ_FLAGS]               =
24                 NLA_POLICY_MASK(NLA_BE32, NF_NAT_RANGE_MASK),
25         [NFTA_MASQ_REG_PROTO_MIN]       = { .type = NLA_U32 },
26         [NFTA_MASQ_REG_PROTO_MAX]       = { .type = NLA_U32 },
27 };
28
29 static int nft_masq_validate(const struct nft_ctx *ctx,
30                              const struct nft_expr *expr,
31                              const struct nft_data **data)
32 {
33         int err;
34
35         err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
36         if (err < 0)
37                 return err;
38
39         return nft_chain_validate_hooks(ctx->chain,
40                                         (1 << NF_INET_POST_ROUTING));
41 }
42
43 static int nft_masq_init(const struct nft_ctx *ctx,
44                          const struct nft_expr *expr,
45                          const struct nlattr * const tb[])
46 {
47         u32 plen = sizeof_field(struct nf_nat_range, min_proto.all);
48         struct nft_masq *priv = nft_expr_priv(expr);
49         int err;
50
51         if (tb[NFTA_MASQ_FLAGS])
52                 priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
53
54         if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
55                 err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
56                                               &priv->sreg_proto_min, plen);
57                 if (err < 0)
58                         return err;
59
60                 if (tb[NFTA_MASQ_REG_PROTO_MAX]) {
61                         err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX],
62                                                       &priv->sreg_proto_max,
63                                                       plen);
64                         if (err < 0)
65                                 return err;
66                 } else {
67                         priv->sreg_proto_max = priv->sreg_proto_min;
68                 }
69         }
70
71         return nf_ct_netns_get(ctx->net, ctx->family);
72 }
73
74 static int nft_masq_dump(struct sk_buff *skb,
75                          const struct nft_expr *expr, bool reset)
76 {
77         const struct nft_masq *priv = nft_expr_priv(expr);
78
79         if (priv->flags != 0 &&
80             nla_put_be32(skb, NFTA_MASQ_FLAGS, htonl(priv->flags)))
81                 goto nla_put_failure;
82
83         if (priv->sreg_proto_min) {
84                 if (nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MIN,
85                                       priv->sreg_proto_min) ||
86                     nft_dump_register(skb, NFTA_MASQ_REG_PROTO_MAX,
87                                       priv->sreg_proto_max))
88                         goto nla_put_failure;
89         }
90
91         return 0;
92
93 nla_put_failure:
94         return -1;
95 }
96
97 static void nft_masq_eval(const struct nft_expr *expr,
98                           struct nft_regs *regs,
99                           const struct nft_pktinfo *pkt)
100 {
101         const struct nft_masq *priv = nft_expr_priv(expr);
102         struct nf_nat_range2 range;
103
104         memset(&range, 0, sizeof(range));
105         range.flags = priv->flags;
106         if (priv->sreg_proto_min) {
107                 range.min_proto.all = (__force __be16)
108                         nft_reg_load16(&regs->data[priv->sreg_proto_min]);
109                 range.max_proto.all = (__force __be16)
110                         nft_reg_load16(&regs->data[priv->sreg_proto_max]);
111         }
112
113         switch (nft_pf(pkt)) {
114         case NFPROTO_IPV4:
115                 regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb,
116                                                             nft_hook(pkt),
117                                                             &range,
118                                                             nft_out(pkt));
119                 break;
120 #ifdef CONFIG_NF_TABLES_IPV6
121         case NFPROTO_IPV6:
122                 regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range,
123                                                             nft_out(pkt));
124                 break;
125 #endif
126         default:
127                 WARN_ON_ONCE(1);
128                 break;
129         }
130 }
131
132 static void
133 nft_masq_ipv4_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
134 {
135         nf_ct_netns_put(ctx->net, NFPROTO_IPV4);
136 }
137
138 static struct nft_expr_type nft_masq_ipv4_type;
139 static const struct nft_expr_ops nft_masq_ipv4_ops = {
140         .type           = &nft_masq_ipv4_type,
141         .size           = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
142         .eval           = nft_masq_eval,
143         .init           = nft_masq_init,
144         .destroy        = nft_masq_ipv4_destroy,
145         .dump           = nft_masq_dump,
146         .validate       = nft_masq_validate,
147         .reduce         = NFT_REDUCE_READONLY,
148 };
149
150 static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
151         .family         = NFPROTO_IPV4,
152         .name           = "masq",
153         .ops            = &nft_masq_ipv4_ops,
154         .policy         = nft_masq_policy,
155         .maxattr        = NFTA_MASQ_MAX,
156         .owner          = THIS_MODULE,
157 };
158
159 #ifdef CONFIG_NF_TABLES_IPV6
160 static void
161 nft_masq_ipv6_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
162 {
163         nf_ct_netns_put(ctx->net, NFPROTO_IPV6);
164 }
165
166 static struct nft_expr_type nft_masq_ipv6_type;
167 static const struct nft_expr_ops nft_masq_ipv6_ops = {
168         .type           = &nft_masq_ipv6_type,
169         .size           = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
170         .eval           = nft_masq_eval,
171         .init           = nft_masq_init,
172         .destroy        = nft_masq_ipv6_destroy,
173         .dump           = nft_masq_dump,
174         .validate       = nft_masq_validate,
175         .reduce         = NFT_REDUCE_READONLY,
176 };
177
178 static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
179         .family         = NFPROTO_IPV6,
180         .name           = "masq",
181         .ops            = &nft_masq_ipv6_ops,
182         .policy         = nft_masq_policy,
183         .maxattr        = NFTA_MASQ_MAX,
184         .owner          = THIS_MODULE,
185 };
186
187 static int __init nft_masq_module_init_ipv6(void)
188 {
189         return nft_register_expr(&nft_masq_ipv6_type);
190 }
191
192 static void nft_masq_module_exit_ipv6(void)
193 {
194         nft_unregister_expr(&nft_masq_ipv6_type);
195 }
196 #else
197 static inline int nft_masq_module_init_ipv6(void) { return 0; }
198 static inline void nft_masq_module_exit_ipv6(void) {}
199 #endif
200
201 #ifdef CONFIG_NF_TABLES_INET
202 static void
203 nft_masq_inet_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
204 {
205         nf_ct_netns_put(ctx->net, NFPROTO_INET);
206 }
207
208 static struct nft_expr_type nft_masq_inet_type;
209 static const struct nft_expr_ops nft_masq_inet_ops = {
210         .type           = &nft_masq_inet_type,
211         .size           = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
212         .eval           = nft_masq_eval,
213         .init           = nft_masq_init,
214         .destroy        = nft_masq_inet_destroy,
215         .dump           = nft_masq_dump,
216         .validate       = nft_masq_validate,
217         .reduce         = NFT_REDUCE_READONLY,
218 };
219
220 static struct nft_expr_type nft_masq_inet_type __read_mostly = {
221         .family         = NFPROTO_INET,
222         .name           = "masq",
223         .ops            = &nft_masq_inet_ops,
224         .policy         = nft_masq_policy,
225         .maxattr        = NFTA_MASQ_MAX,
226         .owner          = THIS_MODULE,
227 };
228
229 static int __init nft_masq_module_init_inet(void)
230 {
231         return nft_register_expr(&nft_masq_inet_type);
232 }
233
234 static void nft_masq_module_exit_inet(void)
235 {
236         nft_unregister_expr(&nft_masq_inet_type);
237 }
238 #else
239 static inline int nft_masq_module_init_inet(void) { return 0; }
240 static inline void nft_masq_module_exit_inet(void) {}
241 #endif
242
243 static int __init nft_masq_module_init(void)
244 {
245         int ret;
246
247         ret = nft_masq_module_init_ipv6();
248         if (ret < 0)
249                 return ret;
250
251         ret = nft_masq_module_init_inet();
252         if (ret < 0) {
253                 nft_masq_module_exit_ipv6();
254                 return ret;
255         }
256
257         ret = nft_register_expr(&nft_masq_ipv4_type);
258         if (ret < 0) {
259                 nft_masq_module_exit_inet();
260                 nft_masq_module_exit_ipv6();
261                 return ret;
262         }
263
264         ret = nf_nat_masquerade_inet_register_notifiers();
265         if (ret < 0) {
266                 nft_masq_module_exit_ipv6();
267                 nft_masq_module_exit_inet();
268                 nft_unregister_expr(&nft_masq_ipv4_type);
269                 return ret;
270         }
271
272         return ret;
273 }
274
275 static void __exit nft_masq_module_exit(void)
276 {
277         nft_masq_module_exit_ipv6();
278         nft_masq_module_exit_inet();
279         nft_unregister_expr(&nft_masq_ipv4_type);
280         nf_nat_masquerade_inet_unregister_notifiers();
281 }
282
283 module_init(nft_masq_module_init);
284 module_exit(nft_masq_module_exit);
285
286 MODULE_LICENSE("GPL");
287 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
288 MODULE_ALIAS_NFT_EXPR("masq");
289 MODULE_DESCRIPTION("Netfilter nftables masquerade expression support");