0001 #include <linux/init.h>
0002 #include <linux/kernel.h>
0003 #include <linux/netdevice.h>
0004 #include <net/net_namespace.h>
0005 #include <net/netfilter/nf_tables.h>
0006 #include <linux/netfilter_ipv4.h>
0007 #include <linux/netfilter_ipv6.h>
0008 #include <linux/netfilter_bridge.h>
0009 #include <linux/netfilter_arp.h>
0010 #include <net/netfilter/nf_tables_ipv4.h>
0011 #include <net/netfilter/nf_tables_ipv6.h>
0012
0013 #ifdef CONFIG_NF_TABLES_IPV4
0014 static unsigned int nft_do_chain_ipv4(void *priv,
0015 struct sk_buff *skb,
0016 const struct nf_hook_state *state)
0017 {
0018 struct nft_pktinfo pkt;
0019
0020 nft_set_pktinfo(&pkt, skb, state);
0021 nft_set_pktinfo_ipv4(&pkt);
0022
0023 return nft_do_chain(&pkt, priv);
0024 }
0025
0026 static const struct nft_chain_type nft_chain_filter_ipv4 = {
0027 .name = "filter",
0028 .type = NFT_CHAIN_T_DEFAULT,
0029 .family = NFPROTO_IPV4,
0030 .hook_mask = (1 << NF_INET_LOCAL_IN) |
0031 (1 << NF_INET_LOCAL_OUT) |
0032 (1 << NF_INET_FORWARD) |
0033 (1 << NF_INET_PRE_ROUTING) |
0034 (1 << NF_INET_POST_ROUTING),
0035 .hooks = {
0036 [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
0037 [NF_INET_LOCAL_OUT] = nft_do_chain_ipv4,
0038 [NF_INET_FORWARD] = nft_do_chain_ipv4,
0039 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
0040 [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
0041 },
0042 };
0043
0044 static void nft_chain_filter_ipv4_init(void)
0045 {
0046 nft_register_chain_type(&nft_chain_filter_ipv4);
0047 }
0048 static void nft_chain_filter_ipv4_fini(void)
0049 {
0050 nft_unregister_chain_type(&nft_chain_filter_ipv4);
0051 }
0052
0053 #else
0054 static inline void nft_chain_filter_ipv4_init(void) {}
0055 static inline void nft_chain_filter_ipv4_fini(void) {}
0056 #endif
0057
0058 #ifdef CONFIG_NF_TABLES_ARP
0059 static unsigned int nft_do_chain_arp(void *priv, struct sk_buff *skb,
0060 const struct nf_hook_state *state)
0061 {
0062 struct nft_pktinfo pkt;
0063
0064 nft_set_pktinfo(&pkt, skb, state);
0065 nft_set_pktinfo_unspec(&pkt);
0066
0067 return nft_do_chain(&pkt, priv);
0068 }
0069
0070 static const struct nft_chain_type nft_chain_filter_arp = {
0071 .name = "filter",
0072 .type = NFT_CHAIN_T_DEFAULT,
0073 .family = NFPROTO_ARP,
0074 .owner = THIS_MODULE,
0075 .hook_mask = (1 << NF_ARP_IN) |
0076 (1 << NF_ARP_OUT),
0077 .hooks = {
0078 [NF_ARP_IN] = nft_do_chain_arp,
0079 [NF_ARP_OUT] = nft_do_chain_arp,
0080 },
0081 };
0082
0083 static void nft_chain_filter_arp_init(void)
0084 {
0085 nft_register_chain_type(&nft_chain_filter_arp);
0086 }
0087
0088 static void nft_chain_filter_arp_fini(void)
0089 {
0090 nft_unregister_chain_type(&nft_chain_filter_arp);
0091 }
0092 #else
0093 static inline void nft_chain_filter_arp_init(void) {}
0094 static inline void nft_chain_filter_arp_fini(void) {}
0095 #endif
0096
0097 #ifdef CONFIG_NF_TABLES_IPV6
0098 static unsigned int nft_do_chain_ipv6(void *priv,
0099 struct sk_buff *skb,
0100 const struct nf_hook_state *state)
0101 {
0102 struct nft_pktinfo pkt;
0103
0104 nft_set_pktinfo(&pkt, skb, state);
0105 nft_set_pktinfo_ipv6(&pkt);
0106
0107 return nft_do_chain(&pkt, priv);
0108 }
0109
0110 static const struct nft_chain_type nft_chain_filter_ipv6 = {
0111 .name = "filter",
0112 .type = NFT_CHAIN_T_DEFAULT,
0113 .family = NFPROTO_IPV6,
0114 .hook_mask = (1 << NF_INET_LOCAL_IN) |
0115 (1 << NF_INET_LOCAL_OUT) |
0116 (1 << NF_INET_FORWARD) |
0117 (1 << NF_INET_PRE_ROUTING) |
0118 (1 << NF_INET_POST_ROUTING),
0119 .hooks = {
0120 [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
0121 [NF_INET_LOCAL_OUT] = nft_do_chain_ipv6,
0122 [NF_INET_FORWARD] = nft_do_chain_ipv6,
0123 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6,
0124 [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
0125 },
0126 };
0127
0128 static void nft_chain_filter_ipv6_init(void)
0129 {
0130 nft_register_chain_type(&nft_chain_filter_ipv6);
0131 }
0132
0133 static void nft_chain_filter_ipv6_fini(void)
0134 {
0135 nft_unregister_chain_type(&nft_chain_filter_ipv6);
0136 }
0137 #else
0138 static inline void nft_chain_filter_ipv6_init(void) {}
0139 static inline void nft_chain_filter_ipv6_fini(void) {}
0140 #endif
0141
0142 #ifdef CONFIG_NF_TABLES_INET
0143 static unsigned int nft_do_chain_inet(void *priv, struct sk_buff *skb,
0144 const struct nf_hook_state *state)
0145 {
0146 struct nft_pktinfo pkt;
0147
0148 nft_set_pktinfo(&pkt, skb, state);
0149
0150 switch (state->pf) {
0151 case NFPROTO_IPV4:
0152 nft_set_pktinfo_ipv4(&pkt);
0153 break;
0154 case NFPROTO_IPV6:
0155 nft_set_pktinfo_ipv6(&pkt);
0156 break;
0157 default:
0158 break;
0159 }
0160
0161 return nft_do_chain(&pkt, priv);
0162 }
0163
0164 static unsigned int nft_do_chain_inet_ingress(void *priv, struct sk_buff *skb,
0165 const struct nf_hook_state *state)
0166 {
0167 struct nf_hook_state ingress_state = *state;
0168 struct nft_pktinfo pkt;
0169
0170 switch (skb->protocol) {
0171 case htons(ETH_P_IP):
0172
0173 ingress_state.pf = NFPROTO_IPV4;
0174 ingress_state.hook = NF_INET_INGRESS;
0175 nft_set_pktinfo(&pkt, skb, &ingress_state);
0176
0177 if (nft_set_pktinfo_ipv4_ingress(&pkt) < 0)
0178 return NF_DROP;
0179 break;
0180 case htons(ETH_P_IPV6):
0181 ingress_state.pf = NFPROTO_IPV6;
0182 ingress_state.hook = NF_INET_INGRESS;
0183 nft_set_pktinfo(&pkt, skb, &ingress_state);
0184
0185 if (nft_set_pktinfo_ipv6_ingress(&pkt) < 0)
0186 return NF_DROP;
0187 break;
0188 default:
0189 return NF_ACCEPT;
0190 }
0191
0192 return nft_do_chain(&pkt, priv);
0193 }
0194
0195 static const struct nft_chain_type nft_chain_filter_inet = {
0196 .name = "filter",
0197 .type = NFT_CHAIN_T_DEFAULT,
0198 .family = NFPROTO_INET,
0199 .hook_mask = (1 << NF_INET_INGRESS) |
0200 (1 << NF_INET_LOCAL_IN) |
0201 (1 << NF_INET_LOCAL_OUT) |
0202 (1 << NF_INET_FORWARD) |
0203 (1 << NF_INET_PRE_ROUTING) |
0204 (1 << NF_INET_POST_ROUTING),
0205 .hooks = {
0206 [NF_INET_INGRESS] = nft_do_chain_inet_ingress,
0207 [NF_INET_LOCAL_IN] = nft_do_chain_inet,
0208 [NF_INET_LOCAL_OUT] = nft_do_chain_inet,
0209 [NF_INET_FORWARD] = nft_do_chain_inet,
0210 [NF_INET_PRE_ROUTING] = nft_do_chain_inet,
0211 [NF_INET_POST_ROUTING] = nft_do_chain_inet,
0212 },
0213 };
0214
0215 static void nft_chain_filter_inet_init(void)
0216 {
0217 nft_register_chain_type(&nft_chain_filter_inet);
0218 }
0219
0220 static void nft_chain_filter_inet_fini(void)
0221 {
0222 nft_unregister_chain_type(&nft_chain_filter_inet);
0223 }
0224 #else
0225 static inline void nft_chain_filter_inet_init(void) {}
0226 static inline void nft_chain_filter_inet_fini(void) {}
0227 #endif
0228
0229 #if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE)
0230 static unsigned int
0231 nft_do_chain_bridge(void *priv,
0232 struct sk_buff *skb,
0233 const struct nf_hook_state *state)
0234 {
0235 struct nft_pktinfo pkt;
0236
0237 nft_set_pktinfo(&pkt, skb, state);
0238
0239 switch (eth_hdr(skb)->h_proto) {
0240 case htons(ETH_P_IP):
0241 nft_set_pktinfo_ipv4_validate(&pkt);
0242 break;
0243 case htons(ETH_P_IPV6):
0244 nft_set_pktinfo_ipv6_validate(&pkt);
0245 break;
0246 default:
0247 nft_set_pktinfo_unspec(&pkt);
0248 break;
0249 }
0250
0251 return nft_do_chain(&pkt, priv);
0252 }
0253
0254 static const struct nft_chain_type nft_chain_filter_bridge = {
0255 .name = "filter",
0256 .type = NFT_CHAIN_T_DEFAULT,
0257 .family = NFPROTO_BRIDGE,
0258 .hook_mask = (1 << NF_BR_PRE_ROUTING) |
0259 (1 << NF_BR_LOCAL_IN) |
0260 (1 << NF_BR_FORWARD) |
0261 (1 << NF_BR_LOCAL_OUT) |
0262 (1 << NF_BR_POST_ROUTING),
0263 .hooks = {
0264 [NF_BR_PRE_ROUTING] = nft_do_chain_bridge,
0265 [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
0266 [NF_BR_FORWARD] = nft_do_chain_bridge,
0267 [NF_BR_LOCAL_OUT] = nft_do_chain_bridge,
0268 [NF_BR_POST_ROUTING] = nft_do_chain_bridge,
0269 },
0270 };
0271
0272 static void nft_chain_filter_bridge_init(void)
0273 {
0274 nft_register_chain_type(&nft_chain_filter_bridge);
0275 }
0276
0277 static void nft_chain_filter_bridge_fini(void)
0278 {
0279 nft_unregister_chain_type(&nft_chain_filter_bridge);
0280 }
0281 #else
0282 static inline void nft_chain_filter_bridge_init(void) {}
0283 static inline void nft_chain_filter_bridge_fini(void) {}
0284 #endif
0285
0286 #ifdef CONFIG_NF_TABLES_NETDEV
0287 static unsigned int nft_do_chain_netdev(void *priv, struct sk_buff *skb,
0288 const struct nf_hook_state *state)
0289 {
0290 struct nft_pktinfo pkt;
0291
0292 nft_set_pktinfo(&pkt, skb, state);
0293
0294 switch (skb->protocol) {
0295 case htons(ETH_P_IP):
0296 nft_set_pktinfo_ipv4_validate(&pkt);
0297 break;
0298 case htons(ETH_P_IPV6):
0299 nft_set_pktinfo_ipv6_validate(&pkt);
0300 break;
0301 default:
0302 nft_set_pktinfo_unspec(&pkt);
0303 break;
0304 }
0305
0306 return nft_do_chain(&pkt, priv);
0307 }
0308
0309 static const struct nft_chain_type nft_chain_filter_netdev = {
0310 .name = "filter",
0311 .type = NFT_CHAIN_T_DEFAULT,
0312 .family = NFPROTO_NETDEV,
0313 .hook_mask = (1 << NF_NETDEV_INGRESS) |
0314 (1 << NF_NETDEV_EGRESS),
0315 .hooks = {
0316 [NF_NETDEV_INGRESS] = nft_do_chain_netdev,
0317 [NF_NETDEV_EGRESS] = nft_do_chain_netdev,
0318 },
0319 };
0320
0321 static void nft_netdev_event(unsigned long event, struct net_device *dev,
0322 struct nft_ctx *ctx)
0323 {
0324 struct nft_base_chain *basechain = nft_base_chain(ctx->chain);
0325 struct nft_hook *hook, *found = NULL;
0326 int n = 0;
0327
0328 if (event != NETDEV_UNREGISTER)
0329 return;
0330
0331 list_for_each_entry(hook, &basechain->hook_list, list) {
0332 if (hook->ops.dev == dev)
0333 found = hook;
0334
0335 n++;
0336 }
0337 if (!found)
0338 return;
0339
0340 if (n > 1) {
0341 nf_unregister_net_hook(ctx->net, &found->ops);
0342 list_del_rcu(&found->list);
0343 kfree_rcu(found, rcu);
0344 return;
0345 }
0346
0347 __nft_release_basechain(ctx);
0348 }
0349
0350 static int nf_tables_netdev_event(struct notifier_block *this,
0351 unsigned long event, void *ptr)
0352 {
0353 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
0354 struct nftables_pernet *nft_net;
0355 struct nft_table *table;
0356 struct nft_chain *chain, *nr;
0357 struct nft_ctx ctx = {
0358 .net = dev_net(dev),
0359 };
0360
0361 if (event != NETDEV_UNREGISTER &&
0362 event != NETDEV_CHANGENAME)
0363 return NOTIFY_DONE;
0364
0365 if (!check_net(ctx.net))
0366 return NOTIFY_DONE;
0367
0368 nft_net = nft_pernet(ctx.net);
0369 mutex_lock(&nft_net->commit_mutex);
0370 list_for_each_entry(table, &nft_net->tables, list) {
0371 if (table->family != NFPROTO_NETDEV)
0372 continue;
0373
0374 ctx.family = table->family;
0375 ctx.table = table;
0376 list_for_each_entry_safe(chain, nr, &table->chains, list) {
0377 if (!nft_is_base_chain(chain))
0378 continue;
0379
0380 ctx.chain = chain;
0381 nft_netdev_event(event, dev, &ctx);
0382 }
0383 }
0384 mutex_unlock(&nft_net->commit_mutex);
0385
0386 return NOTIFY_DONE;
0387 }
0388
0389 static struct notifier_block nf_tables_netdev_notifier = {
0390 .notifier_call = nf_tables_netdev_event,
0391 };
0392
0393 static int nft_chain_filter_netdev_init(void)
0394 {
0395 int err;
0396
0397 nft_register_chain_type(&nft_chain_filter_netdev);
0398
0399 err = register_netdevice_notifier(&nf_tables_netdev_notifier);
0400 if (err)
0401 goto err_register_netdevice_notifier;
0402
0403 return 0;
0404
0405 err_register_netdevice_notifier:
0406 nft_unregister_chain_type(&nft_chain_filter_netdev);
0407
0408 return err;
0409 }
0410
0411 static void nft_chain_filter_netdev_fini(void)
0412 {
0413 nft_unregister_chain_type(&nft_chain_filter_netdev);
0414 unregister_netdevice_notifier(&nf_tables_netdev_notifier);
0415 }
0416 #else
0417 static inline int nft_chain_filter_netdev_init(void) { return 0; }
0418 static inline void nft_chain_filter_netdev_fini(void) {}
0419 #endif
0420
0421 int __init nft_chain_filter_init(void)
0422 {
0423 int err;
0424
0425 err = nft_chain_filter_netdev_init();
0426 if (err < 0)
0427 return err;
0428
0429 nft_chain_filter_ipv4_init();
0430 nft_chain_filter_ipv6_init();
0431 nft_chain_filter_arp_init();
0432 nft_chain_filter_inet_init();
0433 nft_chain_filter_bridge_init();
0434
0435 return 0;
0436 }
0437
0438 void nft_chain_filter_fini(void)
0439 {
0440 nft_chain_filter_bridge_fini();
0441 nft_chain_filter_inet_fini();
0442 nft_chain_filter_arp_fini();
0443 nft_chain_filter_ipv6_fini();
0444 nft_chain_filter_ipv4_fini();
0445 nft_chain_filter_netdev_fini();
0446 }