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);
292 case NETDEV_UNREGISTER:
293 if (strcmp(basechain->dev_name, dev->name) != 0)
296 /* UNREGISTER events are also happpening on netns exit.
298 * Altough nf_tables core releases all tables/chains, only
299 * this event handler provides guarantee that
300 * basechain.ops->dev is still accessible, so we cannot
301 * skip exiting net namespaces.
303 __nft_release_basechain(ctx);
305 case NETDEV_CHANGENAME:
306 if (dev->ifindex != basechain->ops.dev->ifindex)
309 strncpy(basechain->dev_name, dev->name, IFNAMSIZ);
314 static int nf_tables_netdev_event(struct notifier_block *this,
315 unsigned long event, void *ptr)
317 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
318 struct nft_table *table;
319 struct nft_chain *chain, *nr;
320 struct nft_ctx ctx = {
324 if (event != NETDEV_UNREGISTER &&
325 event != NETDEV_CHANGENAME)
328 mutex_lock(&ctx.net->nft.commit_mutex);
329 list_for_each_entry(table, &ctx.net->nft.tables, list) {
330 if (table->family != NFPROTO_NETDEV)
333 ctx.family = table->family;
335 list_for_each_entry_safe(chain, nr, &table->chains, list) {
336 if (!nft_is_base_chain(chain))
340 nft_netdev_event(event, dev, &ctx);
343 mutex_unlock(&ctx.net->nft.commit_mutex);
348 static struct notifier_block nf_tables_netdev_notifier = {
349 .notifier_call = nf_tables_netdev_event,
352 static int nft_chain_filter_netdev_init(void)
356 nft_register_chain_type(&nft_chain_filter_netdev);
358 err = register_netdevice_notifier(&nf_tables_netdev_notifier);
360 goto err_register_netdevice_notifier;
364 err_register_netdevice_notifier:
365 nft_unregister_chain_type(&nft_chain_filter_netdev);
370 static void nft_chain_filter_netdev_fini(void)
372 nft_unregister_chain_type(&nft_chain_filter_netdev);
373 unregister_netdevice_notifier(&nf_tables_netdev_notifier);
376 static inline int nft_chain_filter_netdev_init(void) { return 0; }
377 static inline void nft_chain_filter_netdev_fini(void) {}
378 #endif /* CONFIG_NF_TABLES_NETDEV */
380 int __init nft_chain_filter_init(void)
384 err = nft_chain_filter_netdev_init();
388 nft_chain_filter_ipv4_init();
389 nft_chain_filter_ipv6_init();
390 nft_chain_filter_arp_init();
391 nft_chain_filter_inet_init();
392 nft_chain_filter_bridge_init();
397 void nft_chain_filter_fini(void)
399 nft_chain_filter_bridge_fini();
400 nft_chain_filter_inet_fini();
401 nft_chain_filter_arp_fini();
402 nft_chain_filter_ipv6_fini();
403 nft_chain_filter_ipv4_fini();
404 nft_chain_filter_netdev_fini();