xt_NFQUEUE.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* iptables module for using new netfilter netlink queue
  2. *
  3. * (C) 2005 by Harald Welte <laforge@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. */
  10. #include <linux/module.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/ip.h>
  13. #include <linux/ipv6.h>
  14. #include <linux/jhash.h>
  15. #include <linux/netfilter.h>
  16. #include <linux/netfilter_arp.h>
  17. #include <linux/netfilter/x_tables.h>
  18. #include <linux/netfilter/xt_NFQUEUE.h>
  19. MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  20. MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
  21. MODULE_LICENSE("GPL");
  22. MODULE_ALIAS("ipt_NFQUEUE");
  23. MODULE_ALIAS("ip6t_NFQUEUE");
  24. MODULE_ALIAS("arpt_NFQUEUE");
  25. static u32 jhash_initval __read_mostly;
  26. static bool rnd_inited __read_mostly;
  27. static unsigned int
  28. nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
  29. {
  30. const struct xt_NFQ_info *tinfo = par->targinfo;
  31. return NF_QUEUE_NR(tinfo->queuenum);
  32. }
  33. static u32 hash_v4(const struct sk_buff *skb)
  34. {
  35. const struct iphdr *iph = ip_hdr(skb);
  36. __be32 ipaddr;
  37. /* packets in either direction go into same queue */
  38. ipaddr = iph->saddr ^ iph->daddr;
  39. return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval);
  40. }
  41. #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
  42. static u32 hash_v6(const struct sk_buff *skb)
  43. {
  44. const struct ipv6hdr *ip6h = ipv6_hdr(skb);
  45. __be32 addr[4];
  46. addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0];
  47. addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1];
  48. addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2];
  49. addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3];
  50. return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval);
  51. }
  52. #endif
  53. static unsigned int
  54. nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
  55. {
  56. const struct xt_NFQ_info_v1 *info = par->targinfo;
  57. u32 queue = info->queuenum;
  58. if (info->queues_total > 1) {
  59. if (par->family == NFPROTO_IPV4)
  60. queue = (((u64) hash_v4(skb) * info->queues_total) >>
  61. 32) + queue;
  62. #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
  63. else if (par->family == NFPROTO_IPV6)
  64. queue = (((u64) hash_v6(skb) * info->queues_total) >>
  65. 32) + queue;
  66. #endif
  67. }
  68. return NF_QUEUE_NR(queue);
  69. }
  70. static unsigned int
  71. nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
  72. {
  73. const struct xt_NFQ_info_v2 *info = par->targinfo;
  74. unsigned int ret = nfqueue_tg_v1(skb, par);
  75. if (info->bypass)
  76. ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
  77. return ret;
  78. }
  79. static int nfqueue_tg_check(const struct xt_tgchk_param *par)
  80. {
  81. const struct xt_NFQ_info_v2 *info = par->targinfo;
  82. u32 maxid;
  83. if (unlikely(!rnd_inited)) {
  84. get_random_bytes(&jhash_initval, sizeof(jhash_initval));
  85. rnd_inited = true;
  86. }
  87. if (info->queues_total == 0) {
  88. pr_err("NFQUEUE: number of total queues is 0\n");
  89. return -EINVAL;
  90. }
  91. maxid = info->queues_total - 1 + info->queuenum;
  92. if (maxid > 0xffff) {
  93. pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
  94. info->queues_total, maxid);
  95. return -ERANGE;
  96. }
  97. if (par->target->revision == 2 && info->bypass > 1)
  98. return -EINVAL;
  99. return 0;
  100. }
  101. static struct xt_target nfqueue_tg_reg[] __read_mostly = {
  102. {
  103. .name = "NFQUEUE",
  104. .family = NFPROTO_UNSPEC,
  105. .target = nfqueue_tg,
  106. .targetsize = sizeof(struct xt_NFQ_info),
  107. .me = THIS_MODULE,
  108. },
  109. {
  110. .name = "NFQUEUE",
  111. .revision = 1,
  112. .family = NFPROTO_UNSPEC,
  113. .checkentry = nfqueue_tg_check,
  114. .target = nfqueue_tg_v1,
  115. .targetsize = sizeof(struct xt_NFQ_info_v1),
  116. .me = THIS_MODULE,
  117. },
  118. {
  119. .name = "NFQUEUE",
  120. .revision = 2,
  121. .family = NFPROTO_UNSPEC,
  122. .checkentry = nfqueue_tg_check,
  123. .target = nfqueue_tg_v2,
  124. .targetsize = sizeof(struct xt_NFQ_info_v2),
  125. .me = THIS_MODULE,
  126. },
  127. };
  128. static int __init nfqueue_tg_init(void)
  129. {
  130. return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
  131. }
  132. static void __exit nfqueue_tg_exit(void)
  133. {
  134. xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
  135. }
  136. module_init(nfqueue_tg_init);
  137. module_exit(nfqueue_tg_exit);