blob: 8f8713b4388fbfa9a0d36298603995b02718d21d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Filtering ARP tables module.
3 *
4 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
5 *
6 */
7
8#include <linux/module.h>
Jan Engelhardte3eaa992009-06-17 22:14:54 +02009#include <linux/netfilter/x_tables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/netfilter_arp/arp_tables.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
13MODULE_LICENSE("GPL");
14MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
15MODULE_DESCRIPTION("arptables filter table");
16
17#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
18 (1 << NF_ARP_FORWARD))
19
Florian Westphalb9e69e12016-02-25 10:08:36 +010020static int __net_init arptable_filter_table_init(struct net *net);
21
Jan Engelhardt35aad0f2009-08-24 14:56:30 +020022static const struct xt_table packet_filter = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 .name = "filter",
24 .valid_hooks = FILTER_VALID_HOOKS,
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 .me = THIS_MODULE,
Jan Engelhardtee999d82008-10-08 11:35:01 +020026 .af = NFPROTO_ARP,
Jan Engelhardt2b95efe2009-06-17 13:57:48 +020027 .priority = NF_IP_PRI_FILTER,
Florian Westphalb9e69e12016-02-25 10:08:36 +010028 .table_init = arptable_filter_table_init,
Linus Torvalds1da177e2005-04-16 15:20:36 -070029};
30
31/* The work comes in here from netfilter.c */
Jan Engelhardt737535c2009-06-13 06:46:36 +020032static unsigned int
Eric W. Biederman06198b32015-09-18 14:33:06 -050033arptable_filter_hook(void *priv, struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -040034 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -070035{
Eric W. Biederman6cb8ff3f12015-09-18 14:32:55 -050036 return arpt_do_table(skb, state, state->net->ipv4.arptable_filter);
Alexey Dobriyan3918fed52008-07-26 17:48:59 -070037}
38
Jan Engelhardt2b95efe2009-06-17 13:57:48 +020039static struct nf_hook_ops *arpfilter_ops __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Florian Westphalb9e69e12016-02-25 10:08:36 +010041static int __net_init arptable_filter_table_init(struct net *net)
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080042{
Jan Engelhardte3eaa992009-06-17 22:14:54 +020043 struct arpt_replace *repl;
Florian Westphala67dd262016-02-25 10:08:35 +010044 int err;
45
Florian Westphalb9e69e12016-02-25 10:08:36 +010046 if (net->ipv4.arptable_filter)
47 return 0;
48
Jan Engelhardte3eaa992009-06-17 22:14:54 +020049 repl = arpt_alloc_initial_table(&packet_filter);
50 if (repl == NULL)
51 return -ENOMEM;
Florian Westphala67dd262016-02-25 10:08:35 +010052 err = arpt_register_table(net, &packet_filter, repl, arpfilter_ops,
53 &net->ipv4.arptable_filter);
Jan Engelhardte3eaa992009-06-17 22:14:54 +020054 kfree(repl);
Florian Westphala67dd262016-02-25 10:08:35 +010055 return err;
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080056}
57
58static void __net_exit arptable_filter_net_exit(struct net *net)
59{
Florian Westphalb9e69e12016-02-25 10:08:36 +010060 if (!net->ipv4.arptable_filter)
61 return;
Florian Westphala67dd262016-02-25 10:08:35 +010062 arpt_unregister_table(net, net->ipv4.arptable_filter, arpfilter_ops);
Florian Westphalb9e69e12016-02-25 10:08:36 +010063 net->ipv4.arptable_filter = NULL;
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080064}
65
66static struct pernet_operations arptable_filter_net_ops = {
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080067 .exit = arptable_filter_net_exit,
68};
69
Andrew Morton65b4b4e2006-03-28 16:37:06 -080070static int __init arptable_filter_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071{
Patrick McHardy964ddaa2006-04-06 14:09:49 -070072 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Florian Westphalb9e69e12016-02-25 10:08:36 +010074 arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook);
75 if (IS_ERR(arpfilter_ops))
76 return PTR_ERR(arpfilter_ops);
77
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080078 ret = register_pernet_subsys(&arptable_filter_net_ops);
Florian Westphalb9e69e12016-02-25 10:08:36 +010079 if (ret < 0) {
80 kfree(arpfilter_ops);
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080081 return ret;
Jan Engelhardt2b95efe2009-06-17 13:57:48 +020082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Florian Westphalff76def2016-03-29 11:05:16 +020084 ret = arptable_filter_table_init(&init_net);
85 if (ret) {
86 unregister_pernet_subsys(&arptable_filter_net_ops);
87 kfree(arpfilter_ops);
88 }
89
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 return ret;
91}
92
Andrew Morton65b4b4e2006-03-28 16:37:06 -080093static void __exit arptable_filter_fini(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
Alexey Dobriyan9ea0cb22008-01-31 04:05:09 -080095 unregister_pernet_subsys(&arptable_filter_net_ops);
Florian Westphalb9e69e12016-02-25 10:08:36 +010096 kfree(arpfilter_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097}
98
Andrew Morton65b4b4e2006-03-28 16:37:06 -080099module_init(arptable_filter_init);
100module_exit(arptable_filter_fini);