summaryrefslogtreecommitdiff
path: root/net/netfilter/nft_chain_nat.c
blob: 40e230d8b712e68bc49ca0ab555de2ac213be3e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: GPL-2.0

#include <linux/module.h>
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_ipv4.h>
#include <net/netfilter/nf_tables_ipv6.h>

static unsigned int nft_nat_do_chain(void *priv, struct sk_buff *skb,
				     const struct nf_hook_state *state)
{
	struct nft_pktinfo pkt;

	nft_set_pktinfo(&pkt, skb, state);

	switch (state->pf) {
#ifdef CONFIG_NF_TABLES_IPV4
	case NFPROTO_IPV4:
		nft_set_pktinfo_ipv4(&pkt);
		break;
#endif
#ifdef CONFIG_NF_TABLES_IPV6
	case NFPROTO_IPV6:
		nft_set_pktinfo_ipv6(&pkt);
		break;
#endif
	default:
		break;
	}

	return nft_do_chain(&pkt, priv);
}

#ifdef CONFIG_NF_TABLES_IPV4
static const struct nft_chain_type nft_chain_nat_ipv4 = {
	.name		= "nat",
	.type		= NFT_CHAIN_T_NAT,
	.family		= NFPROTO_IPV4,
	.owner		= THIS_MODULE,
	.hook_mask	= (1 << NF_INET_PRE_ROUTING) |
			  (1 << NF_INET_POST_ROUTING) |
			  (1 << NF_INET_LOCAL_OUT) |
			  (1 << NF_INET_LOCAL_IN),
	.hooks		= {
		[NF_INET_PRE_ROUTING]	= nft_nat_do_chain,
		[NF_INET_POST_ROUTING]	= nft_nat_do_chain,
		[NF_INET_LOCAL_OUT]	= nft_nat_do_chain,
		[NF_INET_LOCAL_IN]	= nft_nat_do_chain,
	},
	.ops_register = nf_nat_ipv4_register_fn,
	.ops_unregister = nf_nat_ipv4_unregister_fn,
};
#endif

#ifdef CONFIG_NF_TABLES_IPV6
static const struct nft_chain_type nft_chain_nat_ipv6 = {
	.name		= "nat",
	.type		= NFT_CHAIN_T_NAT,
	.family		= NFPROTO_IPV6,
	.owner		= THIS_MODULE,
	.hook_mask	= (1 << NF_INET_PRE_ROUTING) |
			  (1 << NF_INET_POST_ROUTING) |
			  (1 << NF_INET_LOCAL_OUT) |
			  (1 << NF_INET_LOCAL_IN),
	.hooks		= {
		[NF_INET_PRE_ROUTING]	= nft_nat_do_chain,
		[NF_INET_POST_ROUTING]	= nft_nat_do_chain,
		[NF_INET_LOCAL_OUT]	= nft_nat_do_chain,
		[NF_INET_LOCAL_IN]	= nft_nat_do_chain,
	},
	.ops_register		= nf_nat_ipv6_register_fn,
	.ops_unregister		= nf_nat_ipv6_unregister_fn,
};
#endif

#ifdef CONFIG_NF_TABLES_INET
static int nft_nat_inet_reg(struct net *net, const struct nf_hook_ops *ops)
{
	return nf_nat_inet_register_fn(net, ops);
}

static void nft_nat_inet_unreg(struct net *net, const struct nf_hook_ops *ops)
{
	nf_nat_inet_unregister_fn(net, ops);
}

static const struct nft_chain_type nft_chain_nat_inet = {
	.name		= "nat",
	.type		= NFT_CHAIN_T_NAT,
	.family		= NFPROTO_INET,
	.owner		= THIS_MODULE,
	.hook_mask	= (1 << NF_INET_PRE_ROUTING) |
			  (1 << NF_INET_LOCAL_IN) |
			  (1 << NF_INET_LOCAL_OUT) |
			  (1 << NF_INET_POST_ROUTING),
	.hooks		= {
		[NF_INET_PRE_ROUTING]	= nft_nat_do_chain,
		[NF_INET_LOCAL_IN]	= nft_nat_do_chain,
		[NF_INET_LOCAL_OUT]	= nft_nat_do_chain,
		[NF_INET_POST_ROUTING]	= nft_nat_do_chain,
	},
	.ops_register		= nft_nat_inet_reg,
	.ops_unregister		= nft_nat_inet_unreg,
};
#endif

static int __init nft_chain_nat_init(void)
{
#ifdef CONFIG_NF_TABLES_IPV6
	nft_register_chain_type(&nft_chain_nat_ipv6);
#endif
#ifdef CONFIG_NF_TABLES_IPV4
	nft_register_chain_type(&nft_chain_nat_ipv4);
#endif
#ifdef CONFIG_NF_TABLES_INET
	nft_register_chain_type(&nft_chain_nat_inet);
#endif

	return 0;
}

static void __exit nft_chain_nat_exit(void)
{
#ifdef CONFIG_NF_TABLES_IPV4
	nft_unregister_chain_type(&nft_chain_nat_ipv4);
#endif
#ifdef CONFIG_NF_TABLES_IPV6
	nft_unregister_chain_type(&nft_chain_nat_ipv6);
#endif
#ifdef CONFIG_NF_TABLES_INET
	nft_unregister_chain_type(&nft_chain_nat_inet);
#endif
}

module_init(nft_chain_nat_init);
module_exit(nft_chain_nat_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("nftables network address translation support");
#ifdef CONFIG_NF_TABLES_IPV4
MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat");
#endif
#ifdef CONFIG_NF_TABLES_IPV6
MODULE_ALIAS_NFT_CHAIN(AF_INET6, "nat");
#endif
#ifdef CONFIG_NF_TABLES_INET
MODULE_ALIAS_NFT_CHAIN(1, "nat");	/* NFPROTO_INET */
#endif