You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.4 KiB

10 years ago
  1. /* -*- coding: utf-8 -*-
  2. * ----------------------------------------------------------------------
  3. * Copyright © 2012, RedJack, LLC.
  4. * All rights reserved.
  5. *
  6. * Please see the LICENSE.txt file in this distribution for license
  7. * details.
  8. * ----------------------------------------------------------------------
  9. */
  10. #include <libcork/core.h>
  11. #include "ipset/bdd/nodes.h"
  12. #include "ipset/bits.h"
  13. #include "ipset/errors.h"
  14. #include "ipset/ipset.h"
  15. /**
  16. * Given a BDD variable number, return the index of the corresponding
  17. * bit in an IP address. IPv4 addresses use variables 1-32; IPv6
  18. * addresses use 1-128. (Variable 0 is used to identify the kind of
  19. * address — TRUE for IPv4, FALSE for IPv6.)
  20. */
  21. static unsigned int
  22. IPSET_NAME(bit_for_var)(ipset_variable var)
  23. {
  24. return (var - 1);
  25. }
  26. /**
  27. * An assignment function that can be used to evaluate an IP set BDD.
  28. */
  29. static bool
  30. IPSET_NAME(assignment)(const void *addr, ipset_variable var)
  31. {
  32. if (var == 0) {
  33. return IP_DISCRIMINATOR_VALUE;
  34. } else {
  35. unsigned int bit = IPSET_NAME(bit_for_var)(var);
  36. return IPSET_BIT_GET(addr, bit);
  37. }
  38. }
  39. bool
  40. IPSET_PRENAME(contains)(const struct ip_set *set, CORK_IP *elem)
  41. {
  42. return ipset_node_evaluate
  43. (set->cache, set->set_bdd, IPSET_NAME(assignment), elem);
  44. }
  45. bool
  46. IPSET_NAME(add_network)(struct ip_set *set, CORK_IP *elem,
  47. unsigned int cidr_prefix)
  48. {
  49. /* Special case — the BDD for a netmask that's out of range never
  50. * evaluates to true. */
  51. if (cidr_prefix > IP_BIT_SIZE) {
  52. cork_error_set
  53. (IPSET_ERROR, IPSET_PARSE_ERROR,
  54. "CIDR block %u out of range [0..%u]", cidr_prefix, IP_BIT_SIZE);
  55. return false;
  56. }
  57. ipset_node_id new_bdd =
  58. ipset_node_insert
  59. (set->cache, set->set_bdd,
  60. IPSET_NAME(assignment), elem, cidr_prefix + 1, 1);
  61. bool result = (new_bdd == set->set_bdd);
  62. ipset_node_decref(set->cache, set->set_bdd);
  63. set->set_bdd = new_bdd;
  64. return result;
  65. }
  66. bool
  67. IPSET_NAME(add)(struct ip_set *set, CORK_IP *elem)
  68. {
  69. ipset_node_id new_bdd =
  70. ipset_node_insert
  71. (set->cache, set->set_bdd,
  72. IPSET_NAME(assignment), elem, IP_BIT_SIZE + 1, 1);
  73. bool result = (new_bdd == set->set_bdd);
  74. ipset_node_decref(set->cache, set->set_bdd);
  75. set->set_bdd = new_bdd;
  76. return result;
  77. }
  78. bool
  79. IPSET_NAME(remove)(struct ip_set *set, CORK_IP *elem)
  80. {
  81. ipset_node_id new_bdd =
  82. ipset_node_insert
  83. (set->cache, set->set_bdd,
  84. IPSET_NAME(assignment), elem, IP_BIT_SIZE + 1, 0);
  85. bool result = (new_bdd == set->set_bdd);
  86. ipset_node_decref(set->cache, set->set_bdd);
  87. set->set_bdd = new_bdd;
  88. return result;
  89. }
  90. bool
  91. IPSET_NAME(remove_network)(struct ip_set *set, CORK_IP *elem,
  92. unsigned int cidr_prefix)
  93. {
  94. /* Special case — the BDD for a netmask that's out of range never
  95. * evaluates to true. */
  96. if (cidr_prefix > IP_BIT_SIZE) {
  97. cork_error_set
  98. (IPSET_ERROR, IPSET_PARSE_ERROR,
  99. "CIDR block %u out of range [0..%u]", cidr_prefix, IP_BIT_SIZE);
  100. return false;
  101. }
  102. ipset_node_id new_bdd =
  103. ipset_node_insert
  104. (set->cache, set->set_bdd,
  105. IPSET_NAME(assignment), elem, cidr_prefix + 1, 0);
  106. bool result = (new_bdd == set->set_bdd);
  107. ipset_node_decref(set->cache, set->set_bdd);
  108. set->set_bdd = new_bdd;
  109. return result;
  110. }