network.h 17.4 KB
Newer Older
1
// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9
//
// 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 NETWORK_H
#define NETWORK_H

10
#include <asiolink/io_address.h>
11 12
#include <cc/cfg_to_element.h>
#include <cc/data.h>
13
#include <cc/stamped_element.h>
14
#include <cc/user_context.h>
15
#include <dhcp/classify.h>
16
#include <dhcp/option.h>
17 18
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfg_4o6.h>
19
#include <dhcpsrv/triplet.h>
20
#include <boost/shared_ptr.hpp>
21
#include <boost/weak_ptr.hpp>
22
#include <cstdint>
23 24 25 26 27
#include <string>

namespace isc {
namespace dhcp {

28 29 30
/// List of IOAddresses
typedef std::vector<isc::asiolink::IOAddress> IOAddressList;

31 32 33 34 35
/// @brief Common interface representing a network to which the DHCP clients
/// are connected.
///
/// The most common type of network, in Kea's terminology, is a subnet. The
/// @ref Subnet implements this interface. Another types of objects implementing
Francis Dupont's avatar
Francis Dupont committed
36 37 38 39 40 41
/// this interface are @ref SharedNetwork4 and @ref SharedNetwork6 objects.
/// They group multiple subnets together to provide means for
/// extending available address pools (a single client may obtain IP
/// address from any of the pools belonging to subnets in the shared
/// network), or for selecting a subnet on a given link, depending on the
/// class of the client (e.g. cable network case: different subnet is
42 43 44 45 46 47 48
/// selected for cable modems, different one for routers).
///
/// The subnets and shared networks share many data structures, e.g. DHCP
/// options, local interface name, address manipulation methods, thus this
/// class provides an abstract interface that must be implemented by derived
/// classes and, where appropriate, implements common methods used by the
/// derived classes.
49 50 51
class Network : public virtual isc::data::StampedElement,
                public virtual isc::data::UserContext,
                public isc::data::CfgToElement {
52
public:
53 54 55 56
    /// @brief Holds optional information about relay.
    ///
    /// In some cases it is beneficial to have additional information about
    /// a relay configured in the subnet. For now, the structure holds only
57
    /// IP addresses, but there may potentially be additional parameters added
58
    /// later, e.g. relay interface-id or relay-id.
59 60
    class RelayInfo {
    public:
61

62
        /// @brief Adds an address to the list of addresses
63
        ///
64 65 66
        /// @param addr address to add
        /// @throw BadValue if the address is already in the list
        void addAddress(const asiolink::IOAddress& addr);
67

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
        /// @brief Returns const reference to the list of addresses
        ///
        /// @return const reference to the list of addresses
        const IOAddressList& getAddresses() const;

        /// @brief Indicates whether or not the address list has entries
        ///
        /// @return True if the address list is not empty
        bool hasAddresses() const;

        /// @brief Checks the address list for the given address
        ///
        /// @return True if the address is found in the address list
        bool containsAddress(const asiolink::IOAddress& addr) const;

    private:
        /// @brief List of relay IP addresses
        IOAddressList addresses_;
86 87
    };

88

89 90 91 92 93 94 95 96 97 98 99 100 101
    /// @brief Specifies allowed host reservation mode.
    ///
    typedef enum  {

        /// None - host reservation is disabled. No reservation types
        /// are allowed.
        HR_DISABLED,

        /// Only out-of-pool reservations is allowed. This mode
        /// allows AllocEngine to skip reservation checks when
        /// dealing with with addresses that are in pool.
        HR_OUT_OF_POOL,

102 103 104 105
        /// Only global reservations are allowed. This mode
        /// instructs AllocEngine to only look at global reservations.
        HR_GLOBAL,

106 107 108 109 110
        /// Both out-of-pool and in-pool reservations are allowed. This is the
        /// most flexible mode, where sysadmin have biggest liberty. However,
        /// there is a non-trivial performance penalty for it, as the
        /// AllocEngine code has to check whether there are reservations, even
        /// when dealing with reservations from within the dynamic pools.
111
        /// @todo - should ALL include global?
112 113 114 115 116 117
        HR_ALL
    } HRMode;

    /// Pointer to the RelayInfo structure
    typedef boost::shared_ptr<Network::RelayInfo> RelayInfoPtr;

118 119
    /// @brief Constructor.
    Network()
120
        : iface_name_(), client_class_(""), t1_(), t2_(), valid_(),
121
          host_reservation_mode_(HR_ALL), cfg_option_(new CfgOption()) {
122 123
    }

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    /// @brief Virtual destructor.
    ///
    /// Does nothing at the moment.
    virtual ~Network() { };

    /// @brief Sets local name of the interface for which this network is
    /// selected.
    ///
    /// If the interface is specified, the server will use the network
    /// associated with this local interface to allocate IP addresses and
    /// other resources to a client.
    ///
    /// @param iface_name Interface name.
    void setIface(const std::string& iface_name) {
        iface_name_ = iface_name;
    }

    /// @brief Returns name of the local interface for which this network is
    /// selected.
    ///
    /// @return Interface name as text.
    std::string getIface() const {
        return (iface_name_);
    };

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    /// @brief Sets information about relay
    ///
    /// In some situations where there are shared subnets (i.e. two different
    /// subnets are available on the same physical link), there is only one
    /// relay that handles incoming requests from clients. In such a case,
    /// the usual subnet selection criteria based on relay belonging to the
    /// subnet being selected are no longer sufficient and we need to explicitly
    /// specify a relay. One notable example of such uncommon, but valid
    /// scenario is a cable network, where there is only one CMTS (one relay),
    /// but there are 2 distinct subnets behind it: one for cable modems
    /// and another one for CPEs and other user equipment behind modems.
    /// From manageability perspective, it is essential that modems get addresses
    /// from different subnet, so users won't tinker with their modems.
    ///
    /// Setting this parameter is not needed in most deployments.
    /// This structure holds IP address only for now, but it is expected to
    /// be extended in the future.
    ///
    /// @param relay structure that contains relay information
    void setRelayInfo(const RelayInfo& relay) {
        relay_ = relay;
    }

    /// @brief Returns const reference to relay information
    ///
    /// @note The returned reference is only valid as long as the object
    /// returned it is valid.
    ///
    /// @return const reference to the relay information
    const RelayInfo& getRelayInfo() const {
        return (relay_);
    }

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
    /// @brief Adds an address to the list addresses in the network's relay info
    ///
    /// @param addr address of the relay
    /// @throw BadValue if the address is already in the list
    void addRelayAddress(const asiolink::IOAddress& addr);

    /// @brief Returns the list of relay addresses from the network's relay info
    ///
    /// @return const reference to the list of addresses
    const IOAddressList& getRelayAddresses() const;

    /// @brief Indicates if network's relay info has relay addresses
    ///
    /// @return True the relay list is not empty, false otherwise
    bool hasRelays() const;

    /// @brief Tests if the network's relay info contains the given address
    ///
    /// @param address address to search for in the relay list
    /// @return True if a relay with the given address is found, false otherwise
    bool hasRelayAddress(const asiolink::IOAddress& address) const;

204 205 206 207 208 209 210 211 212
    /// @brief Checks whether this network supports client that belongs to
    /// specified classes.
    ///
    /// This method checks whether a client that belongs to given classes can
    /// use this network. For example, if this class is reserved for client
    /// class "foo" and the client belongs to classes "foo", "bar" and "baz",
    /// it is supported. On the other hand, client belonging to classes
    /// "foobar" and "zyxxy" is not supported.
    ///
213 214
    /// @note: changed the planned white and black lists idea to a simple
    /// client class name.
215 216 217
    ///
    /// @param client_classes list of all classes the client belongs to
    /// @return true if client can be supported, false otherwise
218
    virtual bool
219 220
    clientSupported(const isc::dhcp::ClientClasses& client_classes) const;

221
    /// @brief Sets the supported class to class class_name
222
    ///
223
    /// @param class_name client class to be supported by this network
224 225
    void allowClientClass(const isc::dhcp::ClientClass& class_name);

226
    /// @brief Adds class class_name to classes required to be evaluated.
227
    ///
228 229
    /// @param class_name client class required to be evaluated
    void requireClientClass(const isc::dhcp::ClientClass& class_name);
230

231 232
    /// @brief Returns classes which are required to be evaluated
    const isc::dhcp::ClientClasses& getRequiredClasses() const;
233

234
    /// @brief returns the client class
235 236 237 238
    ///
    /// @note The returned reference is only valid as long as the object
    /// returned it is valid.
    ///
239 240 241
    /// @return client class @ref client_class_
    const isc::dhcp::ClientClass& getClientClass() const {
        return (client_class_);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
    }

    /// @brief Return valid-lifetime for addresses in that prefix
    Triplet<uint32_t> getValid() const {
        return (valid_);
    }

    /// @brief Sets new valid lifetime for a network.
    ///
    /// @param valid New valid lifetime in seconds.
    void setValid(const Triplet<uint32_t>& valid) {
        valid_ = valid;
    }

    /// @brief Returns T1 (renew timer), expressed in seconds
    Triplet<uint32_t> getT1() const {
        return (t1_);
    }

    /// @brief Sets new renew timer for a network.
    ///
    /// @param t1 New renew timer value in seconds.
    void setT1(const Triplet<uint32_t>& t1) {
        t1_ = t1;
    }

    /// @brief Returns T2 (rebind timer), expressed in seconds
    Triplet<uint32_t> getT2() const {
        return (t2_);
    }

    /// @brief Sets new rebind timer for a network.
    ///
    /// @param t2 New rebind timer value in seconds.
    void setT2(const Triplet<uint32_t>& t2) {
        t2_ = t2;
    }

    /// @brief Specifies what type of Host Reservations are supported.
    ///
    /// Host reservations may be either in-pool (they reserve an address that
    /// is in the dynamic pool) or out-of-pool (they reserve an address that is
    /// not in the dynamic pool). HR may also be completely disabled for
    /// performance reasons.
    ///
    /// @return whether in-pool host reservations are allowed.
    HRMode
    getHostReservationMode() const {
        return (host_reservation_mode_);
    }

    /// @brief Sets host reservation mode.
    ///
    /// See @ref getHostReservationMode for details.
    ///
    /// @param mode mode to be set
    void setHostReservationMode(HRMode mode) {
        host_reservation_mode_ = mode;
    }

302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
    /// @brief Returns pointer to the option data configuration for this subnet.
    CfgOptionPtr getCfgOption() {
        return (cfg_option_);
    }

    /// @brief Returns const pointer to the option data configuration for this
    /// subnet.
    ConstCfgOptionPtr getCfgOption() const {
        return (cfg_option_);
    }

    /// @brief Unparses network object.
    ///
    /// @return A pointer to unparsed network configuration.
    virtual data::ElementPtr toElement() const;

318 319 320 321 322
protected:

    /// @brief Holds interface name for which this network is selected.
    std::string iface_name_;

323 324 325 326 327 328 329 330
    /// @brief Relay information
    ///
    /// See @ref RelayInfo for detailed description.
    RelayInfo relay_;

    /// @brief Optional definition of a client class
    ///
    /// If defined, only clients belonging to that class will be allowed to use
331
    /// this particular network. The default value for this is an empty string,
332
    /// which means that any client is allowed, regardless of its class.
333
    ClientClass client_class_;
334

335
    /// @brief Required classes
336
    ///
337
    /// If the network is selected these classes will be added to the
338 339
    /// incoming packet and their evaluation will be required.
    ClientClasses required_classes_;
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354

    /// @brief a Triplet (min/default/max) holding allowed renew timer values
    Triplet<uint32_t> t1_;

    /// @brief a Triplet (min/default/max) holding allowed rebind timer values
    Triplet<uint32_t> t2_;

    /// @brief a Triplet (min/default/max) holding allowed valid lifetime values
    Triplet<uint32_t> valid_;

    /// @brief Specifies host reservation mode
    ///
    /// See @ref HRMode type for details.
    HRMode host_reservation_mode_;

355 356
    /// @brief Pointer to the option data configuration for this subnet.
    CfgOptionPtr cfg_option_;
357 358 359 360 361
};

/// @brief Pointer to the @ref Network object.
typedef boost::shared_ptr<Network> NetworkPtr;

362 363 364
/// @brief Weak pointer to the @ref Network object.
typedef boost::weak_ptr<Network> WeakNetworkPtr;

365
/// @brief Specialization of the @ref Network object for DHCPv4 case.
366 367
class Network4 : public Network {
public:
368 369 370

    /// @brief Constructor.
    Network4()
371
        : Network(), match_client_id_(true), authoritative_(false) {
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
    }

    /// @brief Returns the flag indicating if the client identifiers should
    /// be used to identify the client's lease.
    ///
    /// @return true if client identifiers should be used, false otherwise.
    bool getMatchClientId() const {
        return (match_client_id_);
    }

    /// @brief Sets the flag indicating if the client identifier should be
    /// used to identify the client's lease.
    ///
    /// @param match If this value is true, the client identifiers are not
    /// used for lease lookup.
    void setMatchClientId(const bool match) {
        match_client_id_ = match;
    }

391 392 393 394 395 396 397 398 399 400 401 402
    /// @brief Returns the flag indicating if requests for unknown IP addresses
    /// should be rejected with DHCPNAK instead of ignored.
    ///
    /// @return true if requests for unknown IP addresses should be rejected,
    /// false otherwise.
    bool getAuthoritative() const {
        return (authoritative_);
    }

    /// @brief Sets the flag indicating if requests for unknown IP addresses
    /// should be rejected with DHCPNAK instead of ignored.
    ///
403
    /// @param authoritative If this value is true, the requests for unknown IP
404 405 406 407 408
    /// addresses will be rejected with DHCPNAK messages
    void setAuthoritative(const bool authoritative) {
        authoritative_ = authoritative;
    }

409 410 411 412 413
    /// @brief Unparses network object.
    ///
    /// @return A pointer to unparsed network configuration.
    virtual data::ElementPtr toElement() const;

414 415 416 417 418 419
    /// @brief Returns binary representation of the dhcp-server-identifier option (54).
    ///
    /// @return Server identifier option as IPv4 address. Zero IPv4 address
    /// indicates that server identifier hasn't been specified.
    virtual asiolink::IOAddress getServerId() const;

420 421 422 423 424
private:

    /// @brief Should server use client identifiers for client lease
    /// lookup.
    bool match_client_id_;
425 426 427

    /// @brief Should requests for unknown IP addresses be rejected.
    bool authoritative_;
428 429
};

430
/// @brief Specialization of the @ref Network object for DHCPv6 case.
431 432
class Network6 : public Network {
public:
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447

    /// @brief Constructor.
    Network6()
        : Network(), preferred_(0), interface_id_(), rapid_commit_(false) {
    }

    /// @brief Returns preferred lifetime (in seconds)
    ///
    /// @return a triplet with preferred lifetime
    Triplet<uint32_t> getPreferred() const {
        return (preferred_);
    }

    /// @brief Sets new preferred lifetime for a network.
    ///
Francis Dupont's avatar
Francis Dupont committed
448
    /// @param preferred New preferred lifetime in seconds.
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
    void setPreferred(const Triplet<uint32_t>& preferred) {
        preferred_ = preferred;
    }

    /// @brief Returns interface-id value (if specified)
    ///
    /// @return interface-id option (if defined)
    OptionPtr getInterfaceId() const {
        return (interface_id_);
    }

    /// @brief sets interface-id option (if defined)
    ///
    /// @param ifaceid pointer to interface-id option
    void setInterfaceId(const OptionPtr& ifaceid) {
        interface_id_ = ifaceid;
    }

    /// @brief Returns boolean value indicating that the Rapid Commit option
    /// is supported or unsupported for the subnet.
    ///
    /// @return true if the Rapid Commit option is supported, false otherwise.
    bool getRapidCommit() const {
        return (rapid_commit_);
    }

    /// @brief Enables or disables Rapid Commit option support for the subnet.
    ///
    /// @param rapid_commit A boolean value indicating that the Rapid Commit
    /// option support is enabled (if true), or disabled (if false).
    void setRapidCommit(const bool rapid_commit) {
        rapid_commit_ = rapid_commit;
    };

    /// @brief Unparses network object.
    ///
    /// @return A pointer to unparsed network configuration.
    virtual data::ElementPtr toElement() const;

private:

    /// @brief a triplet with preferred lifetime (in seconds)
    Triplet<uint32_t> preferred_;

    /// @brief specifies optional interface-id
    OptionPtr interface_id_;

    /// @brief A flag indicating if Rapid Commit option is supported
    /// for this network.
    ///
    /// It's default value is false, which indicates that the Rapid
    /// Commit is disabled for the subnet.
    bool rapid_commit_;
502 503
};

504 505 506 507
} // end of namespace isc::dhcp
} // end of namespace isc

#endif // NETWORK_H