hc
2024-03-22 f63cd4c03ea42695d5f9b0e1798edd196923aae6
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
// 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, skb);
       break;
#endif
#ifdef CONFIG_NF_TABLES_IPV6
   case NFPROTO_IPV6:
       nft_set_pktinfo_ipv6(&pkt, skb);
       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");
#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