Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nft_masq: add inet support

This allows use of a single masquerade rule in nat inet family
to handle both ipv4 and ipv6.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
071657d2 4806e975

+64
+64
net/netfilter/nft_masq.c
··· 218 218 static inline void nft_masq_module_exit_ipv6(void) {} 219 219 #endif 220 220 221 + #ifdef CONFIG_NF_TABLES_INET 222 + static void nft_masq_inet_eval(const struct nft_expr *expr, 223 + struct nft_regs *regs, 224 + const struct nft_pktinfo *pkt) 225 + { 226 + switch (nft_pf(pkt)) { 227 + case NFPROTO_IPV4: 228 + return nft_masq_ipv4_eval(expr, regs, pkt); 229 + case NFPROTO_IPV6: 230 + return nft_masq_ipv6_eval(expr, regs, pkt); 231 + } 232 + 233 + WARN_ON_ONCE(1); 234 + } 235 + 236 + static void 237 + nft_masq_inet_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 238 + { 239 + nf_ct_netns_put(ctx->net, NFPROTO_INET); 240 + } 241 + 242 + static struct nft_expr_type nft_masq_inet_type; 243 + static const struct nft_expr_ops nft_masq_inet_ops = { 244 + .type = &nft_masq_inet_type, 245 + .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 246 + .eval = nft_masq_inet_eval, 247 + .init = nft_masq_init, 248 + .destroy = nft_masq_inet_destroy, 249 + .dump = nft_masq_dump, 250 + .validate = nft_masq_validate, 251 + }; 252 + 253 + static struct nft_expr_type nft_masq_inet_type __read_mostly = { 254 + .family = NFPROTO_INET, 255 + .name = "masq", 256 + .ops = &nft_masq_inet_ops, 257 + .policy = nft_masq_policy, 258 + .maxattr = NFTA_MASQ_MAX, 259 + .owner = THIS_MODULE, 260 + }; 261 + 262 + static int __init nft_masq_module_init_inet(void) 263 + { 264 + return nft_register_expr(&nft_masq_inet_type); 265 + } 266 + 267 + static void nft_masq_module_exit_inet(void) 268 + { 269 + nft_unregister_expr(&nft_masq_inet_type); 270 + } 271 + #else 272 + static inline int nft_masq_module_init_inet(void) { return 0; } 273 + static inline void nft_masq_module_exit_inet(void) {} 274 + #endif 275 + 221 276 static int __init nft_masq_module_init(void) 222 277 { 223 278 int ret; ··· 281 226 if (ret < 0) 282 227 return ret; 283 228 229 + ret = nft_masq_module_init_inet(); 230 + if (ret < 0) { 231 + nft_masq_module_exit_ipv6(); 232 + return ret; 233 + } 234 + 284 235 ret = nft_register_expr(&nft_masq_ipv4_type); 285 236 if (ret < 0) { 237 + nft_masq_module_exit_inet(); 286 238 nft_masq_module_exit_ipv6(); 287 239 return ret; 288 240 } ··· 297 235 ret = nf_nat_masquerade_ipv4_register_notifier(); 298 236 if (ret < 0) { 299 237 nft_masq_module_exit_ipv6(); 238 + nft_masq_module_exit_inet(); 300 239 nft_unregister_expr(&nft_masq_ipv4_type); 301 240 return ret; 302 241 } ··· 308 245 static void __exit nft_masq_module_exit(void) 309 246 { 310 247 nft_masq_module_exit_ipv6(); 248 + nft_masq_module_exit_inet(); 311 249 nft_unregister_expr(&nft_masq_ipv4_type); 312 250 nf_nat_masquerade_ipv4_unregister_notifier(); 313 251 }