cfg_subnets6.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <dhcpsrv/cfg_subnets6.h>
  16. #include <dhcpsrv/dhcpsrv_log.h>
  17. #include <dhcpsrv/subnet_id.h>
  18. using namespace isc::asiolink;
  19. namespace isc {
  20. namespace dhcp {
  21. void
  22. CfgSubnets6::add(const Subnet6Ptr& subnet) {
  23. /// @todo: Check that this new subnet does not cross boundaries of any
  24. /// other already defined subnet.
  25. if (isDuplicate(*subnet)) {
  26. isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv6 subnet '"
  27. << subnet->getID() << "' is already in use");
  28. }
  29. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET6)
  30. .arg(subnet->toText());
  31. subnets_.push_back(subnet);
  32. }
  33. Subnet6Ptr
  34. CfgSubnets6::selectSubnet(const SubnetSelector& selector) const {
  35. Subnet6Ptr subnet;
  36. // If relay agent link address is set to zero it means that we're dealing
  37. // with a directly connected client.
  38. if (selector.first_relay_linkaddr_ == IOAddress("::")) {
  39. // If interface name is known try to match it with interface names
  40. // specified for configured subnets.
  41. if (!selector.iface_name_.empty()) {
  42. subnet = selectSubnet(selector.iface_name_,
  43. selector.client_classes_);
  44. }
  45. // If interface name didn't match, try the client's address.
  46. if (!subnet && selector.remote_address_ != IOAddress("::")) {
  47. subnet = selectSubnet(selector.remote_address_,
  48. selector.client_classes_);
  49. }
  50. // If relay agent link address is set, we're dealing with a relayed message.
  51. } else {
  52. // Find the subnet using the Interface Id option, if present.
  53. subnet = selectSubnet(selector.interface_id_, selector.client_classes_);
  54. // If Interface ID option could not be matched for any subnet, try
  55. // the relay agent link address.
  56. if (!subnet) {
  57. subnet = selectSubnet(selector.first_relay_linkaddr_,
  58. selector.client_classes_,
  59. true);
  60. }
  61. }
  62. // Return subnet found, or NULL if not found.
  63. return (subnet);
  64. }
  65. Subnet6Ptr
  66. CfgSubnets6::selectSubnet(const asiolink::IOAddress& address,
  67. const ClientClasses& client_classes,
  68. const bool is_relay_address) const {
  69. // If the specified address is a relay address we first need to match
  70. // it with the relay addresses specified for all subnets.
  71. if (is_relay_address) {
  72. for (Subnet6Collection::const_iterator subnet = subnets_.begin();
  73. subnet != subnets_.end(); ++subnet) {
  74. // If the specified address matches the relay address, return this
  75. // subnet.
  76. if (is_relay_address &&
  77. ((*subnet)->getRelayInfo().addr_ == address) &&
  78. (*subnet)->clientSupported(client_classes)) {
  79. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
  80. DHCPSRV_CFGMGR_SUBNET6_RELAY)
  81. .arg((*subnet)->toText()).arg(address.toText());
  82. return (*subnet);
  83. }
  84. }
  85. }
  86. // No success so far. Check if the specified address is in range
  87. // with any subnet.
  88. for (Subnet6Collection::const_iterator subnet = subnets_.begin();
  89. subnet != subnets_.end(); ++subnet) {
  90. if ((*subnet)->inRange(address) &&
  91. (*subnet)->clientSupported(client_classes)) {
  92. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_SUBNET6)
  93. .arg((*subnet)->toText()).arg(address.toText());
  94. return (*subnet);
  95. }
  96. }
  97. // Nothing found.
  98. return (Subnet6Ptr());
  99. }
  100. Subnet6Ptr
  101. CfgSubnets6::selectSubnet(const std::string& iface_name,
  102. const ClientClasses& client_classes) const {
  103. // If empty interface specified, we can't select subnet by interface.
  104. if (!iface_name.empty()) {
  105. for (Subnet6Collection::const_iterator subnet = subnets_.begin();
  106. subnet != subnets_.end(); ++subnet) {
  107. // If interface name matches with the one specified for the subnet
  108. // and the client is not rejected based on the classification,
  109. // return the subnet.
  110. if ((iface_name == (*subnet)->getIface()) &&
  111. (*subnet)->clientSupported(client_classes)) {
  112. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
  113. DHCPSRV_CFGMGR_SUBNET6_IFACE)
  114. .arg((*subnet)->toText()).arg(iface_name);
  115. return (*subnet);
  116. }
  117. }
  118. }
  119. // No subnet found for this interface name.
  120. return (Subnet6Ptr());
  121. }
  122. Subnet6Ptr
  123. CfgSubnets6::selectSubnet(const OptionPtr& interface_id,
  124. const ClientClasses& client_classes) const {
  125. // We can only select subnet using an interface id, if the interface
  126. // id is known.
  127. if (interface_id) {
  128. for (Subnet6Collection::const_iterator subnet = subnets_.begin();
  129. subnet != subnets_.end(); ++subnet) {
  130. // If interface id matches for the subnet and the subnet is not
  131. // rejected based on the classification.
  132. if ((*subnet)->getInterfaceId() &&
  133. (*subnet)->getInterfaceId()->equals(interface_id) &&
  134. (*subnet)->clientSupported(client_classes)) {
  135. LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
  136. DHCPSRV_CFGMGR_SUBNET6_IFACE_ID)
  137. .arg((*subnet)->toText());
  138. return (*subnet);
  139. }
  140. }
  141. }
  142. // No subnet found.
  143. return (Subnet6Ptr());
  144. }
  145. bool
  146. CfgSubnets6::isDuplicate(const Subnet6& subnet) const {
  147. for (Subnet6Collection::const_iterator subnet_it = subnets_.begin();
  148. subnet_it != subnets_.end(); ++subnet_it) {
  149. if ((*subnet_it)->getID() == subnet.getID()) {
  150. return (true);
  151. }
  152. }
  153. return (false);
  154. }
  155. } // end of namespace isc::dhcp
  156. } // end of namespace isc