%PDF- %PDF-
| Direktori : /backups/router/usr/local/include/kea/dhcpsrv/ |
| Current File : //backups/router/usr/local/include/kea/dhcpsrv/cfg_shared_networks.h |
// Copyright (C) 2017-2024 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 CFG_SHARED_NETWORKS_H
#define CFG_SHARED_NETWORKS_H
#include <asiolink/io_address.h>
#include <cc/cfg_to_element.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/shared_network.h>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
namespace isc {
namespace dhcp {
/// @brief This class holds configuration of shared networks.
///
/// This is a generic class implementing basic functions such as shared network
/// addition, removal and retrieval. It also dumps configuration in the JSON
/// format.
///
/// There are specializations of this class implemented as
/// @ref CfgSharedNetworks4 and @ref CfgSharedNetworks6 for IPv4 and IPv6 cases
/// repspectively.
///
/// @tparam Type of the pointer to a shared network, i.e. @ref SharedNetwork4Ptr
/// or @ref SharedNetwork6Ptr.
template<typename SharedNetworkPtrType, typename SharedNetworkCollection>
class CfgSharedNetworks : public data::CfgToElement {
public:
/// @brief Returns pointer to all configured shared networks.
const SharedNetworkCollection* getAll() const {
return (&networks_);
}
/// @brief Adds new shared network to the configuration.
///
/// @param network Pointer to a network
///
/// @throw isc::BadValue when name is a duplicate of existing network's
/// name.
void add(const SharedNetworkPtrType& network) {
if (getByName(network->getName())) {
isc_throw(BadValue, "duplicate network '" << network->getName() <<
"' found in the configuration");
}
static_cast<void>(networks_.push_back(network));
}
/// @brief Deletes shared network from the configuration.
///
/// @param name Name of the network to be deleted.
///
/// @throw isc::BadValue if the network can't be found.
void del(const std::string& name) {
auto& index = networks_.template get<SharedNetworkNameIndexTag>();
auto shared_network = index.find(name);
if (shared_network != index.end()) {
// Delete all subnets from the network
(*shared_network)->delAll();
// Then delete the network from the networks list.
index.erase(shared_network);
} else {
isc_throw(BadValue, "unable to delete non-existing network '"
<< name << "' from shared networks configuration");
}
}
/// @brief Deletes shared networks from the configuration by id.
///
/// Note that there are cases when there will be multiple shared
/// networks having the same id (typically id of 0). When configuration
/// backend is in use it sets the unique ids from the database.
/// In cases when the configuration backend is not used, the ids
/// default to 0. Passing the id of 0 would result in deleting all
/// shared networks that were not added via the database.
///
/// @param id Identifier of the shared networks to be deleted.
///
/// @return Number of deleted shared networks.
uint64_t del(const uint64_t id) {
auto& index = networks_.template get<SharedNetworkIdIndexTag>();
auto sn_range = index.equal_range(id);
// For each shared network found, dereference the subnets belonging
// to it.
BOOST_FOREACH(auto const& it, sn_range) {
it->delAll();
}
// Remove the shared networks.
return (static_cast<uint64_t>(index.erase(id)));
}
/// @brief Retrieves shared network by name.
///
/// @param name Name of the network to be retrieved.
///
/// @return Pointer to the shared network or null pointer if the network
/// is not found.
SharedNetworkPtrType getByName(const std::string& name) const {
auto const& index = networks_.template get<SharedNetworkNameIndexTag>();
auto shared_network = index.find(name);
if (shared_network != index.cend()) {
return (*shared_network);
}
return (SharedNetworkPtrType());
}
/// @brief Unparses shared networks configuration.
///
/// @return Element object representing a list of shared networks held
/// within configuration. The networks are sorted by their names.
virtual data::ElementPtr toElement() const {
data::ElementPtr list = data::Element::createList();
// Insert shared networks sorted by their names into the list.
auto const& index = networks_.template get<SharedNetworkNameIndexTag>();
for (auto const& shared_network : index) {
list->add(shared_network->toElement());
}
return (list);
}
/// @brief Merges specified shared network configuration into this
/// configuration.
///
/// This method merges networks from the @c other configuration into this
/// configuration. The general rule is that existing networks are replaced
/// by the networks from @c other.
///
/// For each network in @c other, do the following:
///
/// - Any associated subnets are removed. Shared networks retrieved from
/// config backends, do not carry their associated subnets (if any) with
/// them. (Subnet assignments are maintained by subnet merges).
/// - If a shared network of the same name already exists in this
/// configuration:
/// - All of its associated subnets are moved to the "other" network.
/// - The existing network is removed from this configuration.
/// - The "other" network's option instances are created.
/// - The "other" network is added to this configuration.
///
/// @warning The merge operation may affect the @c other configuration.
/// Therefore, the caller must not rely on the data held in the @c other
/// object after the call to @c merge. Also, the data held in @c other must
/// not be modified after the call to @c merge because it may affect the
/// merged configuration.
///
/// @param cfg_def set of of user-defined option definitions to use
/// when creating option instances.
/// @param other the shared network configuration to be merged into this
/// configuration.
void merge(CfgOptionDefPtr cfg_def, CfgSharedNetworks& other) {
auto& index = networks_.template get<SharedNetworkNameIndexTag>();
// Iterate over the subnets to be merged. They will replace the existing
// subnets with the same id. All new subnets will be inserted into this
// configuration.
auto const& other_networks = other.getAll();
for (auto const& other_network : *other_networks) {
// In theory we should drop subnet assignments from "other". The
// idea being those that come from the CB should not have subnets_
// populated. We will quietly throw them away, just in case.
other_network->delAll();
// Check if the other network exists in this config.
auto existing_network = index.find(other_network->getName());
if (existing_network != index.end()) {
// Somehow the same instance is in both, skip it.
if (*existing_network == other_network) {
continue;
}
// Network exists, which means we're updating it.
// First we need to move its subnets to the new
// version of the network.
auto const subnets = (*existing_network)->getAllSubnets();
auto copy_subnets(*subnets);
for (auto const& subnet : copy_subnets) {
(*existing_network)->del(subnet->getID());
other_network->add(subnet);
}
// Now we discard the existing copy of the network.
index.erase(existing_network);
}
// Create the network's options based on the given definitions.
other_network->getCfgOption()->createOptions(cfg_def);
// Encapsulate options, so that the DHCP server can effectively return
// them to the clients without having to encapsulate them for each request.
other_network->getCfgOption()->encapsulate();
// Add the new/updated network.
static_cast<void>(networks_.push_back(other_network));
}
}
protected:
/// @brief Multi index container holding shared networks.
SharedNetworkCollection networks_;
};
/// @brief Represents configuration of IPv4 shared networks.
class CfgSharedNetworks4 : public CfgSharedNetworks<SharedNetwork4Ptr,
SharedNetwork4Collection> {
public:
/// @brief Checks if specified server identifier has been specified for
/// any network.
///
/// @param server_id Server identifier.
///
/// @return true if there is a network with a specified server identifier.
bool hasNetworkWithServerId(const asiolink::IOAddress& server_id) const;
};
/// @brief Pointer to the configuration of IPv4 shared networks.
typedef boost::shared_ptr<CfgSharedNetworks4> CfgSharedNetworks4Ptr;
/// @brief Represents configuration of IPv6 shared networks.
class CfgSharedNetworks6 : public CfgSharedNetworks<SharedNetwork6Ptr,
SharedNetwork6Collection> {
};
/// @brief Pointer to the configuration of IPv6 shared networks.
typedef boost::shared_ptr<CfgSharedNetworks6> CfgSharedNetworks6Ptr;
} // end of namespace isc::dhcp
} // end of namespace isc
#endif // CFG_SHARED_NETWORKS_H