xt_iprange.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * xt_iprange - Netfilter module to match IP address ranges
  4. *
  5. * (C) 2003 Jozsef Kadlecsik <kadlec@netfilter.org>
  6. * (C) CC Computer Consultants GmbH, 2008
  7. */
  8. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9. #include <linux/module.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/ip.h>
  12. #include <linux/ipv6.h>
  13. #include <linux/netfilter/x_tables.h>
  14. #include <linux/netfilter/xt_iprange.h>
  15. static bool
  16. iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par)
  17. {
  18. const struct xt_iprange_mtinfo *info = par->matchinfo;
  19. const struct iphdr *iph = ip_hdr(skb);
  20. bool m;
  21. if (info->flags & IPRANGE_SRC) {
  22. m = ntohl(iph->saddr) < ntohl(info->src_min.ip);
  23. m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
  24. m ^= !!(info->flags & IPRANGE_SRC_INV);
  25. if (m) {
  26. pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n",
  27. &iph->saddr,
  28. (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
  29. &info->src_min.ip,
  30. &info->src_max.ip);
  31. return false;
  32. }
  33. }
  34. if (info->flags & IPRANGE_DST) {
  35. m = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
  36. m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
  37. m ^= !!(info->flags & IPRANGE_DST_INV);
  38. if (m) {
  39. pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n",
  40. &iph->daddr,
  41. (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
  42. &info->dst_min.ip,
  43. &info->dst_max.ip);
  44. return false;
  45. }
  46. }
  47. return true;
  48. }
  49. static inline int
  50. iprange_ipv6_lt(const struct in6_addr *a, const struct in6_addr *b)
  51. {
  52. unsigned int i;
  53. for (i = 0; i < 4; ++i) {
  54. if (a->s6_addr32[i] != b->s6_addr32[i])
  55. return ntohl(a->s6_addr32[i]) < ntohl(b->s6_addr32[i]);
  56. }
  57. return 0;
  58. }
  59. static bool
  60. iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par)
  61. {
  62. const struct xt_iprange_mtinfo *info = par->matchinfo;
  63. const struct ipv6hdr *iph = ipv6_hdr(skb);
  64. bool m;
  65. if (info->flags & IPRANGE_SRC) {
  66. m = iprange_ipv6_lt(&iph->saddr, &info->src_min.in6);
  67. m |= iprange_ipv6_lt(&info->src_max.in6, &iph->saddr);
  68. m ^= !!(info->flags & IPRANGE_SRC_INV);
  69. if (m) {
  70. pr_debug("src IP %pI6 NOT in range %s%pI6-%pI6\n",
  71. &iph->saddr,
  72. (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
  73. &info->src_min.in6,
  74. &info->src_max.in6);
  75. return false;
  76. }
  77. }
  78. if (info->flags & IPRANGE_DST) {
  79. m = iprange_ipv6_lt(&iph->daddr, &info->dst_min.in6);
  80. m |= iprange_ipv6_lt(&info->dst_max.in6, &iph->daddr);
  81. m ^= !!(info->flags & IPRANGE_DST_INV);
  82. if (m) {
  83. pr_debug("dst IP %pI6 NOT in range %s%pI6-%pI6\n",
  84. &iph->daddr,
  85. (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
  86. &info->dst_min.in6,
  87. &info->dst_max.in6);
  88. return false;
  89. }
  90. }
  91. return true;
  92. }
  93. static struct xt_match iprange_mt_reg[] __read_mostly = {
  94. {
  95. .name = "iprange",
  96. .revision = 1,
  97. .family = NFPROTO_IPV4,
  98. .match = iprange_mt4,
  99. .matchsize = sizeof(struct xt_iprange_mtinfo),
  100. .me = THIS_MODULE,
  101. },
  102. {
  103. .name = "iprange",
  104. .revision = 1,
  105. .family = NFPROTO_IPV6,
  106. .match = iprange_mt6,
  107. .matchsize = sizeof(struct xt_iprange_mtinfo),
  108. .me = THIS_MODULE,
  109. },
  110. };
  111. static int __init iprange_mt_init(void)
  112. {
  113. return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
  114. }
  115. static void __exit iprange_mt_exit(void)
  116. {
  117. xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
  118. }
  119. module_init(iprange_mt_init);
  120. module_exit(iprange_mt_exit);
  121. MODULE_LICENSE("GPL");
  122. MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  123. MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
  124. MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching");
  125. MODULE_ALIAS("ipt_iprange");
  126. MODULE_ALIAS("ip6t_iprange");