nf_tables_ipv6.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
  3. * Copyright (c) 2012-2013 Pablo Neira Ayuso <pablo@netfilter.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Development of this code funded by Astaro AG (http://www.astaro.com/)
  10. */
  11. #include <linux/init.h>
  12. #include <linux/module.h>
  13. #include <linux/ipv6.h>
  14. #include <linux/netfilter_ipv6.h>
  15. #include <net/netfilter/nf_tables.h>
  16. #include <net/netfilter/nf_tables_ipv6.h>
  17. static unsigned int nft_do_chain_ipv6(void *priv,
  18. struct sk_buff *skb,
  19. const struct nf_hook_state *state)
  20. {
  21. struct nft_pktinfo pkt;
  22. /* malformed packet, drop it */
  23. if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0)
  24. return NF_DROP;
  25. return nft_do_chain(&pkt, priv);
  26. }
  27. static unsigned int nft_ipv6_output(void *priv,
  28. struct sk_buff *skb,
  29. const struct nf_hook_state *state)
  30. {
  31. if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
  32. if (net_ratelimit())
  33. pr_info("nf_tables_ipv6: ignoring short SOCK_RAW "
  34. "packet\n");
  35. return NF_ACCEPT;
  36. }
  37. return nft_do_chain_ipv6(priv, skb, state);
  38. }
  39. struct nft_af_info nft_af_ipv6 __read_mostly = {
  40. .family = NFPROTO_IPV6,
  41. .nhooks = NF_INET_NUMHOOKS,
  42. .owner = THIS_MODULE,
  43. .nops = 1,
  44. .hooks = {
  45. [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
  46. [NF_INET_LOCAL_OUT] = nft_ipv6_output,
  47. [NF_INET_FORWARD] = nft_do_chain_ipv6,
  48. [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6,
  49. [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
  50. },
  51. };
  52. EXPORT_SYMBOL_GPL(nft_af_ipv6);
  53. static int nf_tables_ipv6_init_net(struct net *net)
  54. {
  55. net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
  56. if (net->nft.ipv6 == NULL)
  57. return -ENOMEM;
  58. memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));
  59. if (nft_register_afinfo(net, net->nft.ipv6) < 0)
  60. goto err;
  61. return 0;
  62. err:
  63. kfree(net->nft.ipv6);
  64. return -ENOMEM;
  65. }
  66. static void nf_tables_ipv6_exit_net(struct net *net)
  67. {
  68. nft_unregister_afinfo(net->nft.ipv6);
  69. kfree(net->nft.ipv6);
  70. }
  71. static struct pernet_operations nf_tables_ipv6_net_ops = {
  72. .init = nf_tables_ipv6_init_net,
  73. .exit = nf_tables_ipv6_exit_net,
  74. };
  75. static const struct nf_chain_type filter_ipv6 = {
  76. .name = "filter",
  77. .type = NFT_CHAIN_T_DEFAULT,
  78. .family = NFPROTO_IPV6,
  79. .owner = THIS_MODULE,
  80. .hook_mask = (1 << NF_INET_LOCAL_IN) |
  81. (1 << NF_INET_LOCAL_OUT) |
  82. (1 << NF_INET_FORWARD) |
  83. (1 << NF_INET_PRE_ROUTING) |
  84. (1 << NF_INET_POST_ROUTING),
  85. };
  86. static int __init nf_tables_ipv6_init(void)
  87. {
  88. int ret;
  89. nft_register_chain_type(&filter_ipv6);
  90. ret = register_pernet_subsys(&nf_tables_ipv6_net_ops);
  91. if (ret < 0)
  92. nft_unregister_chain_type(&filter_ipv6);
  93. return ret;
  94. }
  95. static void __exit nf_tables_ipv6_exit(void)
  96. {
  97. unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
  98. nft_unregister_chain_type(&filter_ipv6);
  99. }
  100. module_init(nf_tables_ipv6_init);
  101. module_exit(nf_tables_ipv6_exit);
  102. MODULE_LICENSE("GPL");
  103. MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  104. MODULE_ALIAS_NFT_FAMILY(AF_INET6);