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
, skb
);
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
, skb
);
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
, skb
);
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
, skb
);
155 nft_set_pktinfo_ipv6(&pkt
, skb
);
161 return nft_do_chain(&pkt
, priv
);
164 static const struct nft_chain_type nft_chain_filter_inet
= {
166 .type
= NFT_CHAIN_T_DEFAULT
,
167 .family
= NFPROTO_INET
,
168 .hook_mask
= (1 << NF_INET_LOCAL_IN
) |
169 (1 << NF_INET_LOCAL_OUT
) |
170 (1 << NF_INET_FORWARD
) |
171 (1 << NF_INET_PRE_ROUTING
) |
172 (1 << NF_INET_POST_ROUTING
),
174 [NF_INET_LOCAL_IN
] = nft_do_chain_inet
,
175 [NF_INET_LOCAL_OUT
] = nft_do_chain_inet
,
176 [NF_INET_FORWARD
] = nft_do_chain_inet
,
177 [NF_INET_PRE_ROUTING
] = nft_do_chain_inet
,
178 [NF_INET_POST_ROUTING
] = nft_do_chain_inet
,
182 static void nft_chain_filter_inet_init(void)
184 nft_register_chain_type(&nft_chain_filter_inet
);
187 static void nft_chain_filter_inet_fini(void)
189 nft_unregister_chain_type(&nft_chain_filter_inet
);
192 static inline void nft_chain_filter_inet_init(void) {}
193 static inline void nft_chain_filter_inet_fini(void) {}
194 #endif /* CONFIG_NF_TABLES_IPV6 */
196 #if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE)
198 nft_do_chain_bridge(void *priv
,
200 const struct nf_hook_state
*state
)
202 struct nft_pktinfo pkt
;
204 nft_set_pktinfo(&pkt
, skb
, state
);
206 switch (eth_hdr(skb
)->h_proto
) {
207 case htons(ETH_P_IP
):
208 nft_set_pktinfo_ipv4_validate(&pkt
, skb
);
210 case htons(ETH_P_IPV6
):
211 nft_set_pktinfo_ipv6_validate(&pkt
, skb
);
214 nft_set_pktinfo_unspec(&pkt
, skb
);
218 return nft_do_chain(&pkt
, priv
);
221 static const struct nft_chain_type nft_chain_filter_bridge
= {
223 .type
= NFT_CHAIN_T_DEFAULT
,
224 .family
= NFPROTO_BRIDGE
,
225 .hook_mask
= (1 << NF_BR_PRE_ROUTING
) |
226 (1 << NF_BR_LOCAL_IN
) |
227 (1 << NF_BR_FORWARD
) |
228 (1 << NF_BR_LOCAL_OUT
) |
229 (1 << NF_BR_POST_ROUTING
),
231 [NF_BR_PRE_ROUTING
] = nft_do_chain_bridge
,
232 [NF_BR_LOCAL_IN
] = nft_do_chain_bridge
,
233 [NF_BR_FORWARD
] = nft_do_chain_bridge
,
234 [NF_BR_LOCAL_OUT
] = nft_do_chain_bridge
,
235 [NF_BR_POST_ROUTING
] = nft_do_chain_bridge
,
239 static void nft_chain_filter_bridge_init(void)
241 nft_register_chain_type(&nft_chain_filter_bridge
);
244 static void nft_chain_filter_bridge_fini(void)
246 nft_unregister_chain_type(&nft_chain_filter_bridge
);
249 static inline void nft_chain_filter_bridge_init(void) {}
250 static inline void nft_chain_filter_bridge_fini(void) {}
251 #endif /* CONFIG_NF_TABLES_BRIDGE */
253 #ifdef CONFIG_NF_TABLES_NETDEV
254 static unsigned int nft_do_chain_netdev(void *priv
, struct sk_buff
*skb
,
255 const struct nf_hook_state
*state
)
257 struct nft_pktinfo pkt
;
259 nft_set_pktinfo(&pkt
, skb
, state
);
261 switch (skb
->protocol
) {
262 case htons(ETH_P_IP
):
263 nft_set_pktinfo_ipv4_validate(&pkt
, skb
);
265 case htons(ETH_P_IPV6
):
266 nft_set_pktinfo_ipv6_validate(&pkt
, skb
);
269 nft_set_pktinfo_unspec(&pkt
, skb
);
273 return nft_do_chain(&pkt
, priv
);
276 static const struct nft_chain_type nft_chain_filter_netdev
= {
278 .type
= NFT_CHAIN_T_DEFAULT
,
279 .family
= NFPROTO_NETDEV
,
280 .hook_mask
= (1 << NF_NETDEV_INGRESS
),
282 [NF_NETDEV_INGRESS
] = nft_do_chain_netdev
,
286 static void nft_netdev_event(unsigned long event
, struct net_device
*dev
,
289 struct nft_base_chain
*basechain
= nft_base_chain(ctx
->chain
);
290 struct nft_hook
*hook
, *found
= NULL
;
293 if (event
!= NETDEV_UNREGISTER
)
296 list_for_each_entry(hook
, &basechain
->hook_list
, list
) {
297 if (hook
->ops
.dev
== dev
)
306 nf_unregister_net_hook(ctx
->net
, &found
->ops
);
307 list_del_rcu(&found
->list
);
308 kfree_rcu(found
, rcu
);
312 /* UNREGISTER events are also happening on netns exit.
314 * Although nf_tables core releases all tables/chains, only this event
315 * handler provides guarantee that hook->ops.dev is still accessible,
316 * so we cannot skip exiting net namespaces.
318 __nft_release_basechain(ctx
);
321 static int nf_tables_netdev_event(struct notifier_block
*this,
322 unsigned long event
, void *ptr
)
324 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
325 struct nft_table
*table
;
326 struct nft_chain
*chain
, *nr
;
327 struct nft_ctx ctx
= {
331 if (event
!= NETDEV_UNREGISTER
&&
332 event
!= NETDEV_CHANGENAME
)
335 mutex_lock(&ctx
.net
->nft
.commit_mutex
);
336 list_for_each_entry(table
, &ctx
.net
->nft
.tables
, list
) {
337 if (table
->family
!= NFPROTO_NETDEV
)
340 ctx
.family
= table
->family
;
342 list_for_each_entry_safe(chain
, nr
, &table
->chains
, list
) {
343 if (!nft_is_base_chain(chain
))
347 nft_netdev_event(event
, dev
, &ctx
);
350 mutex_unlock(&ctx
.net
->nft
.commit_mutex
);
355 static struct notifier_block nf_tables_netdev_notifier
= {
356 .notifier_call
= nf_tables_netdev_event
,
359 static int nft_chain_filter_netdev_init(void)
363 nft_register_chain_type(&nft_chain_filter_netdev
);
365 err
= register_netdevice_notifier(&nf_tables_netdev_notifier
);
367 goto err_register_netdevice_notifier
;
371 err_register_netdevice_notifier
:
372 nft_unregister_chain_type(&nft_chain_filter_netdev
);
377 static void nft_chain_filter_netdev_fini(void)
379 nft_unregister_chain_type(&nft_chain_filter_netdev
);
380 unregister_netdevice_notifier(&nf_tables_netdev_notifier
);
383 static inline int nft_chain_filter_netdev_init(void) { return 0; }
384 static inline void nft_chain_filter_netdev_fini(void) {}
385 #endif /* CONFIG_NF_TABLES_NETDEV */
387 int __init
nft_chain_filter_init(void)
391 err
= nft_chain_filter_netdev_init();
395 nft_chain_filter_ipv4_init();
396 nft_chain_filter_ipv6_init();
397 nft_chain_filter_arp_init();
398 nft_chain_filter_inet_init();
399 nft_chain_filter_bridge_init();
404 void nft_chain_filter_fini(void)
406 nft_chain_filter_bridge_fini();
407 nft_chain_filter_inet_fini();
408 nft_chain_filter_arp_fini();
409 nft_chain_filter_ipv6_fini();
410 nft_chain_filter_ipv4_fini();
411 nft_chain_filter_netdev_fini();