1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4 * Copyright (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>
5 * Copyright (c) 2012 Intel Corporation
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/skbuff.h>
12 #include <linux/string.h>
13 #include <linux/netlink.h>
14 #include <linux/netfilter.h>
15 #include <linux/netfilter_ipv4.h>
16 #include <linux/netfilter/nfnetlink.h>
17 #include <linux/netfilter/nf_tables.h>
18 #include <net/netfilter/nf_conntrack.h>
19 #include <net/netfilter/nf_nat.h>
20 #include <net/netfilter/nf_tables.h>
24 enum nft_registers sreg_addr_min
:8;
25 enum nft_registers sreg_addr_max
:8;
26 enum nft_registers sreg_proto_min
:8;
27 enum nft_registers sreg_proto_max
:8;
28 enum nf_nat_manip_type type
:8;
33 static void nft_nat_eval(const struct nft_expr
*expr
,
34 struct nft_regs
*regs
,
35 const struct nft_pktinfo
*pkt
)
37 const struct nft_nat
*priv
= nft_expr_priv(expr
);
38 enum ip_conntrack_info ctinfo
;
39 struct nf_conn
*ct
= nf_ct_get(pkt
->skb
, &ctinfo
);
40 struct nf_nat_range2 range
;
42 memset(&range
, 0, sizeof(range
));
43 if (priv
->sreg_addr_min
) {
44 if (priv
->family
== AF_INET
) {
45 range
.min_addr
.ip
= (__force __be32
)
46 regs
->data
[priv
->sreg_addr_min
];
47 range
.max_addr
.ip
= (__force __be32
)
48 regs
->data
[priv
->sreg_addr_max
];
51 memcpy(range
.min_addr
.ip6
,
52 ®s
->data
[priv
->sreg_addr_min
],
53 sizeof(range
.min_addr
.ip6
));
54 memcpy(range
.max_addr
.ip6
,
55 ®s
->data
[priv
->sreg_addr_max
],
56 sizeof(range
.max_addr
.ip6
));
58 range
.flags
|= NF_NAT_RANGE_MAP_IPS
;
61 if (priv
->sreg_proto_min
) {
62 range
.min_proto
.all
= (__force __be16
)nft_reg_load16(
63 ®s
->data
[priv
->sreg_proto_min
]);
64 range
.max_proto
.all
= (__force __be16
)nft_reg_load16(
65 ®s
->data
[priv
->sreg_proto_max
]);
66 range
.flags
|= NF_NAT_RANGE_PROTO_SPECIFIED
;
69 range
.flags
|= priv
->flags
;
71 regs
->verdict
.code
= nf_nat_setup_info(ct
, &range
, priv
->type
);
74 static const struct nla_policy nft_nat_policy
[NFTA_NAT_MAX
+ 1] = {
75 [NFTA_NAT_TYPE
] = { .type
= NLA_U32
},
76 [NFTA_NAT_FAMILY
] = { .type
= NLA_U32
},
77 [NFTA_NAT_REG_ADDR_MIN
] = { .type
= NLA_U32
},
78 [NFTA_NAT_REG_ADDR_MAX
] = { .type
= NLA_U32
},
79 [NFTA_NAT_REG_PROTO_MIN
] = { .type
= NLA_U32
},
80 [NFTA_NAT_REG_PROTO_MAX
] = { .type
= NLA_U32
},
81 [NFTA_NAT_FLAGS
] = { .type
= NLA_U32
},
84 static int nft_nat_validate(const struct nft_ctx
*ctx
,
85 const struct nft_expr
*expr
,
86 const struct nft_data
**data
)
88 struct nft_nat
*priv
= nft_expr_priv(expr
);
91 err
= nft_chain_validate_dependency(ctx
->chain
, NFT_CHAIN_T_NAT
);
97 err
= nft_chain_validate_hooks(ctx
->chain
,
98 (1 << NF_INET_POST_ROUTING
) |
99 (1 << NF_INET_LOCAL_IN
));
102 err
= nft_chain_validate_hooks(ctx
->chain
,
103 (1 << NF_INET_PRE_ROUTING
) |
104 (1 << NF_INET_LOCAL_OUT
));
111 static int nft_nat_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
112 const struct nlattr
* const tb
[])
114 struct nft_nat
*priv
= nft_expr_priv(expr
);
115 unsigned int alen
, plen
;
119 if (tb
[NFTA_NAT_TYPE
] == NULL
||
120 (tb
[NFTA_NAT_REG_ADDR_MIN
] == NULL
&&
121 tb
[NFTA_NAT_REG_PROTO_MIN
] == NULL
))
124 switch (ntohl(nla_get_be32(tb
[NFTA_NAT_TYPE
]))) {
126 priv
->type
= NF_NAT_MANIP_SRC
;
129 priv
->type
= NF_NAT_MANIP_DST
;
135 if (tb
[NFTA_NAT_FAMILY
] == NULL
)
138 family
= ntohl(nla_get_be32(tb
[NFTA_NAT_FAMILY
]));
139 if (ctx
->family
!= NFPROTO_INET
&& ctx
->family
!= family
)
144 alen
= sizeof_field(struct nf_nat_range
, min_addr
.ip
);
147 alen
= sizeof_field(struct nf_nat_range
, min_addr
.ip6
);
150 return -EAFNOSUPPORT
;
152 priv
->family
= family
;
154 if (tb
[NFTA_NAT_REG_ADDR_MIN
]) {
155 priv
->sreg_addr_min
=
156 nft_parse_register(tb
[NFTA_NAT_REG_ADDR_MIN
]);
157 err
= nft_validate_register_load(priv
->sreg_addr_min
, alen
);
161 if (tb
[NFTA_NAT_REG_ADDR_MAX
]) {
162 priv
->sreg_addr_max
=
163 nft_parse_register(tb
[NFTA_NAT_REG_ADDR_MAX
]);
165 err
= nft_validate_register_load(priv
->sreg_addr_max
,
170 priv
->sreg_addr_max
= priv
->sreg_addr_min
;
174 plen
= sizeof_field(struct nf_nat_range
, min_addr
.all
);
175 if (tb
[NFTA_NAT_REG_PROTO_MIN
]) {
176 priv
->sreg_proto_min
=
177 nft_parse_register(tb
[NFTA_NAT_REG_PROTO_MIN
]);
179 err
= nft_validate_register_load(priv
->sreg_proto_min
, plen
);
183 if (tb
[NFTA_NAT_REG_PROTO_MAX
]) {
184 priv
->sreg_proto_max
=
185 nft_parse_register(tb
[NFTA_NAT_REG_PROTO_MAX
]);
187 err
= nft_validate_register_load(priv
->sreg_proto_max
,
192 priv
->sreg_proto_max
= priv
->sreg_proto_min
;
196 if (tb
[NFTA_NAT_FLAGS
]) {
197 priv
->flags
= ntohl(nla_get_be32(tb
[NFTA_NAT_FLAGS
]));
198 if (priv
->flags
& ~NF_NAT_RANGE_MASK
)
202 return nf_ct_netns_get(ctx
->net
, family
);
205 static int nft_nat_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
207 const struct nft_nat
*priv
= nft_expr_priv(expr
);
209 switch (priv
->type
) {
210 case NF_NAT_MANIP_SRC
:
211 if (nla_put_be32(skb
, NFTA_NAT_TYPE
, htonl(NFT_NAT_SNAT
)))
212 goto nla_put_failure
;
214 case NF_NAT_MANIP_DST
:
215 if (nla_put_be32(skb
, NFTA_NAT_TYPE
, htonl(NFT_NAT_DNAT
)))
216 goto nla_put_failure
;
220 if (nla_put_be32(skb
, NFTA_NAT_FAMILY
, htonl(priv
->family
)))
221 goto nla_put_failure
;
223 if (priv
->sreg_addr_min
) {
224 if (nft_dump_register(skb
, NFTA_NAT_REG_ADDR_MIN
,
225 priv
->sreg_addr_min
) ||
226 nft_dump_register(skb
, NFTA_NAT_REG_ADDR_MAX
,
227 priv
->sreg_addr_max
))
228 goto nla_put_failure
;
231 if (priv
->sreg_proto_min
) {
232 if (nft_dump_register(skb
, NFTA_NAT_REG_PROTO_MIN
,
233 priv
->sreg_proto_min
) ||
234 nft_dump_register(skb
, NFTA_NAT_REG_PROTO_MAX
,
235 priv
->sreg_proto_max
))
236 goto nla_put_failure
;
239 if (priv
->flags
!= 0) {
240 if (nla_put_be32(skb
, NFTA_NAT_FLAGS
, htonl(priv
->flags
)))
241 goto nla_put_failure
;
251 nft_nat_destroy(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
)
253 const struct nft_nat
*priv
= nft_expr_priv(expr
);
255 nf_ct_netns_put(ctx
->net
, priv
->family
);
258 static struct nft_expr_type nft_nat_type
;
259 static const struct nft_expr_ops nft_nat_ops
= {
260 .type
= &nft_nat_type
,
261 .size
= NFT_EXPR_SIZE(sizeof(struct nft_nat
)),
262 .eval
= nft_nat_eval
,
263 .init
= nft_nat_init
,
264 .destroy
= nft_nat_destroy
,
265 .dump
= nft_nat_dump
,
266 .validate
= nft_nat_validate
,
269 static struct nft_expr_type nft_nat_type __read_mostly
= {
272 .policy
= nft_nat_policy
,
273 .maxattr
= NFTA_NAT_MAX
,
274 .owner
= THIS_MODULE
,
277 #ifdef CONFIG_NF_TABLES_INET
278 static void nft_nat_inet_eval(const struct nft_expr
*expr
,
279 struct nft_regs
*regs
,
280 const struct nft_pktinfo
*pkt
)
282 const struct nft_nat
*priv
= nft_expr_priv(expr
);
284 if (priv
->family
== nft_pf(pkt
))
285 nft_nat_eval(expr
, regs
, pkt
);
288 static const struct nft_expr_ops nft_nat_inet_ops
= {
289 .type
= &nft_nat_type
,
290 .size
= NFT_EXPR_SIZE(sizeof(struct nft_nat
)),
291 .eval
= nft_nat_inet_eval
,
292 .init
= nft_nat_init
,
293 .destroy
= nft_nat_destroy
,
294 .dump
= nft_nat_dump
,
295 .validate
= nft_nat_validate
,
298 static struct nft_expr_type nft_inet_nat_type __read_mostly
= {
300 .family
= NFPROTO_INET
,
301 .ops
= &nft_nat_inet_ops
,
302 .policy
= nft_nat_policy
,
303 .maxattr
= NFTA_NAT_MAX
,
304 .owner
= THIS_MODULE
,
307 static int nft_nat_inet_module_init(void)
309 return nft_register_expr(&nft_inet_nat_type
);
312 static void nft_nat_inet_module_exit(void)
314 nft_unregister_expr(&nft_inet_nat_type
);
317 static int nft_nat_inet_module_init(void) { return 0; }
318 static void nft_nat_inet_module_exit(void) { }
321 static int __init
nft_nat_module_init(void)
323 int ret
= nft_nat_inet_module_init();
328 ret
= nft_register_expr(&nft_nat_type
);
330 nft_nat_inet_module_exit();
335 static void __exit
nft_nat_module_exit(void)
337 nft_nat_inet_module_exit();
338 nft_unregister_expr(&nft_nat_type
);
341 module_init(nft_nat_module_init
);
342 module_exit(nft_nat_module_exit
);
344 MODULE_LICENSE("GPL");
345 MODULE_AUTHOR("Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>");
346 MODULE_ALIAS_NFT_EXPR("nat");