arptable_filter.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Filtering ARP tables module.
  4. *
  5. * Copyright (C) 2002 David S. Miller (davem@redhat.com)
  6. *
  7. */
  8. #include <linux/module.h>
  9. #include <linux/netfilter/x_tables.h>
  10. #include <linux/netfilter_arp/arp_tables.h>
  11. #include <linux/slab.h>
  12. MODULE_LICENSE("GPL");
  13. MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
  14. MODULE_DESCRIPTION("arptables filter table");
  15. #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
  16. (1 << NF_ARP_FORWARD))
  17. static int __net_init arptable_filter_table_init(struct net *net);
  18. static const struct xt_table packet_filter = {
  19. .name = "filter",
  20. .valid_hooks = FILTER_VALID_HOOKS,
  21. .me = THIS_MODULE,
  22. .af = NFPROTO_ARP,
  23. .priority = NF_IP_PRI_FILTER,
  24. .table_init = arptable_filter_table_init,
  25. };
  26. /* The work comes in here from netfilter.c */
  27. static unsigned int
  28. arptable_filter_hook(void *priv, struct sk_buff *skb,
  29. const struct nf_hook_state *state)
  30. {
  31. return arpt_do_table(skb, state, state->net->ipv4.arptable_filter);
  32. }
  33. static struct nf_hook_ops *arpfilter_ops __read_mostly;
  34. static int __net_init arptable_filter_table_init(struct net *net)
  35. {
  36. struct arpt_replace *repl;
  37. int err;
  38. if (net->ipv4.arptable_filter)
  39. return 0;
  40. repl = arpt_alloc_initial_table(&packet_filter);
  41. if (repl == NULL)
  42. return -ENOMEM;
  43. err = arpt_register_table(net, &packet_filter, repl, arpfilter_ops,
  44. &net->ipv4.arptable_filter);
  45. kfree(repl);
  46. return err;
  47. }
  48. static void __net_exit arptable_filter_net_pre_exit(struct net *net)
  49. {
  50. if (net->ipv4.arptable_filter)
  51. arpt_unregister_table_pre_exit(net, net->ipv4.arptable_filter,
  52. arpfilter_ops);
  53. }
  54. static void __net_exit arptable_filter_net_exit(struct net *net)
  55. {
  56. if (!net->ipv4.arptable_filter)
  57. return;
  58. arpt_unregister_table(net, net->ipv4.arptable_filter);
  59. net->ipv4.arptable_filter = NULL;
  60. }
  61. static struct pernet_operations arptable_filter_net_ops = {
  62. .exit = arptable_filter_net_exit,
  63. .pre_exit = arptable_filter_net_pre_exit,
  64. };
  65. static int __init arptable_filter_init(void)
  66. {
  67. int ret;
  68. arpfilter_ops = xt_hook_ops_alloc(&packet_filter, arptable_filter_hook);
  69. if (IS_ERR(arpfilter_ops))
  70. return PTR_ERR(arpfilter_ops);
  71. ret = register_pernet_subsys(&arptable_filter_net_ops);
  72. if (ret < 0) {
  73. kfree(arpfilter_ops);
  74. return ret;
  75. }
  76. ret = arptable_filter_table_init(&init_net);
  77. if (ret) {
  78. unregister_pernet_subsys(&arptable_filter_net_ops);
  79. kfree(arpfilter_ops);
  80. }
  81. return ret;
  82. }
  83. static void __exit arptable_filter_fini(void)
  84. {
  85. unregister_pernet_subsys(&arptable_filter_net_ops);
  86. kfree(arpfilter_ops);
  87. }
  88. module_init(arptable_filter_init);
  89. module_exit(arptable_filter_fini);