1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
5 * Based on Rusty Russell's IPv4 NAT code. Development of IPv6 NAT
9 #include <linux/module.h>
10 #include <linux/netfilter.h>
11 #include <linux/netfilter_ipv6.h>
12 #include <linux/netfilter_ipv6/ip6_tables.h>
13 #include <linux/ipv6.h>
16 #include <net/netfilter/nf_nat.h>
18 struct ip6table_nat_pernet
{
19 struct nf_hook_ops
*nf_nat_ops
;
22 static unsigned int ip6table_nat_net_id __read_mostly
;
24 static const struct xt_table nf_nat_ipv6_table
= {
26 .valid_hooks
= (1 << NF_INET_PRE_ROUTING
) |
27 (1 << NF_INET_POST_ROUTING
) |
28 (1 << NF_INET_LOCAL_OUT
) |
29 (1 << NF_INET_LOCAL_IN
),
34 static const struct nf_hook_ops nf_nat_ipv6_ops
[] = {
36 .hook
= ip6t_do_table
,
38 .hooknum
= NF_INET_PRE_ROUTING
,
39 .priority
= NF_IP6_PRI_NAT_DST
,
42 .hook
= ip6t_do_table
,
44 .hooknum
= NF_INET_POST_ROUTING
,
45 .priority
= NF_IP6_PRI_NAT_SRC
,
48 .hook
= ip6t_do_table
,
50 .hooknum
= NF_INET_LOCAL_OUT
,
51 .priority
= NF_IP6_PRI_NAT_DST
,
54 .hook
= ip6t_do_table
,
56 .hooknum
= NF_INET_LOCAL_IN
,
57 .priority
= NF_IP6_PRI_NAT_SRC
,
61 static int ip6t_nat_register_lookups(struct net
*net
)
63 struct ip6table_nat_pernet
*xt_nat_net
;
64 struct nf_hook_ops
*ops
;
65 struct xt_table
*table
;
68 table
= xt_find_table(net
, NFPROTO_IPV6
, "nat");
69 if (WARN_ON_ONCE(!table
))
72 xt_nat_net
= net_generic(net
, ip6table_nat_net_id
);
73 ops
= kmemdup(nf_nat_ipv6_ops
, sizeof(nf_nat_ipv6_ops
), GFP_KERNEL
);
77 for (i
= 0; i
< ARRAY_SIZE(nf_nat_ipv6_ops
); i
++) {
79 ret
= nf_nat_ipv6_register_fn(net
, &ops
[i
]);
82 nf_nat_ipv6_unregister_fn(net
, &ops
[--i
]);
89 xt_nat_net
->nf_nat_ops
= ops
;
93 static void ip6t_nat_unregister_lookups(struct net
*net
)
95 struct ip6table_nat_pernet
*xt_nat_net
= net_generic(net
, ip6table_nat_net_id
);
96 struct nf_hook_ops
*ops
= xt_nat_net
->nf_nat_ops
;
102 for (i
= 0; i
< ARRAY_SIZE(nf_nat_ipv6_ops
); i
++)
103 nf_nat_ipv6_unregister_fn(net
, &ops
[i
]);
108 static int ip6table_nat_table_init(struct net
*net
)
110 struct ip6t_replace
*repl
;
113 repl
= ip6t_alloc_initial_table(&nf_nat_ipv6_table
);
116 ret
= ip6t_register_table(net
, &nf_nat_ipv6_table
, repl
,
123 ret
= ip6t_nat_register_lookups(net
);
125 ip6t_unregister_table_exit(net
, "nat");
131 static void __net_exit
ip6table_nat_net_pre_exit(struct net
*net
)
133 ip6t_nat_unregister_lookups(net
);
136 static void __net_exit
ip6table_nat_net_exit(struct net
*net
)
138 ip6t_unregister_table_exit(net
, "nat");
141 static struct pernet_operations ip6table_nat_net_ops
= {
142 .pre_exit
= ip6table_nat_net_pre_exit
,
143 .exit
= ip6table_nat_net_exit
,
144 .id
= &ip6table_nat_net_id
,
145 .size
= sizeof(struct ip6table_nat_pernet
),
148 static int __init
ip6table_nat_init(void)
152 /* net->gen->ptr[ip6table_nat_net_id] must be allocated
153 * before calling ip6t_nat_register_lookups().
155 ret
= register_pernet_subsys(&ip6table_nat_net_ops
);
159 ret
= xt_register_template(&nf_nat_ipv6_table
,
160 ip6table_nat_table_init
);
162 unregister_pernet_subsys(&ip6table_nat_net_ops
);
167 static void __exit
ip6table_nat_exit(void)
169 xt_unregister_template(&nf_nat_ipv6_table
);
170 unregister_pernet_subsys(&ip6table_nat_net_ops
);
173 module_init(ip6table_nat_init
);
174 module_exit(ip6table_nat_exit
);
176 MODULE_LICENSE("GPL");
177 MODULE_DESCRIPTION("Ip6tables legacy nat table");