cfg_option_def.cc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 <dhcp/libdhcp++.h>
  16. #include <dhcp/option_definition.h>
  17. #include <dhcp/option_space.h>
  18. #include <dhcpsrv/cfg_option_def.h>
  19. namespace isc {
  20. namespace dhcp {
  21. void
  22. CfgOptionDef::copyTo(CfgOptionDef& new_config) const {
  23. // Remove any existing option definitions from the destination.
  24. new_config.option_definitions_.clearItems();
  25. const std::list<std::string>& names =
  26. option_definitions_.getOptionSpaceNames();
  27. for (std::list<std::string>::const_iterator name = names.begin();
  28. name != names.end(); ++name) {
  29. OptionDefContainerPtr defs = getAll(*name);
  30. for (OptionDefContainer::const_iterator def = defs->begin();
  31. def != defs->end(); ++def) {
  32. OptionDefinitionPtr new_def =
  33. OptionDefinitionPtr(new OptionDefinition(**def));
  34. new_config.add(new_def, *name);
  35. }
  36. }
  37. }
  38. bool
  39. CfgOptionDef::equals(const CfgOptionDef& other) const {
  40. // Get our option space names.
  41. const std::list<std::string>& names = option_definitions_.getOptionSpaceNames();
  42. // Get option space names held by the other object.
  43. const std::list<std::string>&
  44. other_names = other.option_definitions_.getOptionSpaceNames();
  45. // Compareg that sizes are the same. If they hold different number of
  46. // option space names the objects are not equal.
  47. if (names.size() != other_names.size()) {
  48. return (false);
  49. }
  50. // Iterate over all option space names and get the definitions for each
  51. // of them.
  52. for (std::list<std::string>::const_iterator name = names.begin();
  53. name != names.end(); ++name) {
  54. // Get all definitions.
  55. OptionDefContainerPtr defs = getAll(*name);
  56. OptionDefContainerPtr other_defs = other.getAll(*name);
  57. // Compare sizes. If they hold different number of definitions,
  58. // they are unequal.
  59. if (defs->size() != defs->size()) {
  60. return (false);
  61. }
  62. // For each option definition, try to find one in the other object.
  63. for (OptionDefContainer::const_iterator def = defs->begin();
  64. def != defs->end(); ++def) {
  65. OptionDefinitionPtr
  66. other_def = other.get(*name, (*def)->getCode());
  67. // Actually compare them.
  68. if (!other_def || (*other_def != **def)) {
  69. return (false);
  70. }
  71. }
  72. }
  73. // All checks passed.
  74. return (true);
  75. }
  76. void
  77. CfgOptionDef::add(const OptionDefinitionPtr& def,
  78. const std::string& option_space) {
  79. if (!OptionSpace::validateName(option_space)) {
  80. isc_throw(BadValue, "invalid option space name '"
  81. << option_space << "'");
  82. // Option definition being added must be a valid pointer.
  83. } else if (!def) {
  84. isc_throw(MalformedOptionDefinition,
  85. "option definition must not be NULL");
  86. // Must not duplicate an option definition.
  87. } else if (get(option_space, def->getCode())) {
  88. isc_throw(DuplicateOptionDefinition, "option definition with code '"
  89. << def->getCode() << "' already exists in option"
  90. " space '" << option_space << "'");
  91. // Must not override standard option definition.
  92. } else if (((option_space == DHCP4_OPTION_SPACE) &&
  93. LibDHCP::isStandardOption(Option::V4, def->getCode()) &&
  94. LibDHCP::getOptionDef(Option::V4, def->getCode())) ||
  95. ((option_space == DHCP6_OPTION_SPACE) &&
  96. LibDHCP::isStandardOption(Option::V6, def->getCode()) &&
  97. LibDHCP::getOptionDef(Option::V6, def->getCode()))) {
  98. isc_throw(BadValue, "unable to override definition of option '"
  99. << def->getCode() << "' in standard option space '"
  100. << option_space << "'");
  101. }
  102. // Add the definition.
  103. option_definitions_.addItem(def, option_space);
  104. }
  105. OptionDefContainerPtr
  106. CfgOptionDef::getAll(const std::string& option_space) const {
  107. /// @todo Does option space require any validation here?
  108. return (option_definitions_.getItems(option_space));
  109. }
  110. OptionDefinitionPtr
  111. CfgOptionDef::get(const std::string& option_space,
  112. const uint16_t option_code) const {
  113. // Get the pointer to collection of the option definitions that belong
  114. // to the particular option space.
  115. OptionDefContainerPtr defs = getAll(option_space);
  116. // If there are any option definitions for this option space, get the
  117. // one that has the specified option code.
  118. if (defs && !defs->empty()) {
  119. const OptionDefContainerTypeIndex& idx = defs->get<1>();
  120. const OptionDefContainerTypeRange& range = idx.equal_range(option_code);
  121. // If there is more than one definition matching the option code,
  122. // return the first one. In fact, it shouldn't happen that we have
  123. // more than one because we check for duplicates when we add them.
  124. if (std::distance(range.first, range.second) > 0) {
  125. return (*range.first);
  126. }
  127. }
  128. // Nothing found. Return NULL pointer.
  129. return (OptionDefinitionPtr());
  130. }
  131. OptionDefinitionPtr
  132. CfgOptionDef::get(const std::string& option_space,
  133. const std::string& option_name) const {
  134. // Get the pointer to collection of the option definitions that belong
  135. // to the particular option space.
  136. OptionDefContainerPtr defs = getAll(option_space);
  137. // If there are any option definitions for this option space, get the
  138. // one that has the specified option name.
  139. if (defs && !defs->empty()) {
  140. const OptionDefContainerNameIndex& idx = defs->get<2>();
  141. const OptionDefContainerNameRange& range = idx.equal_range(option_name);
  142. // If there is more than one definition matching the option name,
  143. // return the first one. In fact, it shouldn't happen that we have
  144. // more than one because we check for duplicates when we add them.
  145. if (std::distance(range.first, range.second) > 0) {
  146. return (*range.first);
  147. }
  148. }
  149. // Nothing found. Return NULL pointer.
  150. return (OptionDefinitionPtr());
  151. }
  152. } // end of namespace isc::dhcp
  153. } // end of namespace isc