From 62d94947c2068583c66d894c2066d0bacc1f6608 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Wed, 19 Jul 2017 23:22:30 +0200 Subject: [PATCH] [5314] Subnet to Element conversion moved to SubnetX classes. --- src/lib/dhcpsrv/cfg_subnets4.cc | 101 +----------- src/lib/dhcpsrv/cfg_subnets6.cc | 166 +------------------ src/lib/dhcpsrv/subnet.cc | 275 ++++++++++++++++++++++++++++++++ src/lib/dhcpsrv/subnet.h | 26 ++- 4 files changed, 302 insertions(+), 266 deletions(-) diff --git a/src/lib/dhcpsrv/cfg_subnets4.cc b/src/lib/dhcpsrv/cfg_subnets4.cc index 136f213d45..e86580e351 100644 --- a/src/lib/dhcpsrv/cfg_subnets4.cc +++ b/src/lib/dhcpsrv/cfg_subnets4.cc @@ -284,106 +284,7 @@ CfgSubnets4::toElement() const { // Iterate subnets for (Subnet4Collection::const_iterator subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) { - // Prepare the map - ElementPtr map = Element::createMap(); - // Set subnet id - SubnetID id = (*subnet)->getID(); - map->set("id", Element::create(static_cast(id))); - // Set relay info - const Subnet::RelayInfo& relay_info = (*subnet)->getRelayInfo(); - ElementPtr relay = Element::createMap(); - relay->set("ip-address", Element::create(relay_info.addr_.toText())); - map->set("relay", relay); - // Set subnet - map->set("subnet", Element::create((*subnet)->toText())); - // Set interface - const std::string& iface = (*subnet)->getIface(); - map->set("interface", Element::create(iface)); - // Set renew-timer - map->set("renew-timer", - Element::create(static_cast - ((*subnet)->getT1().get()))); - // Set rebind-timer - map->set("rebind-timer", - Element::create(static_cast - ((*subnet)->getT2().get()))); - // Set valid-lifetime - map->set("valid-lifetime", - Element::create(static_cast - ((*subnet)->getValid().get()))); - // Set pools - const PoolCollection& pools = (*subnet)->getPools(Lease::TYPE_V4); - ElementPtr pool_list = Element::createList(); - for (PoolCollection::const_iterator pool = pools.cbegin(); - pool != pools.cend(); ++pool) { - // Prepare the map for a pool (@todo move this code to pool.cc) - ElementPtr pool_map = Element::createMap(); - // Set pool - const IOAddress& first = (*pool)->getFirstAddress(); - const IOAddress& last = (*pool)->getLastAddress(); - std::string range = first.toText() + "-" + last.toText(); - // Try to output a prefix (vs a range) - int prefix_len = prefixLengthFromRange(first, last); - if (prefix_len >= 0) { - std::ostringstream oss; - oss << first.toText() << "/" << prefix_len; - range = oss.str(); - } - pool_map->set("pool", Element::create(range)); - // Set user-context - ConstElementPtr context = (*pool)->getContext(); - if (!isNull(context)) { - pool_map->set("user-context", context); - } - // Set pool options - ConstCfgOptionPtr opts = (*pool)->getCfgOption(); - pool_map->set("option-data", opts->toElement()); - // Push on the pool list - pool_list->add(pool_map); - } - map->set("pools", pool_list); - // Set host reservation-mode - Subnet::HRMode hrmode = (*subnet)->getHostReservationMode(); - std::string mode; - switch (hrmode) { - case Subnet::HR_DISABLED: - mode = "disabled"; - break; - case Subnet::HR_OUT_OF_POOL: - mode = "out-of-pool"; - break; - case Subnet::HR_ALL: - mode = "all"; - break; - default: - isc_throw(ToElementError, - "invalid host reservation mode: " << hrmode); - } - map->set("reservation-mode", Element::create(mode)); - // Set match-client-id - map->set("match-client-id", - Element::create((*subnet)->getMatchClientId())); - // Set next-server - map->set("next-server", - Element::create((*subnet)->getSiaddr().toText())); - // Set DHCP4o6 - const Cfg4o6& d4o6 = (*subnet)->get4o6(); - isc::data::merge(map, d4o6.toElement()); - // Set client-class - const ClientClasses& cclasses = (*subnet)->getClientClasses(); - if (cclasses.size() > 1) { - isc_throw(ToElementError, "client-class has too many items: " - << cclasses.size()); - } else if (!cclasses.empty()) { - map->set("client-class", Element::create(*cclasses.cbegin())); - } - // Set options - ConstCfgOptionPtr opts = (*subnet)->getCfgOption(); - map->set("option-data", opts->toElement()); - // Not supported: interface-id - // Not supported: rapid-commit - // Push on the list - result->add(map); + result->add((*subnet)->toElement()); } return (result); } diff --git a/src/lib/dhcpsrv/cfg_subnets6.cc b/src/lib/dhcpsrv/cfg_subnets6.cc index a795fe4a60..439bcbf616 100644 --- a/src/lib/dhcpsrv/cfg_subnets6.cc +++ b/src/lib/dhcpsrv/cfg_subnets6.cc @@ -240,171 +240,7 @@ CfgSubnets6::toElement() const { // Iterate subnets for (Subnet6Collection::const_iterator subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) { - // Prepare the map - ElementPtr map = Element::createMap(); - // Set subnet id - SubnetID id = (*subnet)->getID(); - map->set("id", Element::create(static_cast(id))); - // Set relay info - const Subnet::RelayInfo& relay_info = (*subnet)->getRelayInfo(); - ElementPtr relay = Element::createMap(); - relay->set("ip-address", Element::create(relay_info.addr_.toText())); - map->set("relay", relay); - // Set subnet - map->set("subnet", Element::create((*subnet)->toText())); - // Set interface - const std::string& iface = (*subnet)->getIface(); - map->set("interface", Element::create(iface)); - // Set interface-id - const OptionPtr& ifaceid = (*subnet)->getInterfaceId(); - if (ifaceid) { - std::vector bin = ifaceid->getData(); - std::string ifid; - ifid.resize(bin.size()); - if (!bin.empty()) { - std::memcpy(&ifid[0], &bin[0], bin.size()); - } - map->set("interface-id", Element::create(ifid)); - } else { - map->set("interface-id", Element::create(std::string())); - } - // Set renew-timer - map->set("renew-timer", - Element::create(static_cast - ((*subnet)->getT1().get()))); - // Set rebind-timer - map->set("rebind-timer", - Element::create(static_cast - ((*subnet)->getT2().get()))); - // Set preferred-lifetime - map->set("preferred-lifetime", - Element::create(static_cast - ((*subnet)->getPreferred().get()))); - // Set valid-lifetime - map->set("valid-lifetime", - Element::create(static_cast - ((*subnet)->getValid().get()))); - // Set rapid-commit - bool rapid_commit = (*subnet)->getRapidCommit(); - map->set("rapid-commit", Element::create(rapid_commit)); - // Set pools - const PoolCollection& pools = (*subnet)->getPools(Lease::TYPE_NA); - ElementPtr pool_list = Element::createList(); - for (PoolCollection::const_iterator pool = pools.cbegin(); - pool != pools.cend(); ++pool) { - // Prepare the map for a pool (@todo move this code to pool.cc) - ElementPtr pool_map = Element::createMap(); - // Set pool - const IOAddress& first = (*pool)->getFirstAddress(); - const IOAddress& last = (*pool)->getLastAddress(); - std::string range = first.toText() + "-" + last.toText(); - // Try to output a prefix (vs a range) - int prefix_len = prefixLengthFromRange(first, last); - if (prefix_len >= 0) { - std::ostringstream oss; - oss << first.toText() << "/" << prefix_len; - range = oss.str(); - } - pool_map->set("pool", Element::create(range)); - // Set user-context - ConstElementPtr context = (*pool)->getContext(); - if (!isNull(context)) { - pool_map->set("user-context", context); - } - // Set pool options - ConstCfgOptionPtr opts = (*pool)->getCfgOption(); - pool_map->set("option-data", opts->toElement()); - // Push on the pool list - pool_list->add(pool_map); - } - map->set("pools", pool_list); - // Set pd-pools - const PoolCollection& pdpools = (*subnet)->getPools(Lease::TYPE_PD); - ElementPtr pdpool_list = Element::createList(); - for (PoolCollection::const_iterator pool = pdpools.cbegin(); - pool != pdpools.cend(); ++pool) { - // Get it as a Pool6 (@todo move this code to pool.cc) - const Pool6* pdpool = dynamic_cast(pool->get()); - if (!pdpool) { - isc_throw(ToElementError, "invalid pd-pool pointer"); - } - // Prepare the map for a pd-pool - ElementPtr pool_map = Element::createMap(); - // Set prefix - const IOAddress& prefix = pdpool->getFirstAddress(); - pool_map->set("prefix", Element::create(prefix.toText())); - // Set prefix-len (get it from min - max) - const IOAddress& last = pdpool->getLastAddress(); - int prefix_len = prefixLengthFromRange(prefix, last); - if (prefix_len < 0) { - // The pool is bad: give up - isc_throw(ToElementError, "invalid prefix range " - << prefix.toText() << "-" << last.toText()); - } - pool_map->set("prefix-len", Element::create(prefix_len)); - // Set delegated-len - uint8_t len = pdpool->getLength(); - pool_map->set("delegated-len", - Element::create(static_cast(len))); - // Set excluded prefix - const Option6PDExcludePtr& xopt = - pdpool->getPrefixExcludeOption(); - if (xopt) { - const IOAddress& xprefix = - xopt->getExcludedPrefix(prefix, len); - pool_map->set("excluded-prefix", - Element::create(xprefix.toText())); - uint8_t xlen = xopt->getExcludedPrefixLength(); - pool_map->set("excluded-prefix-len", - Element::create(static_cast(xlen))); - } else { - pool_map->set("excluded-prefix", - Element::create(std::string("::"))); - pool_map->set("excluded-prefix-len", Element::create(0)); - } - // Set user-context - ConstElementPtr context = pdpool->getContext(); - if (!isNull(context)) { - pool_map->set("user-context", context); - } - // Set pool options - ConstCfgOptionPtr opts = pdpool->getCfgOption(); - pool_map->set("option-data", opts->toElement()); - // Push on the pool list - pdpool_list->add(pool_map); - } - map->set("pd-pools", pdpool_list); - // Set host reservation-mode - Subnet::HRMode hrmode = (*subnet)->getHostReservationMode(); - std::string mode; - switch (hrmode) { - case Subnet::HR_DISABLED: - mode = "disabled"; - break; - case Subnet::HR_OUT_OF_POOL: - mode = "out-of-pool"; - break; - case Subnet::HR_ALL: - mode = "all"; - break; - default: - isc_throw(ToElementError, - "invalid host reservation mode: " << hrmode); - } - map->set("reservation-mode", Element::create(mode)); - // Set client-class - const ClientClasses& cclasses = (*subnet)->getClientClasses(); - if (cclasses.size() > 1) { - isc_throw(ToElementError, "client-class has too many items: " - << cclasses.size()); - } else if (!cclasses.empty()) { - map->set("client-class", Element::create(*cclasses.cbegin())); - } - // Set options - ConstCfgOptionPtr opts = (*subnet)->getCfgOption(); - map->set("option-data", opts->toElement()); - // Push on the list - result->add(map); + result->add((*subnet)->toElement()); } return (result); } diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc index f0874099cb..6752b76b0d 100644 --- a/src/lib/dhcpsrv/subnet.cc +++ b/src/lib/dhcpsrv/subnet.cc @@ -14,6 +14,7 @@ #include using namespace isc::asiolink; +using namespace isc::data; using namespace isc::dhcp; namespace { @@ -472,5 +473,279 @@ void Subnet6::checkType(Lease::Type type) const { } } +data::ElementPtr +Subnet4::toElement() const { + // Prepare the map + ElementPtr map = Element::createMap(); + // Set subnet id + SubnetID id = getID(); + map->set("id", Element::create(static_cast(id))); + // Set relay info + const Subnet::RelayInfo& relay_info = getRelayInfo(); + ElementPtr relay = Element::createMap(); + relay->set("ip-address", Element::create(relay_info.addr_.toText())); + map->set("relay", relay); + // Set subnet + map->set("subnet", Element::create(toText())); + // Set interface + const std::string& iface = getIface(); + map->set("interface", Element::create(iface)); + // Set renew-timer + map->set("renew-timer", + Element::create(static_cast + (getT1().get()))); + // Set rebind-timer + map->set("rebind-timer", + Element::create(static_cast + (getT2().get()))); + // Set valid-lifetime + map->set("valid-lifetime", + Element::create(static_cast + (getValid().get()))); + // Set pools + const PoolCollection& pools = getPools(Lease::TYPE_V4); + ElementPtr pool_list = Element::createList(); + for (PoolCollection::const_iterator pool = pools.cbegin(); + pool != pools.cend(); ++pool) { + // Prepare the map for a pool (@todo move this code to pool.cc) + ElementPtr pool_map = Element::createMap(); + // Set pool + const IOAddress& first = (*pool)->getFirstAddress(); + const IOAddress& last = (*pool)->getLastAddress(); + std::string range = first.toText() + "-" + last.toText(); + // Try to output a prefix (vs a range) + int prefix_len = prefixLengthFromRange(first, last); + if (prefix_len >= 0) { + std::ostringstream oss; + oss << first.toText() << "/" << prefix_len; + range = oss.str(); + } + pool_map->set("pool", Element::create(range)); + // Set user-context + ConstElementPtr context = (*pool)->getContext(); + if (!isNull(context)) { + pool_map->set("user-context", context); + } + // Set pool options + ConstCfgOptionPtr opts = (*pool)->getCfgOption(); + pool_map->set("option-data", opts->toElement()); + // Push on the pool list + pool_list->add(pool_map); + } + map->set("pools", pool_list); + // Set host reservation-mode + Subnet::HRMode hrmode = getHostReservationMode(); + std::string mode; + switch (hrmode) { + case Subnet::HR_DISABLED: + mode = "disabled"; + break; + case Subnet::HR_OUT_OF_POOL: + mode = "out-of-pool"; + break; + case Subnet::HR_ALL: + mode = "all"; + break; + default: + isc_throw(ToElementError, + "invalid host reservation mode: " << hrmode); + } + map->set("reservation-mode", Element::create(mode)); + // Set match-client-id + map->set("match-client-id", + Element::create(getMatchClientId())); + // Set next-server + map->set("next-server", + Element::create(getSiaddr().toText())); + // Set DHCP4o6 + const Cfg4o6& d4o6 = get4o6(); + isc::data::merge(map, d4o6.toElement()); + // Set client-class + const ClientClasses& cclasses = getClientClasses(); + if (cclasses.size() > 1) { + isc_throw(ToElementError, "client-class has too many items: " + << cclasses.size()); + } else if (!cclasses.empty()) { + map->set("client-class", Element::create(*cclasses.cbegin())); + } + // Set options + ConstCfgOptionPtr opts = getCfgOption(); + map->set("option-data", opts->toElement()); + // Not supported: interface-id + // Not supported: rapid-commit + + return (map); +} + +data::ElementPtr +Subnet6::toElement() const { + // Prepare the map + ElementPtr map = Element::createMap(); + // Set subnet id + SubnetID id = getID(); + map->set("id", Element::create(static_cast(id))); + // Set relay info + const Subnet::RelayInfo& relay_info = getRelayInfo(); + ElementPtr relay = Element::createMap(); + relay->set("ip-address", Element::create(relay_info.addr_.toText())); + map->set("relay", relay); + // Set subnet + map->set("subnet", Element::create(toText())); + // Set interface + const std::string& iface = getIface(); + map->set("interface", Element::create(iface)); + // Set interface-id + const OptionPtr& ifaceid = getInterfaceId(); + if (ifaceid) { + std::vector bin = ifaceid->getData(); + std::string ifid; + ifid.resize(bin.size()); + if (!bin.empty()) { + std::memcpy(&ifid[0], &bin[0], bin.size()); + } + map->set("interface-id", Element::create(ifid)); + } else { + map->set("interface-id", Element::create(std::string())); + } + // Set renew-timer + map->set("renew-timer", + Element::create(static_cast + (getT1().get()))); + // Set rebind-timer + map->set("rebind-timer", + Element::create(static_cast + (getT2().get()))); + // Set preferred-lifetime + map->set("preferred-lifetime", + Element::create(static_cast + (getPreferred().get()))); + // Set valid-lifetime + map->set("valid-lifetime", + Element::create(static_cast + (getValid().get()))); + // Set rapid-commit + bool rapid_commit = getRapidCommit(); + map->set("rapid-commit", Element::create(rapid_commit)); + // Set pools + const PoolCollection& pools = getPools(Lease::TYPE_NA); + ElementPtr pool_list = Element::createList(); + for (PoolCollection::const_iterator pool = pools.cbegin(); + pool != pools.cend(); ++pool) { + // Prepare the map for a pool (@todo move this code to pool.cc) + ElementPtr pool_map = Element::createMap(); + // Set pool + const IOAddress& first = (*pool)->getFirstAddress(); + const IOAddress& last = (*pool)->getLastAddress(); + std::string range = first.toText() + "-" + last.toText(); + // Try to output a prefix (vs a range) + int prefix_len = prefixLengthFromRange(first, last); + if (prefix_len >= 0) { + std::ostringstream oss; + oss << first.toText() << "/" << prefix_len; + range = oss.str(); + } + pool_map->set("pool", Element::create(range)); + // Set user-context + ConstElementPtr context = (*pool)->getContext(); + if (!isNull(context)) { + pool_map->set("user-context", context); + } + // Set pool options + ConstCfgOptionPtr opts = (*pool)->getCfgOption(); + pool_map->set("option-data", opts->toElement()); + // Push on the pool list + pool_list->add(pool_map); + } + map->set("pools", pool_list); + // Set pd-pools + const PoolCollection& pdpools = getPools(Lease::TYPE_PD); + ElementPtr pdpool_list = Element::createList(); + for (PoolCollection::const_iterator pool = pdpools.cbegin(); + pool != pdpools.cend(); ++pool) { + // Get it as a Pool6 (@todo move this code to pool.cc) + const Pool6* pdpool = dynamic_cast(pool->get()); + if (!pdpool) { + isc_throw(ToElementError, "invalid pd-pool pointer"); + } + // Prepare the map for a pd-pool + ElementPtr pool_map = Element::createMap(); + // Set prefix + const IOAddress& prefix = pdpool->getFirstAddress(); + pool_map->set("prefix", Element::create(prefix.toText())); + // Set prefix-len (get it from min - max) + const IOAddress& last = pdpool->getLastAddress(); + int prefix_len = prefixLengthFromRange(prefix, last); + if (prefix_len < 0) { + // The pool is bad: give up + isc_throw(ToElementError, "invalid prefix range " + << prefix.toText() << "-" << last.toText()); + } + pool_map->set("prefix-len", Element::create(prefix_len)); + // Set delegated-len + uint8_t len = pdpool->getLength(); + pool_map->set("delegated-len", + Element::create(static_cast(len))); + // Set excluded prefix + const Option6PDExcludePtr& xopt = + pdpool->getPrefixExcludeOption(); + if (xopt) { + const IOAddress& xprefix = + xopt->getExcludedPrefix(prefix, len); + pool_map->set("excluded-prefix", + Element::create(xprefix.toText())); + uint8_t xlen = xopt->getExcludedPrefixLength(); + pool_map->set("excluded-prefix-len", + Element::create(static_cast(xlen))); + } else { + pool_map->set("excluded-prefix", + Element::create(std::string("::"))); + pool_map->set("excluded-prefix-len", Element::create(0)); + } + // Set user-context + ConstElementPtr context = pdpool->getContext(); + if (!isNull(context)) { + pool_map->set("user-context", context); + } + // Set pool options + ConstCfgOptionPtr opts = pdpool->getCfgOption(); + pool_map->set("option-data", opts->toElement()); + // Push on the pool list + pdpool_list->add(pool_map); + } + map->set("pd-pools", pdpool_list); + // Set host reservation-mode + Subnet::HRMode hrmode = getHostReservationMode(); + std::string mode; + switch (hrmode) { + case Subnet::HR_DISABLED: + mode = "disabled"; + break; + case Subnet::HR_OUT_OF_POOL: + mode = "out-of-pool"; + break; + case Subnet::HR_ALL: + mode = "all"; + break; + default: + isc_throw(ToElementError, + "invalid host reservation mode: " << hrmode); + } + map->set("reservation-mode", Element::create(mode)); + // Set client-class + const ClientClasses& cclasses = getClientClasses(); + if (cclasses.size() > 1) { + isc_throw(ToElementError, "client-class has too many items: " + << cclasses.size()); + } else if (!cclasses.empty()) { + map->set("client-class", Element::create(*cclasses.cbegin())); + } + // Set options + ConstCfgOptionPtr opts = getCfgOption(); + map->set("option-data", opts->toElement()); + + return (map); +} + + } // end of isc::dhcp namespace } // end of isc namespace diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h index 683ca4b6da..e736fb6e89 100644 --- a/src/lib/dhcpsrv/subnet.h +++ b/src/lib/dhcpsrv/subnet.h @@ -8,6 +8,7 @@ #define SUBNET_H #include +#include #include #include #include @@ -280,7 +281,7 @@ public: /// returned it is valid. /// /// @return const reference to the relay information - const isc::dhcp::Subnet::RelayInfo& getRelayInfo() { + const isc::dhcp::Subnet::RelayInfo& getRelayInfo() const { return (relay_); } @@ -429,6 +430,11 @@ protected: /// type. bool poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const; + /// @brief Unparse a subnet object. + /// + /// @return A pointer to unparsed subnet configuration. + virtual data::ElementPtr toElement() const = 0; + /// @brief subnet-id /// /// Subnet-id is a unique value that can be used to find or identify @@ -577,6 +583,19 @@ public: return (dhcp4o6_); } + /// @brief Returns const DHCP4o6 configuration parameters. + /// + /// This structure is always available. If the 4o6 is not enabled, its + /// enabled_ field will be set to false. + const Cfg4o6& get4o6() const { + return (dhcp4o6_); + } + + /// @brief Unparse a subnet object. + /// + /// @return A pointer to unparsed subnet configuration. + virtual data::ElementPtr toElement() const; + private: /// @brief Returns default address for pool selection @@ -676,6 +695,11 @@ public: return (rapid_commit_); } + /// @brief Unparse a subnet object. + /// + /// @return A pointer to unparsed subnet configuration. + virtual data::ElementPtr toElement() const; + private: /// @brief Returns default address for pool selection -- 2.47.2