host.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright (C) 2014 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 <dhcpsrv/host.h>
  15. #include <util/strutil.h>
  16. #include <exceptions/exceptions.h>
  17. #include <sstream>
  18. namespace isc {
  19. namespace dhcp {
  20. IPv6Resrv::IPv6Resrv(const Type& type,
  21. const asiolink::IOAddress& prefix,
  22. const uint8_t prefix_len)
  23. : type_(type), prefix_(asiolink::IOAddress("::")), prefix_len_(128) {
  24. // Validate and set the actual values.
  25. set(type, prefix, prefix_len);
  26. }
  27. void
  28. IPv6Resrv::set(const Type& type, const asiolink::IOAddress& prefix,
  29. const uint8_t prefix_len) {
  30. if (!prefix.isV6() || prefix.isV6Multicast()) {
  31. isc_throw(isc::BadValue, "invalid prefix '" << prefix
  32. << "' for new IPv6 reservation");
  33. } else if (prefix_len > 128) {
  34. isc_throw(isc::BadValue, "invalid prefix length '"
  35. << static_cast<int>(prefix_len)
  36. << "' for new IPv6 reservation");
  37. } else if ((type == TYPE_NA) && (prefix_len != 128)) {
  38. isc_throw(isc::BadValue, "invalid prefix length '"
  39. << static_cast<int>(prefix_len)
  40. << "' for reserved IPv6 address, expected 128");
  41. }
  42. type_ = type;
  43. prefix_ = prefix;
  44. prefix_len_ = prefix_len;
  45. }
  46. std::string
  47. IPv6Resrv::toText() const {
  48. std::ostringstream s;
  49. s << prefix_;
  50. // For PD, append prefix length.
  51. if (getType() == TYPE_PD) {
  52. s << "/" << static_cast<int>(prefix_len_);
  53. }
  54. return (s.str());
  55. }
  56. bool
  57. IPv6Resrv::operator==(const IPv6Resrv& other) const {
  58. return (type_ == other.type_ &&
  59. prefix_ == other.prefix_ &&
  60. prefix_len_ == other.prefix_len_);
  61. }
  62. bool
  63. IPv6Resrv::operator!=(const IPv6Resrv& other) const {
  64. return (!operator==(other));
  65. }
  66. Host::Host(const uint8_t* identifier, const size_t identifier_len,
  67. const IdentifierType& identifier_type,
  68. const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
  69. const asiolink::IOAddress& ipv4_reservation,
  70. const std::string& hostname,
  71. const std::string& dhcp4_client_classes,
  72. const std::string& dhcp6_client_classes)
  73. : hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
  74. ipv6_subnet_id_(ipv6_subnet_id),
  75. ipv4_reservation_(asiolink::IOAddress("0.0.0.0")),
  76. hostname_(hostname), dhcp4_client_classes_(dhcp4_client_classes),
  77. dhcp6_client_classes_(dhcp6_client_classes) {
  78. // Initialize HWAddr or DUID
  79. setIdentifier(identifier, identifier_len, identifier_type);
  80. // Validate and set IPv4 address reservation.
  81. setIPv4Reservation(ipv4_reservation);
  82. }
  83. Host::Host(const std::string& identifier, const std::string& identifier_name,
  84. const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
  85. const asiolink::IOAddress& ipv4_reservation,
  86. const std::string& hostname,
  87. const std::string& dhcp4_client_classes,
  88. const std::string& dhcp6_client_classes)
  89. : hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
  90. ipv6_subnet_id_(ipv6_subnet_id),
  91. ipv4_reservation_(asiolink::IOAddress("0.0.0.0")),
  92. hostname_(hostname), dhcp4_client_classes_(dhcp4_client_classes),
  93. dhcp6_client_classes_(dhcp6_client_classes) {
  94. // Initialize HWAddr or DUID
  95. setIdentifier(identifier, identifier_name);
  96. // Validate and set IPv4 address reservation.
  97. setIPv4Reservation(ipv4_reservation);
  98. }
  99. const std::vector<uint8_t>&
  100. Host::getIdentifier() const {
  101. if (hw_address_) {
  102. return (hw_address_->hwaddr_);
  103. } else if (duid_) {
  104. return (duid_->getDuid());
  105. }
  106. static std::vector<uint8_t> empty_vector;
  107. return (empty_vector);
  108. }
  109. Host::IdentifierType
  110. Host::getIdentifierType() const {
  111. if (hw_address_) {
  112. return (IDENT_HWADDR);
  113. }
  114. return (IDENT_DUID);
  115. }
  116. void
  117. Host::setIdentifier(const uint8_t* identifier, const size_t len,
  118. const IdentifierType& type) {
  119. switch (type) {
  120. case IDENT_HWADDR:
  121. hw_address_ = HWAddrPtr(new HWAddr(identifier, len, HTYPE_ETHER));
  122. duid_.reset();
  123. break;
  124. case IDENT_DUID:
  125. duid_ = DuidPtr(new DUID(identifier, len));
  126. hw_address_.reset();
  127. break;
  128. default:
  129. isc_throw(isc::BadValue, "invalid client identifier type '"
  130. << static_cast<int>(type) << "' when creating host "
  131. " instance");
  132. }
  133. }
  134. void
  135. Host::setIdentifier(const std::string& identifier, const std::string& name) {
  136. if (name == "hw-address") {
  137. hw_address_ = HWAddrPtr(new HWAddr(HWAddr::fromText(identifier)));
  138. duid_.reset();
  139. } else if (name == "duid") {
  140. duid_ = DuidPtr(new DUID(DUID::fromText(identifier)));
  141. hw_address_.reset();
  142. } else {
  143. isc_throw(isc::BadValue, "invalid client identifier type '"
  144. << name << "' when creating host instance");
  145. }
  146. }
  147. void
  148. Host::setIPv4Reservation(const asiolink::IOAddress& address) {
  149. if (!address.isV4()) {
  150. isc_throw(isc::BadValue, "address '" << address << "' is not a valid"
  151. " IPv4 address");
  152. }
  153. ipv4_reservation_ = address;
  154. }
  155. void
  156. Host::addReservation(const IPv6Resrv& reservation) {
  157. // Check if it is not duplicating existing reservation.
  158. if (hasReservation(reservation)) {
  159. isc_throw(isc::InvalidOperation, "failed on attempt to add a duplicated"
  160. " host reservation for " << reservation.toText());
  161. }
  162. // Add it.
  163. ipv6_reservations_.insert(IPv6ResrvTuple(reservation.getType(),
  164. reservation));
  165. }
  166. IPv6ResrvRange
  167. Host::getIPv6Reservations(const IPv6Resrv::Type& type) const {
  168. return (ipv6_reservations_.equal_range(type));
  169. }
  170. bool
  171. Host::hasReservation(const IPv6Resrv& reservation) const {
  172. IPv6ResrvRange reservations = getIPv6Reservations(reservation.getType());
  173. if (std::distance(reservations.first, reservations.second) > 0) {
  174. for (IPv6ResrvIterator it = reservations.first;
  175. it != reservations.second; ++it) {
  176. if (it->second == reservation) {
  177. return (true);
  178. }
  179. }
  180. }
  181. // No matching reservations found.
  182. return (false);
  183. }
  184. void
  185. Host::addClientClassInternal(ClientClasses& classes,
  186. const std::string& class_name) {
  187. std::string trimmed = util::str::trim(class_name);
  188. if (!class_name.empty()) {
  189. classes.insert(ClientClass(class_name));
  190. }
  191. }
  192. } // end of namespace isc::dhcp
  193. } // end of namespace isc