1 #include <linux/init.h>
2 #include <linux/kernel.h>
3 #include <linux/netdevice.h>
4 #include <net/net_namespace.h>
5 #include <net/netfilter/nf_tables.h>
6 #include <linux/netfilter_ipv4.h>
7 #include <linux/netfilter_ipv6.h>
8 #include <linux/netfilter_bridge.h>
9 #include <linux/netfilter_arp.h>
10 #include <net/netfilter/nf_tables_ipv4.h>
11 #include <net/netfilter/nf_tables_ipv6.h>
13 #ifdef CONFIG_NF_TABLES_IPV4
14 static unsigned int nft_do_chain_ipv4(void *priv
,
16 const struct nf_hook_state
*state
)
18 struct nft_pktinfo pkt
;
20 nft_set_pktinfo(&pkt
, skb
, state
);
21 nft_set_pktinfo_ipv4(&pkt
);
23 return nft_do_chain(&pkt
, priv
);
26 static const struct nft_chain_type nft_chain_filter_ipv4
= {
28 .type
= NFT_CHAIN_T_DEFAULT
,
29 .family
= NFPROTO_IPV4
,
30 .hook_mask
= (1 << NF_INET_LOCAL_IN
) |
31 (1 << NF_INET_LOCAL_OUT
) |
32 (1 << NF_INET_FORWARD
) |
33 (1 << NF_INET_PRE_ROUTING
) |
34 (1 << NF_INET_POST_ROUTING
),
36 [NF_INET_LOCAL_IN
] = nft_do_chain_ipv4
,
37 [NF_INET_LOCAL_OUT
] = nft_do_chain_ipv4
,
38 [NF_INET_FORWARD
] = nft_do_chain_ipv4
,
39 [NF_INET_PRE_ROUTING
] = nft_do_chain_ipv4
,
40 [NF_INET_POST_ROUTING
] = nft_do_chain_ipv4
,
44 static void nft_chain_filter_ipv4_init(void)
46 nft_register_chain_type(&nft_chain_filter_ipv4
);
48 static void nft_chain_filter_ipv4_fini(void)
50 nft_unregister_chain_type(&nft_chain_filter_ipv4
);
54 static inline void nft_chain_filter_ipv4_init(void) {}
55 static inline void nft_chain_filter_ipv4_fini(void) {}
56 #endif /* CONFIG_NF_TABLES_IPV4 */
58 #ifdef CONFIG_NF_TABLES_ARP
59 static unsigned int nft_do_chain_arp(void *priv
, struct sk_buff
*skb
,
60 const struct nf_hook_state
*state
)
62 struct nft_pktinfo pkt
;
64 nft_set_pktinfo(&pkt
, skb
, state
);
65 nft_set_pktinfo_unspec(&pkt
);
67 return nft_do_chain(&pkt
, priv
);
70 static const struct nft_chain_type nft_chain_filter_arp
= {
72 .type
= NFT_CHAIN_T_DEFAULT
,
73 .family
= NFPROTO_ARP
,
75 .hook_mask
= (1 << NF_ARP_IN
) |
78 [NF_ARP_IN
] = nft_do_chain_arp
,
79 [NF_ARP_OUT
] = nft_do_chain_arp
,
83 static void nft_chain_filter_arp_init(void)
85 nft_register_chain_type(&nft_chain_filter_arp
);
88 static void nft_chain_filter_arp_fini(void)
90 nft_unregister_chain_type(&nft_chain_filter_arp
);
93 static inline void nft_chain_filter_arp_init(void) {}
94 static inline void nft_chain_filter_arp_fini(void) {}
95 #endif /* CONFIG_NF_TABLES_ARP */
97 #ifdef CONFIG_NF_TABLES_IPV6
98 static unsigned int nft_do_chain_ipv6(void *priv
,
100 const struct nf_hook_state
*state
)
102 struct nft_pktinfo pkt
;
104 nft_set_pktinfo(&pkt
, skb
, state
);
105 nft_set_pktinfo_ipv6(&pkt
);
107 return nft_do_chain(&pkt
, priv
);
110 static const struct nft_chain_type nft_chain_filter_ipv6
= {
112 .type
= NFT_CHAIN_T_DEFAULT
,
113 .family
= NFPROTO_IPV6
,
114 .hook_mask
= (1 << NF_INET_LOCAL_IN
) |
115 (1 << NF_INET_LOCAL_OUT
) |
116 (1 << NF_INET_FORWARD
) |
117 (1 << NF_INET_PRE_ROUTING
) |
118 (1 << NF_INET_POST_ROUTING
),
120 [NF_INET_LOCAL_IN
] = nft_do_chain_ipv6
,
121 [NF_INET_LOCAL_OUT
] = nft_do_chain_ipv6
,
122 [NF_INET_FORWARD
] = nft_do_chain_ipv6
,
123 [NF_INET_PRE_ROUTING
] = nft_do_chain_ipv6
,
124 [NF_INET_POST_ROUTING
] = nft_do_chain_ipv6
,
128 static void nft_chain_filter_ipv6_init(void)
130 nft_register_chain_type(&nft_chain_filter_ipv6
);
133 static void nft_chain_filter_ipv6_fini(void)
135 nft_unregister_chain_type(&nft_chain_filter_ipv6
);
138 static inline void nft_chain_filter_ipv6_init(void) {}
139 static inline void nft_chain_filter_ipv6_fini(void) {}
140 #endif /* CONFIG_NF_TABLES_IPV6 */
142 #ifdef CONFIG_NF_TABLES_INET
143 static unsigned int nft_do_chain_inet(void *priv
, struct sk_buff
*skb
,
144 const struct nf_hook_state
*state
)
146 struct nft_pktinfo pkt
;
148 nft_set_pktinfo(&pkt
, skb
, state
);
152 nft_set_pktinfo_ipv4(&pkt
);
155 nft_set_pktinfo_ipv6(&pkt
);
161 return nft_do_chain(&pkt
, priv
);
164 static unsigned int nft_do_chain_inet_ingress(void *priv
, struct sk_buff
*skb
,
165 const struct nf_hook_state
*state
)
167 struct nf_hook_state ingress_state
= *state
;
168 struct nft_pktinfo pkt
;
170 switch (skb
->protocol
) {
171 case htons(ETH_P_IP
):
172 /* Original hook is NFPROTO_NETDEV and NF_NETDEV_INGRESS. */
173 ingress_state
.pf
= NFPROTO_IPV4
;
174 ingress_state
.hook
= NF_INET_INGRESS
;
175 nft_set_pktinfo(&pkt
, skb
, &ingress_state
);
177 if (nft_set_pktinfo_ipv4_ingress(&pkt
) < 0)
180 case htons(ETH_P_IPV6
):
181 ingress_state
.pf
= NFPROTO_IPV6
;
182 ingress_state
.hook
= NF_INET_INGRESS
;
183 nft_set_pktinfo(&pkt
, skb
, &ingress_state
);
185 if (nft_set_pktinfo_ipv6_ingress(&pkt
) < 0)
192 return nft_do_chain(&pkt
, priv
);
195 static const struct nft_chain_type nft_chain_filter_inet
= {
197 .type
= NFT_CHAIN_T_DEFAULT
,
198 .family
= NFPROTO_INET
,
199 .hook_mask
= (1 << NF_INET_INGRESS
) |
200 (1 << NF_INET_LOCAL_IN
) |
201 (1 << NF_INET_LOCAL_OUT
) |
202 (1 << NF_INET_FORWARD
) |
203 (1 << NF_INET_PRE_ROUTING
) |
204 (1 << NF_INET_POST_ROUTING
),
206 [NF_INET_INGRESS
] = nft_do_chain_inet_ingress
,
207 [NF_INET_LOCAL_IN
] = nft_do_chain_inet
,
208 [NF_INET_LOCAL_OUT
] = nft_do_chain_inet
,
209 [NF_INET_FORWARD
] = nft_do_chain_inet
,
210 [NF_INET_PRE_ROUTING
] = nft_do_chain_inet
,
211 [NF_INET_POST_ROUTING
] = nft_do_chain_inet
,
215 static void nft_chain_filter_inet_init(void)
217 nft_register_chain_type(&nft_chain_filter_inet
);
220 static void nft_chain_filter_inet_fini(void)
222 nft_unregister_chain_type(&nft_chain_filter_inet
);
225 static inline void nft_chain_filter_inet_init(void) {}
226 static inline void nft_chain_filter_inet_fini(void) {}
227 #endif /* CONFIG_NF_TABLES_IPV6 */
229 #if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE)
231 nft_do_chain_bridge(void *priv
,
233 const struct nf_hook_state
*state
)
235 struct nft_pktinfo pkt
;
237 nft_set_pktinfo(&pkt
, skb
, state
);
239 switch (eth_hdr(skb
)->h_proto
) {
240 case htons(ETH_P_IP
):
241 nft_set_pktinfo_ipv4_validate(&pkt
);
243 case htons(ETH_P_IPV6
):
244 nft_set_pktinfo_ipv6_validate(&pkt
);
247 nft_set_pktinfo_unspec(&pkt
);
251 return nft_do_chain(&pkt
, priv
);
254 static const struct nft_chain_type nft_chain_filter_bridge
= {
256 .type
= NFT_CHAIN_T_DEFAULT
,
257 .family
= NFPROTO_BRIDGE
,
258 .hook_mask
= (1 << NF_BR_PRE_ROUTING
) |
259 (1 << NF_BR_LOCAL_IN
) |
260 (1 << NF_BR_FORWARD
) |
261 (1 << NF_BR_LOCAL_OUT
) |
262 (1 << NF_BR_POST_ROUTING
),
264 [NF_BR_PRE_ROUTING
] = nft_do_chain_bridge
,
265 [NF_BR_LOCAL_IN
] = nft_do_chain_bridge
,
266 [NF_BR_FORWARD
] = nft_do_chain_bridge
,
267 [NF_BR_LOCAL_OUT
] = nft_do_chain_bridge
,
268 [NF_BR_POST_ROUTING
] = nft_do_chain_bridge
,
272 static void nft_chain_filter_bridge_init(void)
274 nft_register_chain_type(&nft_chain_filter_bridge
);
277 static void nft_chain_filter_bridge_fini(void)
279 nft_unregister_chain_type(&nft_chain_filter_bridge
);
282 static inline void nft_chain_filter_bridge_init(void) {}
283 static inline void nft_chain_filter_bridge_fini(void) {}
284 #endif /* CONFIG_NF_TABLES_BRIDGE */
286 #ifdef CONFIG_NF_TABLES_NETDEV
287 static unsigned int nft_do_chain_netdev(void *priv
, struct sk_buff
*skb
,
288 const struct nf_hook_state
*state
)
290 struct nft_pktinfo pkt
;
292 nft_set_pktinfo(&pkt
, skb
, state
);
294 switch (skb
->protocol
) {
295 case htons(ETH_P_IP
):
296 nft_set_pktinfo_ipv4_validate(&pkt
);
298 case htons(ETH_P_IPV6
):
299 nft_set_pktinfo_ipv6_validate(&pkt
);
302 nft_set_pktinfo_unspec(&pkt
);
306 return nft_do_chain(&pkt
, priv
);
309 static const struct nft_chain_type nft_chain_filter_netdev
= {
311 .type
= NFT_CHAIN_T_DEFAULT
,
312 .family
= NFPROTO_NETDEV
,
313 .hook_mask
= (1 << NF_NETDEV_INGRESS
) |
314 (1 << NF_NETDEV_EGRESS
),
316 [NF_NETDEV_INGRESS
] = nft_do_chain_netdev
,
317 [NF_NETDEV_EGRESS
] = nft_do_chain_netdev
,
321 static void nft_netdev_event(unsigned long event
, struct net_device
*dev
,
322 struct nft_base_chain
*basechain
)
324 struct nft_hook
*hook
;
326 list_for_each_entry(hook
, &basechain
->hook_list
, list
) {
327 if (hook
->ops
.dev
!= dev
)
330 if (!(basechain
->chain
.table
->flags
& NFT_TABLE_F_DORMANT
))
331 nf_unregister_net_hook(dev_net(dev
), &hook
->ops
);
333 list_del_rcu(&hook
->list
);
334 kfree_rcu(hook
, rcu
);
339 static int nf_tables_netdev_event(struct notifier_block
*this,
340 unsigned long event
, void *ptr
)
342 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
343 struct nft_base_chain
*basechain
;
344 struct nftables_pernet
*nft_net
;
345 struct nft_chain
*chain
;
346 struct nft_table
*table
;
348 if (event
!= NETDEV_UNREGISTER
)
351 nft_net
= nft_pernet(dev_net(dev
));
352 mutex_lock(&nft_net
->commit_mutex
);
353 list_for_each_entry(table
, &nft_net
->tables
, list
) {
354 if (table
->family
!= NFPROTO_NETDEV
&&
355 table
->family
!= NFPROTO_INET
)
358 list_for_each_entry(chain
, &table
->chains
, list
) {
359 if (!nft_is_base_chain(chain
))
362 basechain
= nft_base_chain(chain
);
363 if (table
->family
== NFPROTO_INET
&&
364 basechain
->ops
.hooknum
!= NF_INET_INGRESS
)
367 nft_netdev_event(event
, dev
, basechain
);
370 mutex_unlock(&nft_net
->commit_mutex
);
375 static struct notifier_block nf_tables_netdev_notifier
= {
376 .notifier_call
= nf_tables_netdev_event
,
379 static int nft_chain_filter_netdev_init(void)
383 nft_register_chain_type(&nft_chain_filter_netdev
);
385 err
= register_netdevice_notifier(&nf_tables_netdev_notifier
);
387 goto err_register_netdevice_notifier
;
391 err_register_netdevice_notifier
:
392 nft_unregister_chain_type(&nft_chain_filter_netdev
);
397 static void nft_chain_filter_netdev_fini(void)
399 nft_unregister_chain_type(&nft_chain_filter_netdev
);
400 unregister_netdevice_notifier(&nf_tables_netdev_notifier
);
403 static inline int nft_chain_filter_netdev_init(void) { return 0; }
404 static inline void nft_chain_filter_netdev_fini(void) {}
405 #endif /* CONFIG_NF_TABLES_NETDEV */
407 int __init
nft_chain_filter_init(void)
411 err
= nft_chain_filter_netdev_init();
415 nft_chain_filter_ipv4_init();
416 nft_chain_filter_ipv6_init();
417 nft_chain_filter_arp_init();
418 nft_chain_filter_inet_init();
419 nft_chain_filter_bridge_init();
424 void nft_chain_filter_fini(void)
426 nft_chain_filter_bridge_fini();
427 nft_chain_filter_inet_fini();
428 nft_chain_filter_arp_fini();
429 nft_chain_filter_ipv6_fini();
430 nft_chain_filter_ipv4_fini();
431 nft_chain_filter_netdev_fini();