From: Francis Dupont Date: Thu, 15 Feb 2018 23:26:56 +0000 (+0100) Subject: [5532] Reported trac5531 changes X-Git-Tag: trac5533_base~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bed79e2e73e494a3e722aeb9ce57f80a107a1dd7;p=thirdparty%2Fkea.git [5532] Reported trac5531 changes --- diff --git a/src/lib/dhcpsrv/testutils/memory_host_data_source.cc b/src/lib/dhcpsrv/testutils/memory_host_data_source.cc new file mode 100644 index 0000000000..d15717f3fb --- /dev/null +++ b/src/lib/dhcpsrv/testutils/memory_host_data_source.cc @@ -0,0 +1,233 @@ +// Copyright (C) 2018 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 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include + +using namespace std; + +namespace isc { +namespace dhcp { +namespace test { + +ConstHostCollection +MemHostDataSource::getAll(const HWAddrPtr& /*hwaddr*/, + const DuidPtr& /*duid*/) const { + return (ConstHostCollection()); +} + +ConstHostCollection +MemHostDataSource::getAll(const Host::IdentifierType& /*identifier_type*/, + const uint8_t* /*identifier_begin*/, + const size_t /*identifier_len*/) const { + return (ConstHostCollection()); +} + +ConstHostCollection +MemHostDataSource::getAll4(const asiolink::IOAddress& /*address*/) const { + return (ConstHostCollection()); +} + +ConstHostPtr +MemHostDataSource::get4(const SubnetID& /*subnet_id*/, + const HWAddrPtr& /*hwaddr*/, + const DuidPtr& /*duid*/) const { + return (ConstHostPtr()); +} + +ConstHostPtr +MemHostDataSource::get4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const { + vector ident(identifier_begin, identifier_begin + identifier_len); + for (auto h = store_.begin(); h != store_.end(); ++h) { + // If either subnet-id or identifier type do not match, + // it's not our host + if (((*h)->getIPv4SubnetID() != subnet_id) || + ((*h)->getIdentifierType() != identifier_type)) { + continue; + } + // If the identifier matches, we found it! + if ((*h)->getIdentifier() == ident) { + return (*h); + } + } + + // Nothing found + return (ConstHostPtr()); +} + +ConstHostPtr +MemHostDataSource::get6(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const { + vector ident(identifier_begin, identifier_begin + identifier_len); + for (auto h = store_.begin(); h != store_.end(); ++h) { + // If either subnet-id or identifier type do not match, + // it's not our host + if (((*h)->getIPv6SubnetID() != subnet_id) || + ((*h)->getIdentifierType() != identifier_type)) { + continue; + } + // If the identifier matches, we found it! + if ((*h)->getIdentifier() == ident) { + return (*h); + } + } + + return (ConstHostPtr()); +} + +ConstHostPtr +MemHostDataSource::get4(const SubnetID& subnet_id, + const asiolink::IOAddress& address) const { + for (auto h = store_.begin(); h != store_.end(); ++h) { + if ((*h)->getIPv4SubnetID() == subnet_id && + (*h)->getIPv4Reservation() == address) { + return (*h); + } + } + + return (ConstHostPtr()); +} + +ConstHostPtr +MemHostDataSource::get6(const SubnetID& /*subnet_id*/, + const DuidPtr& /*duid*/, + const HWAddrPtr& /*hwaddr*/) const { + return (ConstHostPtr()); +} + +ConstHostPtr +MemHostDataSource::get6(const asiolink::IOAddress& /*prefix*/, + const uint8_t /*prefix_len*/) const { + return (ConstHostPtr()); +} + +ConstHostPtr +MemHostDataSource::get6(const SubnetID& subnet_id, + const asiolink::IOAddress& address) const { + for (auto h = store_.begin(); h != store_.end(); ++h) { + + // Naive approach: check hosts one by one + + // First check: subnet-id must match. + if ((*h)->getIPv6SubnetID() != subnet_id) { + // wrong subnet-id? ok, skip this one + continue; + } + + // Second check: the v6 reservation must much. This is very simple + // as we ignore the reservation type. + auto resrvs = (*h)->getIPv6Reservations(); + for (auto r = resrvs.first; r != resrvs.second; ++r) { + if ((*r).second.getPrefix() == address) { + return (*h); + } + } + } + + return (ConstHostPtr()); +} + +bool +MemHostDataSource::add(const HostPtr& host) { + store_.push_back(host); + return (true); +} + +bool +MemHostDataSource::del(const SubnetID& subnet_id, + const asiolink::IOAddress& addr) { + for (auto h = store_.begin(); h != store_.end(); ++h) { + if (addr.isV4()) { + if ((*h)->getIPv4SubnetID() == subnet_id && + (*h)->getIPv4Reservation() == addr) { + store_.erase(h); + return (true); + } + } else { + + if ((*h)->getIPv6SubnetID() != subnet_id) { + continue; + } + + // Second check: the v6 reservation must much. This is very simple + // as we ignore the reservation type. + auto resrvs = (*h)->getIPv6Reservations(); + for (auto r = resrvs.first; r != resrvs.second; ++r) { + if ((*r).second.getPrefix() == addr) { + store_.erase(h); + return (true); + } + } + } + } + + return (false); +} + +bool +MemHostDataSource::del4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) { + vector ident(identifier_begin, identifier_begin + identifier_len); + for (auto h = store_.begin(); h != store_.end(); ++h) { + // If either subnet-id or identifier type do not match, + // it's not our host + if (((*h)->getIPv4SubnetID() != subnet_id) || + ((*h)->getIdentifierType() != identifier_type)) { + continue; + } + // If the identifier matches, we found it! + if ((*h)->getIdentifier() == ident) { + store_.erase(h); + return (true); + } + } + + return (false); +} + +bool +MemHostDataSource::del6(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) { + vector ident(identifier_begin, identifier_begin + identifier_len); + for (auto h = store_.begin(); h != store_.end(); ++h) { + // If either subnet-id or identifier type do not match, + // it's not our host + if (((*h)->getIPv6SubnetID() != subnet_id) || + ((*h)->getIdentifierType() != identifier_type)) { + continue; + } + // If the identifier matches, we found it! + if ((*h)->getIdentifier() == ident) { + store_.erase(h); + return (true); + } + } + return (false); +} + +size_t +MemHostDataSource::size() const { + return (store_.size()); +} + +BaseHostDataSource* +memFactory(const DatabaseConnection::ParameterMap& /*parameters*/) { + return (new MemHostDataSource()); +} + +} // namespace isc::dhcp::test +} // namespace isc::dhcp +} // namespace isc diff --git a/src/lib/dhcpsrv/testutils/memory_host_data_source.h b/src/lib/dhcpsrv/testutils/memory_host_data_source.h new file mode 100644 index 0000000000..648a9b99de --- /dev/null +++ b/src/lib/dhcpsrv/testutils/memory_host_data_source.h @@ -0,0 +1,235 @@ +// Copyright (C) 2018 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 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef MEMORY_HOST_DATA_SOURCE_H +#define MEMORY_HOST_DATA_SOURCE_H + +#include +#include +#include +#include + +namespace isc { +namespace dhcp { +namespace test { + +/// @brief Simple host data source implementation for tests. +/// +/// It used vector as a storage and iterates through all hosts when +/// conducting operations. Most operations are skeleton methods that don't +/// work, just several are implemented. Those are used in the tests. +class MemHostDataSource : public BaseHostDataSource { +public: + + /// @brief Destructor. + virtual ~MemHostDataSource() { } + + /// BaseHostDataSource methods. + + /// @brief Return all hosts for the specified HW address or DUID. + /// + /// @param hwaddr HW address of the client or NULL if no HW address + /// available. + /// @param duid client id or NULL if not available, e.g. DHCPv4 client case. + /// @return Empty collection of const @c Host objects. + virtual ConstHostCollection + getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const; + + /// @brief Return all hosts connected to any subnet for which reservations + /// have been made using a specified identifier. + /// + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return Empty collection of const @c Host objects. + virtual ConstHostCollection + getAll(const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const; + + /// @brief Returns a collection of hosts using the specified IPv4 address. + /// + /// @param address IPv4 address for which the @c Host object is searched. + /// @return Empty collection of const @c Host objects. + virtual ConstHostCollection + getAll4(const asiolink::IOAddress& address) const; + + /// @brief Returns a host connected to the IPv4 subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param hwaddr HW address of the client or NULL if no HW address + /// available. + /// @param duid client id or NULL if not available. + /// @return Const @c Host object using a specified HW address or DUID. + virtual ConstHostPtr + get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr, + const DuidPtr& duid = DuidPtr()) const; + + + /// @brief Returns a host connected to the IPv4 subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return Const @c Host object for which reservation has been made using + /// the specified identifier. + virtual ConstHostPtr + get4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const; + + /// @brief Returns a host connected to the IPv4 subnet and having + /// a reservation for a specified IPv4 address. + /// + /// @param subnet_id Subnet identifier. + /// @param address reserved IPv4 address. + /// @return Const @c Host object using a specified IPv4 address. + virtual ConstHostPtr + get4(const SubnetID& subnet_id, + const asiolink::IOAddress& address) const; + + /// @brief Returns a host connected to the IPv6 subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param hwaddr HW address of the client or NULL if no HW address + /// available. + /// @param duid DUID or NULL if not available. + /// @return Const @c Host object using a specified HW address or DUID. + virtual ConstHostPtr + get6(const SubnetID& subnet_id, const DuidPtr& duid, + const HWAddrPtr& hwaddr = HWAddrPtr()) const; + + /// @brief Returns a host connected to the IPv6 subnet. + /// + /// @param subnet_id Subnet identifier. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return Const @c Host object for which reservation has been made using + /// the specified identifier. + virtual ConstHostPtr + get6(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, + const size_t identifier_len) const; + + /// @brief Returns a host using the specified IPv6 prefix. + /// + /// @param prefix IPv6 prefix for which the @c Host object is searched. + /// @param prefix_len IPv6 prefix length. + /// @return Const @c Host object using a specified HW address or DUID. + virtual ConstHostPtr + get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const; + + /// @brief Returns a host connected to the IPv6 subnet and having + /// a reservation for a specified IPv6 address or prefix. + /// + /// @param subnet_id Subnet identifier. + /// @param address reserved IPv6 address/prefix. + /// @return Const @c Host object using a specified IPv6 address/prefix. + virtual ConstHostPtr + get6(const SubnetID& subnet_id, const asiolink::IOAddress& address) const; + + /// @brief Adds a new host to the collection. + /// + /// @param host Pointer to the new @c Host object being added. + /// @return true if addition was successful. + virtual bool add(const HostPtr& host); + + /// @brief Attempts to delete a host by (subnet-id, address) + /// + /// @param subnet_id subnet identifier. + /// @param addr specified address. + /// @return true if deletion was successful, false if the host was not there. + /// @throw various exceptions in case of errors + virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr); + + /// @brief Attempts to delete a host by (subnet-id4, identifier, identifier-type) + /// + /// @param subnet_id IPv4 Subnet identifier. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return true if deletion was successful, false if the host was not there. + /// @throw various exceptions in case of errors + virtual bool del4(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, const size_t identifier_len); + + /// @brief Attempts to delete a host by (subnet-id6, identifier, identifier-type) + /// + /// @param subnet_id IPv6 Subnet identifier. + /// @param identifier_type Identifier type. + /// @param identifier_begin Pointer to a beginning of a buffer containing + /// an identifier. + /// @param identifier_len Identifier length. + /// @return true if deletion was successful, false if the host was not there. + /// @throw various exceptions in case of errors + virtual bool del6(const SubnetID& subnet_id, + const Host::IdentifierType& identifier_type, + const uint8_t* identifier_begin, const size_t identifier_len); + + /// @brief Return backend type + /// + /// Returns the type of the backend (e.g. "mysql", "memfile" etc.) + /// + /// @return Type of the backend. + virtual std::string getType() const { + return ("mem"); + } + + /// More lease backend? + + /// @brief Returns name of the database or file used by the backend + /// @return "mem" string" + virtual std::string getName() const { + return (std::string("mem")); + } + + /// @brief Returns description of the backend. + /// @return description + virtual std::string getDescription() const { + return (std::string("In memory storage, mostly useful for testing.")); + } + + /// @brief Returns version this backend + /// @return two numbers that each represent practical value of this backend. + virtual std::pair getVersion() const { + return (std::make_pair(0,0)); + } + + /// @brief Returns store size. + /// @return number of hosts in the store. + virtual size_t size() const; + +protected: + // This is very simple storage. + + /// @brief Store + std::vector store_; +}; + +/// Pointer to the Mem host data source. +typedef boost::shared_ptr MemHostDataSourcePtr; + +/// @brief Factory function. +/// +/// @param parameters +/// @return A pointer to a base host data source instance. +BaseHostDataSource* +memFactory(const DatabaseConnection::ParameterMap& /*parameters*/); + +} // namespace isc::dhcp::test +} // namespace isc::dhcp +} // namespace isc + +#endif