cfg_subnets4.h 14.4 KB
Newer Older
1
// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
2
//
3 4 5
// 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/.
6 7 8 9 10

#ifndef CFG_SUBNETS4_H
#define CFG_SUBNETS4_H

#include <asiolink/io_address.h>
11
#include <cc/cfg_to_element.h>
12
#include <dhcp/pkt4.h>
13
#include <dhcpsrv/cfg_shared_networks.h>
14
#include <dhcpsrv/subnet.h>
15
#include <dhcpsrv/subnet_id.h>
16
#include <dhcpsrv/subnet_selector.h>
17
#include <boost/shared_ptr.hpp>
18
#include <string>
19 20 21 22 23 24 25 26 27 28 29 30

namespace isc {
namespace dhcp {

/// @brief Holds subnets configured for the DHCPv4 server.
///
/// This class holds a collection of subnets configured for the DHCPv4 server.
/// It allows for retrieving a subnet for the particular client using various
/// parameters extracted from the DHCPv4 message. These parameters must be
/// assigned to the appropriate members of the @c CfgSubnets4::Selector
/// structure.
///
31 32
/// See @c CfgSubnets4::selectSubnet documentation for more details on how the
/// subnet is selected for the client.
33
class CfgSubnets4 : public isc::data::CfgToElement {
34 35 36 37 38 39
public:

    /// @brief Adds new subnet to the configuration.
    ///
    /// @param subnet Pointer to the subnet being added.
    ///
40
    /// @throw isc::DuplicateSubnetID If the subnet id for the new subnet
41 42 43
    /// duplicates id of an existing subnet.
    void add(const Subnet4Ptr& subnet);

44 45 46 47 48 49 50
    /// @brief Removes subnet from the configuration.
    ///
    /// @param subnet Pointer to the subnet to be removed.
    ///
    /// @throw isc::BadValue if such subnet doesn't exist.
    void del(const ConstSubnet4Ptr& subnet);

51 52 53 54 55 56 57 58
    /// @brief Merges specified subnet configuration into this configuration.
    ///
    /// This method merges subnets from the @c other configuration into this
    /// configuration. The general rule is that existing subnets are replaced
    /// by the subnets from @c other. If there is no corresponding subnet in
    /// this configuration the subnet from @c other configuration is inserted.
    ///
    /// The complexity of the merge process stems from the associations between
59 60 61 62
    /// the subnets and shared networks.  It is assumed that subnets in @c other
    /// are the authority on their shared network assignments. It is also
    /// assumed that @ networks is the list of shared networks that should be
    /// used in making assignments.  The general concept is that the overarching
63 64 65
    /// merge process will first merge shared networks and then pass that list
    /// of networks into this method. Subnets from @c other are then merged
    /// into this configuration as follows:
66
    ///
67 68 69 70 71 72
    /// For each subnet in @c other:
    ///
    /// - If a subnet of the same ID already exists in this configuration:
    ///    -# If it belongs to a shared network, remove it from that network
    ///    -# Remove the subnet from this configuration and discard it
    ///
73
    /// - Add the subnet from @c other to this configuration.
74 75
    /// - If that subnet is associated to shared network, find that network
    ///   in @ networks and add that subnet to it.
76
    ///
77 78 79 80 81 82
    /// @warning The merge operation affects 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.
    ///
83
    /// @param networks collection of shared networks that to which assignments
84
    /// should be added. In other words, the list of shared networks that belong
85
    /// to the same SrvConfig instance we are merging into.
86 87
    /// @param other the subnet configuration to be merged into this
    /// configuration.
88
    void merge(CfgSharedNetworks4Ptr networks, const CfgSubnets4& other);
89

90 91 92 93 94 95 96 97 98 99 100
    /// @brief Returns pointer to the collection of all IPv4 subnets.
    ///
    /// This is used in a hook (subnet4_select), where the hook is able
    /// to choose a different subnet. Server code has to offer a list
    /// of possible choices (i.e. all subnets).
    ///
    /// @return A pointer to const Subnet4 collection
    const Subnet4Collection* getAll() const {
        return (&subnets_);
    }

101 102 103 104 105
    /// @brief Returns const pointer to a subnet identified by the specified
    /// subnet identifier.
    ///
    /// The const pointer is returned by this method to prevent a caller from
    /// modifying the subnet configuration. Modifications to subnet configuration
Francis Dupont's avatar
Francis Dupont committed
106
    /// is dangerous and must be done carefully. The subnets' configuration is
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    /// held in the multi index container and any modifications to the subnet
    /// id or subnet prefix must trigger re-indexing of multi index container.
    /// There is no possibility to enforce this when the non-const pointer is
    /// returned.
    ///
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Pointer to the @c Subnet4 object or null pointer if such
    /// subnet doesn't exist.
    ConstSubnet4Ptr getBySubnetId(const SubnetID& subnet_id) const;

    /// @brief Returns const pointer to a subnet which matches the specified
    /// prefix in the canonical form.
    ///
    /// The const pointer is returned by this method to prevent a caller from
    /// modifying the subnet configuration. Modifications to subnet configuration
Francis Dupont's avatar
Francis Dupont committed
123
    /// is dangerous and must be done carefully. The subnets' configuration is
124 125 126 127 128 129 130 131 132 133 134
    /// held in the multi index container and any modifications to the subnet
    /// id or subnet prefix must trigger re-indexing of multi index container.
    /// There is no possibility to enforce this when the non-const pointer is
    /// returned.
    ///
    /// @param subnet_prefix Subnet prefix, e.g. 10.2.3.0/24
    ///
    /// @return Pointer to the @c Subnet4 object or null pointer if such
    /// subnet doesn't exist.
    ConstSubnet4Ptr getByPrefix(const std::string& subnet_prefix) const;

135 136 137 138 139 140 141 142
    /// @brief Checks if specified server identifier has been specified for
    /// any subnet.
    ///
    /// @param server_id Server identifier.
    ///
    /// @return true if there is a subnet with a specified server identifier.
    bool hasSubnetWithServerId(const asiolink::IOAddress& server_id) const;

143 144 145 146 147 148 149 150
    /// @brief Build selector from a client's message.
    ///
    /// @note: code moved from server.
    ///
    /// @param query client's message.
    /// @return filled selector.
    static SubnetSelector initSelector(const Pkt4Ptr& query);

151
    /// @brief Returns a pointer to the selected subnet.
152 153 154 155 156
    ///
    /// This method tries to retrieve the subnet for the client using various
    /// parameters extracted from the client's message using the following
    /// logic.
    ///
157 158 159
    /// First when link select suboption of relay agent information option
    /// or subnet select option in this order exists the address is used
    ///
160 161 162 163 164 165 166 167
    /// If the giaddr value is set in the selector it means that the client's
    /// message was relayed. The subnet configuration allows for setting the
    /// relay address for each subnet to indicate that the subnet must be
    /// assigned when the packet was transmitted over the particular relay.
    /// This method first tries to match the giaddr with the relay addresses
    /// specified for all subnets. If the relay address for the subnet is equal
    /// to the address of the relay through which the message was transmitted,
    /// the particular subnet is returned.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    ///
    /// If the giaddr is not matched with any of the relay addresses in any
    /// subnet or the message was not relayed, the method will need to try to
    /// match one of the addresses in the client's message with the prefixes
    /// of the existing subnets. Depending whether it is a relayed message,
    /// message from the renewing client or a new allocation, the server will
    /// pick one of the following addresses for this matching:
    /// - giaddr - for relayed message
    /// - ciaddr - for renewing or rebinding client
    /// - source address - for the renewing client which didn't provide ciaddr
    /// - address on the local server's interface if this is a new allocation
    /// requested by the directly connected client
    ///
    /// If the address matches with a subnet, the subnet is returned.
    ///
183 184
    /// @todo This method requires performance improvement! It currently
    /// iterates over all existing subnets (possibly a couple of times)
Josh Soref's avatar
Josh Soref committed
185
    /// to find the one which fulfills the search criteria. The subnet storage
186 187 188 189 190
    /// is implemented as a simple STL vector which precludes fast searches
    /// using specific keys. Hence, full scan is required. To improve the
    /// search performance a different container type is required, e.g.
    /// multi-index container, or something of a similar functionality.
    ///
191 192 193 194 195 196 197
    /// @param selector Const reference to the selector structure which holds
    /// various information extracted from the client's packet which are used
    /// to find appropriate subnet.
    ///
    /// @return Pointer to the selected subnet or NULL if no subnet found.
    /// @throw isc::BadValue if the values in the subnet selector are invalid
    /// or they are insufficient to select a subnet.
198
    Subnet4Ptr selectSubnet(const SubnetSelector& selector) const;
199

200 201
    /// @brief Returns subnet with specified subnet-id value
    ///
Francis Dupont's avatar
Francis Dupont committed
202
    /// Warning: this method uses full scan. Its use is not recommended for
203 204 205 206 207
    /// packet processing.
    ///
    /// @return Subnet (or NULL)
    Subnet4Ptr getSubnet(const SubnetID id) const;

208
    /// @brief Returns a pointer to a subnet if provided address is in its range.
209 210 211
    ///
    /// This method returns a pointer to the subnet if the address passed in
    /// parameter is in range with this subnet. This is mainly used for unit
212 213
    /// testing. This method is also called by the
    /// @c selectSubnet(SubnetSelector).
214
    ///
215
    /// @todo This method requires performance improvement! It currently
Josh Soref's avatar
Josh Soref committed
216
    /// iterates over all existing subnets to find the one which fulfills
217 218 219 220 221 222
    /// the search criteria. The subnet storage is implemented as a simple
    /// STL vector which precludes fast searches using specific keys.
    /// Hence, full scan is required. To improve the search performance a
    /// different container type is required, e.g. multi-index container,
    /// or something of a similar functionality.
    ///
223 224 225 226 227
    /// @param address Address for which the subnet is searched.
    /// @param client_classes Optional parameter specifying the classes that
    /// the client belongs to.
    ///
    /// @return Pointer to the selected subnet or NULL if no subnet found.
228 229 230
    Subnet4Ptr selectSubnet(const asiolink::IOAddress& address,
                            const ClientClasses& client_classes
                            = ClientClasses()) const;
231

232
    /// @brief Returns a pointer to a subnet if provided interface name matches.
233 234
    ///
    /// This method returns a pointer to the subnet if the interface name passed
235
    /// in parameter iface matches that of a subnet. This is mainly used for matching
236
    /// local incoming traffic, even when the addresses on local interfaces do
237
    /// not match a subnet definition. This method is also called by the
238 239 240
    /// @c selectSubnet(SubnetSelector).
    ///
    /// @todo This method requires performance improvement! It currently
Josh Soref's avatar
Josh Soref committed
241
    /// iterates over all existing subnets to find the one which fulfills
242 243 244 245 246 247 248 249 250 251 252 253 254 255
    /// the search criteria. The subnet storage is implemented as a simple
    /// STL vector which precludes fast searches using specific keys.
    /// Hence, full scan is required. To improve the search performance a
    /// different container type is required, e.g. multi-index container,
    /// or something of a similar functionality.
    ///
    /// @param iface name of the interface to be matched.
    /// @param client_classes Optional parameter specifying the classes that
    /// the client belongs to.
    ///
    /// @return Pointer to the selected subnet or NULL if no subnet found.
    Subnet4Ptr selectSubnet(const std::string& iface,
                            const ClientClasses& client_classes) const;

256 257 258 259 260 261 262 263 264 265 266 267 268
    /// @brief Attempts to do subnet selection based on DHCP4o6 information
    ///
    /// The algorithm implemented is as follows:
    ///
    /// - First: try to match IPv6 subnet (4o6-subnet parameter) with the
    ///   remote IPv6 address of the incoming packet
    /// - Second: try to match interface-id (4o6-interface-id parameter)
    ///   with the interface-id option in the incoming 4o6 packet
    /// - Third: try to match interface-name (4o6-interface parameter)
    ///   with the name of the interface the incoming 4o6 packet was
    ///   received over.
    ///
    /// @todo: Add additional selection criteria. See
Vicky Risk's avatar
Vicky Risk committed
269
    ///  https://gitlab.isc.org/isc-projects/kea/wikis/designs/dhcpv4o6-design for details.
270 271 272 273 274 275 276 277
    ///
    /// @param selector Const reference to the selector structure which holds
    /// various information extracted from the client's packet which are used
    /// to find appropriate subnet.
    /// @return Pointer to the selected subnet or NULL if no subnet found.
    Subnet4Ptr
    selectSubnet4o6(const SubnetSelector& selector) const;

Tomek Mrugalski's avatar
Tomek Mrugalski committed
278 279 280 281 282
    /// @brief Updates statistics.
    ///
    /// This method updates statistics that are affected by the newly committed
    /// configuration. In particular, it updates the number of available addresses
    /// in each subnet. Other statistics may be added in the future. In general,
Andrei Pavel's avatar
Andrei Pavel committed
283
    /// these are statistics that are dependent only on configuration, so they are
Tomek Mrugalski's avatar
Tomek Mrugalski committed
284 285 286 287 288 289 290 291 292 293 294
    /// not expected to change until the next reconfiguration event.
    void updateStatistics();

    /// @brief Removes statistics.
    ///
    /// During commitment of a new configuration, we need to get rid of the old
    /// statistics for the old configuration. In particular, we need to remove
    /// anything related to subnets, as there may be fewer subnets in the new
    /// configuration and also subnet-ids may change.
    void removeStatistics();

Tomek Mrugalski's avatar
Tomek Mrugalski committed
295
    /// @brief Unparse a configuration object
296 297 298 299
    ///
    /// @return a pointer to unparsed configuration
    virtual isc::data::ElementPtr toElement() const;

300 301 302 303 304 305 306
private:

    /// @brief A container for IPv4 subnets.
    Subnet4Collection subnets_;

};

307 308 309 310 311 312 313 314 315 316
/// @name Pointer to the @c CfgSubnets4 objects.
//@{
/// @brief Non-const pointer.
typedef boost::shared_ptr<CfgSubnets4> CfgSubnets4Ptr;

/// @brief Const pointer.
typedef boost::shared_ptr<const CfgSubnets4> ConstCfgSubnets4Ptr;

//@}

317 318 319 320
}
}

#endif // CFG_SUBNETS4_H