diff options
-rw-r--r-- | src/hooks/dhcp/lease_cmds/lease_cmds.cc | 4 | ||||
-rw-r--r-- | src/hooks/dhcp/lease_cmds/lease_parser.cc | 3 | ||||
-rw-r--r-- | src/lib/dhcpsrv/alloc_engine.cc | 48 | ||||
-rw-r--r-- | src/lib/dhcpsrv/alloc_engine.h | 14 | ||||
-rw-r--r-- | src/lib/dhcpsrv/dhcpsrv_messages.cc | 6 | ||||
-rw-r--r-- | src/lib/dhcpsrv/dhcpsrv_messages.h | 3 | ||||
-rw-r--r-- | src/lib/dhcpsrv/dhcpsrv_messages.mes | 15 | ||||
-rw-r--r-- | src/lib/dhcpsrv/lease.cc | 13 | ||||
-rw-r--r-- | src/lib/dhcpsrv/lease.h | 20 | ||||
-rw-r--r-- | src/lib/dhcpsrv/lease_mgr.cc | 88 | ||||
-rw-r--r-- | src/lib/dhcpsrv/lease_mgr.h | 10 | ||||
-rw-r--r-- | src/lib/dhcpsrv/memfile_lease_mgr.cc | 70 | ||||
-rw-r--r-- | src/lib/dhcpsrv/memfile_lease_mgr.h | 11 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc | 6 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc | 4 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/alloc_engine_utils.h | 3 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/memfile_lease_extended_info_unittest.cc | 44 | ||||
-rw-r--r-- | src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc | 6 |
18 files changed, 293 insertions, 75 deletions
diff --git a/src/hooks/dhcp/lease_cmds/lease_cmds.cc b/src/hooks/dhcp/lease_cmds/lease_cmds.cc index e01f6ffdc8..4a5ed0c649 100644 --- a/src/hooks/dhcp/lease_cmds/lease_cmds.cc +++ b/src/hooks/dhcp/lease_cmds/lease_cmds.cc @@ -725,9 +725,9 @@ LeaseCmdsImpl::addOrUpdate6(Lease6Ptr lease, bool force_create) { if ((!old_extended_info && !extended_info) || (old_extended_info && extended_info && (*old_extended_info == *extended_info))) { - // Leave the default Lease::ACTION_IGNORE. + // Leave the default Lease6::ACTION_IGNORE. } else { - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; } } try { diff --git a/src/hooks/dhcp/lease_cmds/lease_parser.cc b/src/hooks/dhcp/lease_cmds/lease_parser.cc index ad0fb64c41..9cef198af2 100644 --- a/src/hooks/dhcp/lease_cmds/lease_parser.cc +++ b/src/hooks/dhcp/lease_cmds/lease_parser.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2023 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -175,6 +175,7 @@ Lease4Parser::parse(ConstSrvConfigPtr& cfg, if (ctx) { auto check = cfg->getConsistency()->getExtendedInfoSanityCheck(); LeaseMgr::upgradeLease4ExtendedInfo(l, check); + LeaseMgr::extractLease4ExtendedInfo(l); } // Retrieve the optional flag indicating if the lease must be created when it diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index e8e66f0fc6..e89141b792 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -2216,7 +2216,7 @@ AllocEngine::extendLease6(ClientContext6& ctx, Lease6Ptr lease) { // @todo should we call storeLease6ExtendedInfo() here ? updateLease6ExtendedInfo(lease, ctx); - if (lease->extended_info_action_ == Lease::ACTION_UPDATE) { + if (lease->extended_info_action_ == Lease6::ACTION_UPDATE) { changed = true; } @@ -2973,6 +2973,23 @@ AllocEngine::reclaimDeclined(const Lease6Ptr& lease) { return (true); } +void +AllocEngine::clearReclaimedExtendedInfo(const Lease4Ptr& lease) const { + lease->relay_id_.clear(); + lease->remote_id_.clear(); + if (lease->getContext()) { + lease->setContext(ElementPtr()); + } +} + +void +AllocEngine::clearReclaimedExtendedInfo(const Lease6Ptr& lease) const { + if (lease->getContext()) { + lease->extended_info_action_ = Lease6::ACTION_DELETE; + lease->setContext(ElementPtr()); + } +} + template<typename LeasePtrType> void AllocEngine::reclaimLeaseInDatabase(const LeasePtrType& lease, const bool remove_lease, @@ -2993,10 +3010,7 @@ void AllocEngine::reclaimLeaseInDatabase(const LeasePtrType& lease, lease->fqdn_fwd_ = false; lease->fqdn_rev_ = false; lease->state_ = Lease::STATE_EXPIRED_RECLAIMED; - if (lease->getContext()) { - lease->extended_info_action_ = Lease::ACTION_DELETE; - lease->setContext(ElementPtr()); - } + clearReclaimedExtendedInfo(lease); lease_update_fun(lease); } else { @@ -3894,7 +3908,7 @@ AllocEngine::createLease4(const ClientContext4& ctx, const IOAddress& addr, lease->hostname_ = ctx.hostname_; // Add(update) the extended information on the lease. - updateLease4ExtendedInfo(lease, ctx); + static_cast<void>(updateLease4ExtendedInfo(lease, ctx)); // Let's execute all callouts registered for lease4_select if (ctx.callout_handle_ && @@ -4473,30 +4487,28 @@ AllocEngine::updateLease4Information(const Lease4Ptr& lease, } // Add(update) the extended information on the lease. - updateLease4ExtendedInfo(lease, ctx); - if (lease->extended_info_action_ == Lease::ACTION_UPDATE) { + if (updateLease4ExtendedInfo(lease, ctx)) { changed = true; } return (changed); } -void +bool AllocEngine::updateLease4ExtendedInfo(const Lease4Ptr& lease, const AllocEngine::ClientContext4& ctx) const { - // The extended info action is a transient value but be safe so reset it. - lease->extended_info_action_ = Lease::ACTION_IGNORE; + bool changed = false; // If storage is not enabled then punt. if (!ctx.subnet_->getStoreExtendedInfo()) { - return; + return (changed); } // Look for relay agent information option (option 82) OptionPtr rai = ctx.query_->getOption(DHO_DHCP_AGENT_OPTIONS); if (!rai) { // Pkt4 doesn't have it, so nothing to store (or update). - return; + return (changed); } // Create a StringElement with the hex string for relay-agent-info. @@ -4509,6 +4521,7 @@ AllocEngine::updateLease4ExtendedInfo(const Lease4Ptr& lease, OptionPtr remote_id = rai->getOption(RAI_OPTION_REMOTE_ID); if (remote_id) { std::vector<uint8_t> bytes = remote_id->toBinary(false); + lease->remote_id_ = bytes; if (bytes.size() > 0) { extended_info->set("remote-id", Element::create(encode::encodeHex(bytes))); @@ -4518,6 +4531,7 @@ AllocEngine::updateLease4ExtendedInfo(const Lease4Ptr& lease, OptionPtr relay_id = rai->getOption(RAI_OPTION_RELAY_ID); if (relay_id) { std::vector<uint8_t> bytes = relay_id->toBinary(false); + lease->relay_id_ = bytes; if (bytes.size() > 0) { extended_info->set("relay-id", Element::create(encode::encodeHex(bytes))); @@ -4545,20 +4559,22 @@ AllocEngine::updateLease4ExtendedInfo(const Lease4Ptr& lease, // Add/replace the extended info entry. ConstElementPtr old_extended_info = mutable_isc->get("relay-agent-info"); if (!old_extended_info || (*old_extended_info != *extended_info)) { - lease->extended_info_action_ = Lease::ACTION_UPDATE; + changed = true; mutable_isc->set("relay-agent-info", extended_info); mutable_user_context->set("ISC", mutable_isc); } // Update the lease's user_context. lease->setContext(mutable_user_context); + + return (changed); } void AllocEngine::updateLease6ExtendedInfo(const Lease6Ptr& lease, const AllocEngine::ClientContext6& ctx) const { // The extended info action is a transient value but be safe so reset it. - lease->extended_info_action_ = Lease::ACTION_IGNORE; + lease->extended_info_action_ = Lease6::ACTION_IGNORE; // If storage is not enabled then punt. if (!ctx.subnet_->getStoreExtendedInfo()) { @@ -4653,7 +4669,7 @@ AllocEngine::updateLease6ExtendedInfo(const Lease6Ptr& lease, // Add/replace the extended info entry. ConstElementPtr old_extended_info = mutable_isc->get("relay-info"); if (!old_extended_info || (*old_extended_info != *extended_info)) { - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; mutable_isc->set("relay-info", extended_info); mutable_user_context->set("ISC", mutable_isc); } diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index 196ce2bfb7..38b727e82a 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -1744,7 +1744,9 @@ protected: /// @param [out] lease A pointer to the lease to be updated. /// @param ctx A context containing information from the server about the /// client and its message. - void updateLease4ExtendedInfo(const Lease4Ptr& lease, + /// @return True if there was a significant (e.g. other than cltt) change, + /// false otherwise. + bool updateLease4ExtendedInfo(const Lease4Ptr& lease, const ClientContext4& ctx) const; /// @brief Stores additional client query parameters on a V6 lease @@ -1765,6 +1767,16 @@ protected: void updateLease6ExtendedInfo(const Lease6Ptr& lease, const ClientContext6& ctx) const; + /// @brief Clear extended info from a reclaimed V4 lease + /// + /// @param [out] lease A pointer to the reclaimed lease. + void clearReclaimedExtendedInfo(const Lease4Ptr& lease) const; + + /// @brief Clear extended info from a reclaimed V6 lease + /// + /// @param [out] lease A pointer to the reclaimed lease. + void clearReclaimedExtendedInfo(const Lease6Ptr& lease) const; + private: /// @brief Try to reuse an already allocated lease. diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.cc b/src/lib/dhcpsrv/dhcpsrv_messages.cc index 68a04ae832..02d9bb1a99 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.cc +++ b/src/lib/dhcpsrv/dhcpsrv_messages.cc @@ -74,6 +74,7 @@ extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FIXED = "DHCPSRV_LEASE_SAN extern const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR4 = "DHCPSRV_MEMFILE_ADD_ADDR4"; extern const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6 = "DHCPSRV_MEMFILE_ADD_ADDR6"; extern const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6 = "DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6"; +extern const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4 = "DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4"; extern const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_TRANSACTION = "DHCPSRV_MEMFILE_BEGIN_TRANSACTION"; extern const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6 = "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6"; extern const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR = "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR"; @@ -84,6 +85,8 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR = "DHCPSRV_MEMFILE_ extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4 = "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4"; extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6 = "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6"; extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START = "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START"; +extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4 = "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4"; +extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR = "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR"; extern const isc::log::MessageID DHCPSRV_MEMFILE_GET4 = "DHCPSRV_MEMFILE_GET4"; extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6 = "DHCPSRV_MEMFILE_GET6"; extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID = "DHCPSRV_MEMFILE_GET6_DUID"; @@ -322,6 +325,7 @@ const char* values[] = { "DHCPSRV_MEMFILE_ADD_ADDR4", "adding IPv4 lease with address %1", "DHCPSRV_MEMFILE_ADD_ADDR6", "adding IPv6 lease with address %1", "DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6", "building extended info tables with %1 sanity check level%2, tables %3", + "DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4", "extract extended info with %1 sanity check level%2", "DHCPSRV_MEMFILE_BEGIN_TRANSACTION", "committing to memory file database", "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6", "building extended info tables saw %1 leases, extended info sanity checks modified %2 / updated %3 leases and %4 leases were entered into tables", "DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR", "building extended info tables got an exception on the lease for %1: %2", @@ -332,6 +336,8 @@ const char* values[] = { "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4", "deleting reclaimed IPv4 leases that expired more than %1 seconds ago", "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6", "deleting reclaimed IPv6 leases that expired more than %1 seconds ago", "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START", "starting deletion of %1 expired-reclaimed leases", + "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4", "extracting extended info saw %1 leases, extended info sanity checks modified %2 / updated %3 leases and %4 leases have relay or remote id", + "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR", "extracting extended info got an exception on the lease for %1: %2", "DHCPSRV_MEMFILE_GET4", "obtaining all IPv4 leases", "DHCPSRV_MEMFILE_GET6", "obtaining all IPv6 leases", "DHCPSRV_MEMFILE_GET6_DUID", "obtaining IPv6 leases for DUID %1", diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.h b/src/lib/dhcpsrv/dhcpsrv_messages.h index 42ee9497ae..a3d9c5362f 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.h +++ b/src/lib/dhcpsrv/dhcpsrv_messages.h @@ -75,6 +75,7 @@ extern const isc::log::MessageID DHCPSRV_LEASE_SANITY_FIXED; extern const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR4; extern const isc::log::MessageID DHCPSRV_MEMFILE_ADD_ADDR6; extern const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_BUILD_EXTENDED_INFO_TABLES6; +extern const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4; extern const isc::log::MessageID DHCPSRV_MEMFILE_BEGIN_TRANSACTION; extern const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6; extern const isc::log::MessageID DHCPSRV_MEMFILE_BUILD_EXTENDED_INFO_TABLES6_ERROR; @@ -85,6 +86,8 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_ADDR; extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED4; extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6; extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START; +extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4; +extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR; extern const isc::log::MessageID DHCPSRV_MEMFILE_GET4; extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6; extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID; diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index d2105472d9..3b60a833f5 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -1,4 +1,4 @@ -# Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -391,6 +391,11 @@ A debug message issued when the server is building extended info tables. The extended info sanity check level, update in file when requested and the fact tables are enabled or disabled are displayed. +% DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4 extract extended info with %1 sanity check level%2 +A debug message issued when the server is extracting extended info. +The extended info sanity check level and update in file when requested +are displayed. + % DHCPSRV_MEMFILE_BEGIN_TRANSACTION committing to memory file database The code has issued a begin transaction call. For the memory file database, this is a no-op. @@ -442,6 +447,14 @@ A debug message issued when the server has found expired-reclaimed leases to be removed. The number of leases to be removed is logged in the message. +% DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4 extracting extended info saw %1 leases, extended info sanity checks modified %2 / updated %3 leases and %4 leases have relay or remote id +Extended info extraction was finished. Some statistics are displayed, the +updated in database is returned to the command interface. + +% DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR extracting extended info got an exception on the lease for %1: %2 +A debug message issued when the server is extracting extended info and +receives an exception processing a lease. + % DHCPSRV_MEMFILE_GET4 obtaining all IPv4 leases A debug message issued when the server is attempting to obtain all IPv4 leases from the memory file database. diff --git a/src/lib/dhcpsrv/lease.cc b/src/lib/dhcpsrv/lease.cc index b11e45422f..061f823ba1 100644 --- a/src/lib/dhcpsrv/lease.cc +++ b/src/lib/dhcpsrv/lease.cc @@ -44,8 +44,7 @@ Lease::Lease(const isc::asiolink::IOAddress& addr, reuseable_valid_lft_(0), cltt_(cltt), current_cltt_(cltt), subnet_id_(subnet_id), hostname_(boost::algorithm::to_lower_copy(hostname)), fqdn_fwd_(fqdn_fwd), - fqdn_rev_(fqdn_rev), hwaddr_(hwaddr), state_(STATE_DEFAULT), - extended_info_action_(ExtendedInfoAction::ACTION_IGNORE) { + fqdn_rev_(fqdn_rev), hwaddr_(hwaddr), state_(STATE_DEFAULT) { } @@ -493,7 +492,8 @@ Lease6::Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr, SubnetID subnet_id, const HWAddrPtr& hwaddr, uint8_t prefixlen) : Lease(addr, valid, subnet_id, 0/*cltt*/, false, false, "", hwaddr), type_(type), prefixlen_(prefixlen), iaid_(iaid), duid_(duid), - preferred_lft_(preferred), reuseable_preferred_lft_(0) { + preferred_lft_(preferred), reuseable_preferred_lft_(0), + extended_info_action_(ExtendedInfoAction::ACTION_IGNORE) { if (!duid) { isc_throw(InvalidOperation, "DUID is mandatory for an IPv6 lease"); } @@ -510,7 +510,9 @@ Lease6::Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr, : Lease(addr, valid, subnet_id, 0/*cltt*/, fqdn_fwd, fqdn_rev, hostname, hwaddr), type_(type), prefixlen_(prefixlen), iaid_(iaid), duid_(duid), - preferred_lft_(preferred), reuseable_preferred_lft_(0) { + preferred_lft_(preferred), reuseable_preferred_lft_(0), + extended_info_action_(ExtendedInfoAction::ACTION_IGNORE) { + if (!duid) { isc_throw(InvalidOperation, "DUID is mandatory for an IPv6 lease"); } @@ -522,7 +524,8 @@ Lease6::Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr, Lease6::Lease6() : Lease(isc::asiolink::IOAddress("::"), 0, 0, 0, false, false, "", HWAddrPtr()), type_(TYPE_NA), prefixlen_(0), iaid_(0), - duid_(DuidPtr()), preferred_lft_(0), reuseable_preferred_lft_(0) { + duid_(DuidPtr()), preferred_lft_(0), reuseable_preferred_lft_(0), + extended_info_action_(ExtendedInfoAction::ACTION_IGNORE) { } std::string diff --git a/src/lib/dhcpsrv/lease.h b/src/lib/dhcpsrv/lease.h index 645a47056c..3fa764f9c9 100644 --- a/src/lib/dhcpsrv/lease.h +++ b/src/lib/dhcpsrv/lease.h @@ -184,16 +184,6 @@ struct Lease : public isc::data::UserContext, public isc::data::CfgToElement { /// belonging to this class. uint32_t state_; - /// @brief Action on extended info tables. - typedef enum { - ACTION_IGNORE, ///< ignore extended info, - ACTION_DELETE, ///< delete reference to the lease - ACTION_UPDATE ///< update extended info tables. - } ExtendedInfoAction; - - /// @brief Record the action on extended info tables in the lease. - ExtendedInfoAction extended_info_action_; - /// @brief Convert Lease to Printable Form /// /// @return String form of the lease @@ -563,6 +553,16 @@ struct Lease6 : public Lease { /// i.e. when the lease can be reused. uint32_t reuseable_preferred_lft_; + /// @brief Action on extended info tables. + typedef enum { + ACTION_IGNORE, ///< ignore extended info, + ACTION_DELETE, ///< delete reference to the lease + ACTION_UPDATE ///< update extended info tables. + } ExtendedInfoAction; + + /// @brief Record the action on extended info tables in the lease. + ExtendedInfoAction extended_info_action_; + /// @todo: Add DHCPv6 failover related fields here /// @brief Constructor diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc index 396537c808..c1c45283c1 100644 --- a/src/lib/dhcpsrv/lease_mgr.cc +++ b/src/lib/dhcpsrv/lease_mgr.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -961,6 +961,92 @@ LeaseMgr::upgradeLease6ExtendedInfo(const Lease6Ptr& lease, } } +void +LeaseMgr::extractLease4ExtendedInfo(const Lease4Ptr& lease, + bool ignore_errors) { + if (!lease) { + return; + } + + ConstElementPtr user_context = lease->getContext(); + if (!user_context) { + return; + } + if (user_context->getType() != Element::map) { + if (ignore_errors) { + return; + } + isc_throw(BadValue, "user context is not a map"); + } + if (user_context->empty()) { + return; + } + + ConstElementPtr isc = user_context->get("ISC"); + if (!isc) { + return; + } + if (isc->getType() != Element::map) { + if (ignore_errors) { + return; + } + isc_throw(BadValue, "ISC entry is not a map"); + } + if (isc->empty()) { + return; + } + + ConstElementPtr extended_info = isc->get("relay-agent-info"); + if (!extended_info) { + return; + } + if (extended_info->getType() != Element::map) { + if (ignore_errors) { + return; + } + isc_throw(BadValue, "relay-agent-info is not a map"); + } + if (extended_info->empty()) { + return; + } + + ConstElementPtr relay_id = extended_info->get("relay-id"); + if (relay_id) { + if (relay_id->getType() == Element::string) { + vector<uint8_t> bytes; + try { + encode::decodeHex(relay_id->stringValue(), bytes); + } catch (...) { + // Decode failed + if (!ignore_errors) { + throw; + } + } + lease->relay_id_ = bytes; + } else if (!ignore_errors) { + isc_throw(BadValue, "relay-id entry is not a string"); + } + } + + ConstElementPtr remote_id = extended_info->get("remote-id"); + if (remote_id) { + if (remote_id->getType() == Element::string) { + vector<uint8_t> bytes; + try { + encode::decodeHex(remote_id->stringValue(), bytes); + } catch (...) { + // Decode failed + if (!ignore_errors) { + throw; + } + } + lease->remote_id_ = bytes; + } else if (!ignore_errors) { + isc_throw(BadValue, "remote-id entry is not a string"); + } + } +} + bool LeaseMgr::addExtendedInfo6(const Lease6Ptr& lease) { diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h index fa473d14e4..94be5d6a30 100644 --- a/src/lib/dhcpsrv/lease_mgr.h +++ b/src/lib/dhcpsrv/lease_mgr.h @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -855,6 +855,14 @@ public: CfgConsistency::ExtendedInfoSanity check = CfgConsistency::EXTENDED_INFO_CHECK_FIX); + /// @brief Extract relay and remote identifiers from the extended info. + /// + /// @param lease Pointer to the lease to be updated. + /// @param ignore_errors When true (the default) ignore errors, + /// when false throw an exception. + static void extractLease4ExtendedInfo(const Lease4Ptr& lease, + bool ignore_errors = true); + /// @brief Returns existing IPv4 leases with a given relay-id. /// /// @param relay_id RAI Relay-ID sub-option value for relay_id of interest diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 02e6e5b801..c48196c13f 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -652,6 +652,7 @@ Memfile_LeaseMgr::Memfile_LeaseMgr(const DatabaseConnection::ParameterMap& param CSVLeaseFile4>(file4, lease_file4_, storage4_); + static_cast<void>(extractExtendedInfo4(false, false)); } } else { std::string file6 = initLeaseFilePath(V6); @@ -756,7 +757,7 @@ Memfile_LeaseMgr::addLeaseInternal(const Lease6Ptr& lease) { lease_file6_->append(*lease); } - lease->extended_info_action_ = Lease::ACTION_IGNORE; + lease->extended_info_action_ = Lease6::ACTION_IGNORE; storage6_.insert(lease); // Update lease current expiration time (allows update between the creation @@ -1473,8 +1474,8 @@ Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) { bool persist = persistLeases(V6); // Get the recorded action and reset it. - Lease::ExtendedInfoAction recorded_action = lease->extended_info_action_; - lease->extended_info_action_ = Lease::ACTION_IGNORE; + Lease6::ExtendedInfoAction recorded_action = lease->extended_info_action_; + lease->extended_info_action_ = Lease6::ACTION_IGNORE; // Lease must exist if it is to be updated. Lease6StorageAddressIndex::const_iterator lease_it = index.find(lease->addr_); @@ -1512,14 +1513,14 @@ Memfile_LeaseMgr::updateLease6Internal(const Lease6Ptr& lease) { // Update extended info tables. if (getExtendedInfoTablesEnabled()) { switch (recorded_action) { - case Lease::ACTION_IGNORE: + case Lease6::ACTION_IGNORE: break; - case Lease::ACTION_DELETE: + case Lease6::ACTION_DELETE: deleteExtendedInfo6(lease->addr_); break; - case Lease::ACTION_UPDATE: + case Lease6::ACTION_UPDATE: deleteExtendedInfo6(lease->addr_); static_cast<void>(addExtendedInfo6(lease)); break; @@ -1589,7 +1590,7 @@ Memfile_LeaseMgr::deleteLease(const Lease4Ptr& lease) { bool Memfile_LeaseMgr::deleteLeaseInternal(const Lease6Ptr& lease) { - lease->extended_info_action_ = Lease::ACTION_IGNORE; + lease->extended_info_action_ = Lease6::ACTION_IGNORE; const isc::asiolink::IOAddress& addr = lease->addr_; Lease6Storage::iterator l = storage6_.find(addr); @@ -2938,6 +2939,61 @@ Memfile_LeaseMgr::getLeases6ByLinkInternal(const IOAddress& link_addr, } size_t +Memfile_LeaseMgr::extractExtendedInfo4(bool update, bool current) { + CfgConsistencyPtr cfg; + if (current) { + cfg = CfgMgr::instance().getCurrentCfg()->getConsistency(); + } else { + cfg = CfgMgr::instance().getStagingCfg()->getConsistency(); + } + if (!cfg) { + isc_throw(Unexpected, "the " << (current ? "current" : "staging") + << " consistency configuration is null"); + } + auto check = cfg->getExtendedInfoSanityCheck(); + + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, + DHCPSRV_MEMFILE_BEGIN_EXTRACT_EXTENDED_INFO4) + .arg(CfgConsistency::sanityCheckToText(check)) + .arg(update ? " updating in file" : ""); + + size_t leases = 0; + size_t modified = 0; + size_t updated = 0; + size_t processed = 0; + + for (auto lease : storage4_) { + ++leases; + try { + if (upgradeLease4ExtendedInfo(lease, check)) { + ++modified; + if (update && persistLeases(V4)) { + lease_file4_->append(*lease); + ++updated; + } + } + extractLease4ExtendedInfo(lease, false); + if (!lease->relay_id_.empty() || !lease->remote_id_.empty()) { + ++processed; + } + } catch (const std::exception& ex) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, + DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR) + .arg(lease->addr_.toText()) + .arg(ex.what()); + } + } + + LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4) + .arg(leases) + .arg(modified) + .arg(updated) + .arg(processed); + + return (updated); +} + +size_t Memfile_LeaseMgr::buildExtendedInfoTables6Internal(bool update, bool current) { CfgConsistencyPtr cfg; if (current) { diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 6ddd6e7f4a..4fe336265d 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -1477,6 +1477,17 @@ private: const asiolink::IOAddress& lower_bound_address, const LeasePageSize& page_size); + /// @brief Extract extended info for v4 leases. + /// + /// For v4 relay and remote identifiers are stored inside leases vs. + /// tables for v6. + /// + /// @param update Update extended info in database. + /// @param current specify whether to use current (true) or staging + /// (false) config. + /// @return The number of updates in the database or 0. + size_t extractExtendedInfo4(bool update, bool current); + /// @brief Build extended info v6 tables. /// /// @param update Update extended info in database. diff --git a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc index 6a37dc40bc..9686cd68ea 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc @@ -3720,10 +3720,8 @@ TEST_F(AllocEngine4Test, updateExtendedInfo4) { } // Call AllocEngine::updateLease4ExtendeInfo(). - ASSERT_NO_THROW_LOG(engine.callUpdateLease4ExtendedInfo(lease, ctx)); - bool ret = (lease->extended_info_action_ == Lease::ACTION_UPDATE); - // Reset the lease action. - lease->extended_info_action_ = Lease::ACTION_IGNORE; + bool ret = false; + ASSERT_NO_THROW_LOG(ret = engine.callUpdateLease4ExtendedInfo(lease, ctx)); ASSERT_EQ(scenario.exp_ret, ret); // Verify the lease has the expected user context content. diff --git a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc index a7b834ef75..a5d1b065a1 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine6_unittest.cc @@ -4111,9 +4111,9 @@ TEST_F(AllocEngine6ExtendedInfoTest, updateExtendedInfo6) { // Call AllocEngine::updateLease6ExtendeInfo(). ASSERT_NO_THROW_LOG(engine_.callUpdateLease6ExtendedInfo(lease, ctx)); - bool ret = (lease->extended_info_action_ == Lease::ACTION_UPDATE); + bool ret = (lease->extended_info_action_ == Lease6::ACTION_UPDATE); // Reset the lease action. - lease->extended_info_action_ = Lease::ACTION_IGNORE; + lease->extended_info_action_ = Lease6::ACTION_IGNORE; ASSERT_EQ(scenario.exp_ret, ret); // Verify the lease has the expected user context content. diff --git a/src/lib/dhcpsrv/tests/alloc_engine_utils.h b/src/lib/dhcpsrv/tests/alloc_engine_utils.h index d22e166caf..4d3b36bc80 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_utils.h +++ b/src/lib/dhcpsrv/tests/alloc_engine_utils.h @@ -86,7 +86,8 @@ public: /// @brief Wrapper method for invoking AllocEngine4::updateLease4ExtendedInfo(). /// @param lease lease to update /// @param ctx current packet processing context - void callUpdateLease4ExtendedInfo(const Lease4Ptr& lease, + /// @return true if extended information was changed + bool callUpdateLease4ExtendedInfo(const Lease4Ptr& lease, AllocEngine::ClientContext4& ctx) const { return (updateLease4ExtendedInfo(lease, ctx)); } diff --git a/src/lib/dhcpsrv/tests/memfile_lease_extended_info_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_extended_info_unittest.cc index 8c04c13f67..b218df8043 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_extended_info_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_extended_info_unittest.cc @@ -79,7 +79,7 @@ public: MemfileExtendedInfoTest() { pmap_.clear(); lease_mgr_.reset(); - leases4.clear(); + leases4.clear(); leases6.clear(); MultiThreadingMgr::instance().setMode(false); } @@ -88,7 +88,7 @@ public: ~MemfileExtendedInfoTest() { pmap_.clear(); lease_mgr_.reset(); - leases4.clear(); + leases4.clear(); leases6.clear(); MultiThreadingMgr::instance().setMode(false); } @@ -731,11 +731,11 @@ TEST_F(MemfileExtendedInfoTest, deleteLease6) { ASSERT_TRUE(lease); EXPECT_NE(lease_addr, lease->addr_); // Put a value different of the expected one. - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; bool ret = false; EXPECT_NO_THROW(ret = lease_mgr_->deleteLease(lease)); EXPECT_TRUE(ret); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); EXPECT_EQ(2, lease_mgr_->relay_id6_.size()); EXPECT_EQ(2, lease_mgr_->remote_id6_.size()); @@ -773,11 +773,11 @@ TEST_F(MemfileExtendedInfoTest, deleteLease6disabled) { ASSERT_TRUE(lease); EXPECT_EQ(lease_addr, lease->addr_); // Put a value different from the expected one. - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; bool ret = false; EXPECT_NO_THROW(ret = lease_mgr_->deleteLease(lease)); EXPECT_TRUE(ret); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); EXPECT_EQ(1, lease_mgr_->relay_id6_.size()); EXPECT_EQ(1, lease_mgr_->remote_id6_.size()); } @@ -806,11 +806,11 @@ TEST_F(MemfileExtendedInfoTest, addLease6) { ASSERT_NO_THROW(user_context = Element::fromJSON(user_context_txt)); lease->setContext(user_context); // Put a value different of the expected one. - lease->extended_info_action_ = Lease::ACTION_DELETE; + lease->extended_info_action_ = Lease6::ACTION_DELETE; bool ret = false; EXPECT_NO_THROW(ret = lease_mgr_->addLease(lease)); EXPECT_TRUE(ret); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Check extended info tables. ASSERT_EQ(1, lease_mgr_->relay_id6_.size()); @@ -856,11 +856,11 @@ TEST_F(MemfileExtendedInfoTest, addLease6disabled) { ElementPtr user_context; ASSERT_NO_THROW(user_context = Element::fromJSON(user_context_txt)); lease->setContext(user_context); - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; bool ret = false; EXPECT_NO_THROW(ret = lease_mgr_->addLease(lease)); EXPECT_TRUE(ret); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); EXPECT_TRUE(lease_mgr_->relay_id6_.empty()); EXPECT_TRUE(lease_mgr_->remote_id6_.empty()); } @@ -897,9 +897,9 @@ TEST_F(MemfileExtendedInfoTest, updateLease6ignore) { lease->setContext(user_context); // Set action and call updateLease6. - lease->extended_info_action_ = Lease::ACTION_IGNORE; + lease->extended_info_action_ = Lease6::ACTION_IGNORE; ASSERT_NO_THROW(lease_mgr_->updateLease6(lease)); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Tables were not touched. EXPECT_TRUE(lease_mgr_->relay_id6_.empty()); @@ -943,9 +943,9 @@ TEST_F(MemfileExtendedInfoTest, updateLease6delete) { // Set action and call updateLease6. lease.reset(new Lease6(*lease)); - lease->extended_info_action_ = Lease::ACTION_DELETE;; + lease->extended_info_action_ = Lease6::ACTION_DELETE;; ASSERT_NO_THROW(lease_mgr_->updateLease6(lease)); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Tables were cleared. EXPECT_TRUE(lease_mgr_->relay_id6_.empty()); @@ -989,9 +989,9 @@ TEST_F(MemfileExtendedInfoTest, updateLease6deleteDisabled) { // Set action and call updateLease6. lease.reset(new Lease6(*lease)); - lease->extended_info_action_ = Lease::ACTION_DELETE;; + lease->extended_info_action_ = Lease6::ACTION_DELETE;; ASSERT_NO_THROW(lease_mgr_->updateLease6(lease)); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Tables were not touched. EXPECT_EQ(1, lease_mgr_->relay_id6_.size()); @@ -1032,9 +1032,9 @@ TEST_F(MemfileExtendedInfoTest, updateLease6update) { lease->setContext(user_context); // Set action and call updateLease6. - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; ASSERT_NO_THROW(lease_mgr_->updateLease6(lease)); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Tables were updated. ASSERT_EQ(1, lease_mgr_->relay_id6_.size()); @@ -1090,9 +1090,9 @@ TEST_F(MemfileExtendedInfoTest, updateLease6updateDisabled) { lease->setContext(user_context); // Set action and call updateLease6. - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; ASSERT_NO_THROW(lease_mgr_->updateLease6(lease)); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Tables were not touched. EXPECT_TRUE(lease_mgr_->relay_id6_.empty()); @@ -1162,9 +1162,9 @@ TEST_F(MemfileExtendedInfoTest, updateLease6update2) { lease->setContext(user_context); // Set action and call updateLease6. - lease->extended_info_action_ = Lease::ACTION_UPDATE; + lease->extended_info_action_ = Lease6::ACTION_UPDATE; ASSERT_NO_THROW(lease_mgr_->updateLease6(lease)); - EXPECT_EQ(Lease::ACTION_IGNORE, lease->extended_info_action_); + EXPECT_EQ(Lease6::ACTION_IGNORE, lease->extended_info_action_); // Tables were updated. ASSERT_EQ(1, lease_mgr_->relay_id6_.size()); diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index 1da0b9620a..d542791f10 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2023 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -2374,6 +2374,10 @@ TEST_F(MemfileLeaseMgrTest, v4UserContext) { "{ \"a\": \"b\", \"c\": { \"d\": 1,\"e\": 2 } }\n" ); + // Not sanitize user contexts. + CfgMgr::instance().getStagingCfg()->getConsistency()-> + setExtendedInfoSanityCheck(CfgConsistency::EXTENDED_INFO_CHECK_NONE); + startBackend(V4); // Check the lease with no key-value pairs in the user context. |