alloc_engine.h 72.2 KB
Newer Older
Francis Dupont's avatar
Francis Dupont committed
1
// Copyright (C) 2012-2018 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

#ifndef ALLOC_ENGINE_H
#define ALLOC_ENGINE_H

10
#include <asiolink/io_address.h>
11
#include <dhcp/classify.h>
12
#include <dhcp/duid.h>
13
#include <dhcp/hwaddr.h>
14
#include <dhcp/pkt4.h>
15 16
#include <dhcp/pkt6.h>
#include <dhcp/option6_ia.h>
17
#include <dhcpsrv/host.h>
18 19
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/lease_mgr.h>
20
#include <hooks/callout_handle.h>
21

22
#include <boost/function.hpp>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
23
#include <boost/shared_ptr.hpp>
24 25
#include <boost/noncopyable.hpp>

26
#include <list>
27
#include <map>
28
#include <set>
29
#include <utility>
30

31 32 33 34 35 36 37 38
namespace isc {
namespace dhcp {

/// An exception that is thrown when allocation module fails (e.g. due to
/// lack of available addresses)
class AllocFailed : public isc::Exception {
public:

Tomek Mrugalski's avatar
Tomek Mrugalski committed
39 40 41 42 43 44 45
    /// @brief constructor
    ///
    /// @param file name of the file, where exception occurred
    /// @param line line of the file, where exception occurred
    /// @param what text description of the issue that caused exception
    AllocFailed(const char* file, size_t line, const char* what)
        : isc::Exception(file, line, what) {}
46 47 48 49
};

/// @brief DHCPv4 and DHCPv6 allocation engine
///
50
/// This class represents a DHCP allocation engine. It is responsible
51 52
/// for picking subnets, choosing and allocating a lease, extending,
/// renewing, releasing and possibly expiring leases.
53 54 55
///
/// @todo: Does not handle out of leases well
/// @todo: Does not handle out of allocation attempts well
56 57 58
class AllocEngine : public boost::noncopyable {
protected:

59 60 61 62
    /// @brief base class for all address/prefix allocation algorithms
    ///
    /// This is an abstract class that should not be used directly, but rather
    /// specialized implementations should be used instead.
63 64
    class Allocator {
    public:
65 66 67 68 69 70 71 72

        /// @brief picks one address out of available pools in a given subnet
        ///
        /// This method returns one address from the available pools in the
        /// specified subnet. It should not check if the address is used or
        /// reserved - AllocEngine will check that and will call pickAddress
        /// again if necessary. The number of times this method is called will
        /// increase as the number of available leases will decrease.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
73
        ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
74 75 76 77 78 79 80 81
        /// This method can also be used to pick a prefix. We should not rename
        /// it to pickLease(), because at this early stage there is no concept
        /// of a lease yet. Here it is a matter of selecting one address or
        /// prefix from the defined pool, without going into details who it is
        /// for or who uses it. I thought that pickAddress() is less confusing
        /// than pickResource(), because nobody would immediately know what the
        /// resource means in this context.
        ///
82 83
        /// Pools which are not allowed for client classes are skipped.
        ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
84
        /// @param subnet next address will be returned from pool of that subnet
85
        /// @param client_classes list of classes client belongs to
Tomek Mrugalski's avatar
Tomek Mrugalski committed
86 87 88 89
        /// @param duid Client's DUID
        /// @param hint client's hint
        ///
        /// @return the next address
90
        virtual isc::asiolink::IOAddress
91 92 93
        pickAddress(const SubnetPtr& subnet,
                    const ClientClasses& client_classes,
                    const DuidPtr& duid,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
94
                    const isc::asiolink::IOAddress& hint) = 0;
95

96 97 98
        /// @brief Default constructor.
        ///
        /// Specifies which type of leases this allocator will assign
Tomek Mrugalski's avatar
Tomek Mrugalski committed
99
        /// @param pool_type specifies pool type (addresses, temp. addr or prefixes)
100
        Allocator(Lease::Type pool_type)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
101
            :pool_type_(pool_type) {
102 103
        }

104 105 106
        /// @brief virtual destructor
        virtual ~Allocator() {
        }
107
    protected:
108

109 110
        /// @brief defines pool type allocation
        Lease::Type pool_type_;
111 112
    };

113 114 115
    /// defines a pointer to allocator
    typedef boost::shared_ptr<Allocator> AllocatorPtr;

116 117
    /// @brief Address/prefix allocator that iterates over all addresses
    ///
118
    /// This class implements an iterative algorithm that returns all addresses in
Tomek Mrugalski's avatar
Tomek Mrugalski committed
119 120 121
    /// a pool iteratively, one after another. Once the last address is reached,
    /// it starts allocating from the beginning of the first pool (i.e. it loops
    /// over).
122 123
    class IterativeAllocator : public Allocator {
    public:
124 125 126 127

        /// @brief default constructor
        ///
        /// Does not do anything
128
        /// @param type - specifies allocation type
129
        IterativeAllocator(Lease::Type type);
130 131 132 133

        /// @brief returns the next address from pools in a subnet
        ///
        /// @param subnet next address will be returned from pool of that subnet
134
        /// @param client_classes list of classes client belongs to
135 136 137
        /// @param duid Client's DUID (ignored)
        /// @param hint client's hint (ignored)
        /// @return the next address
138
        virtual isc::asiolink::IOAddress
139
            pickAddress(const SubnetPtr& subnet,
140
                        const ClientClasses& client_classes,
141 142
                        const DuidPtr& duid,
                        const isc::asiolink::IOAddress& hint);
143
    protected:
144

Tomek Mrugalski's avatar
Tomek Mrugalski committed
145
        /// @brief Returns the next prefix
146
        ///
147
        /// This method works for IPv6 addresses only. It increases the
148 149 150 151 152 153 154
        /// specified prefix by a given prefix_len. For example, 2001:db8::
        /// increased by prefix length /32 will become 2001:db9::. This method
        /// is used to iterate over IPv6 prefix pools
        ///
        /// @param prefix prefix to be increased
        /// @param prefix_len length of the prefix to be increased
        /// @return result prefix
Tomek Mrugalski's avatar
Tomek Mrugalski committed
155
        static isc::asiolink::IOAddress
156
        increasePrefix(const isc::asiolink::IOAddress& prefix,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
157
                       const uint8_t prefix_len);
158 159 160 161 162 163 164 165 166 167 168 169 170 171

        /// @brief Returns the next address or prefix
        ///
        /// This method works for IPv4 addresses, IPv6 addresses and
        /// IPv6 prefixes.
        ///
        /// @param address address or prefix to be increased
        /// @param prefix true when the previous argument is a prefix
        /// @param prefix_len length of the prefix
        /// @return result address or prefix
        static isc::asiolink::IOAddress
        increaseAddress(const isc::asiolink::IOAddress& address,
                        bool prefix, const uint8_t prefix_len);

172 173
    };

174 175
    /// @brief Address/prefix allocator that gets an address based on a hash
    ///
176
    /// @todo: This is a skeleton class for now and is missing an implementation.
177
    class HashedAllocator : public Allocator {
178 179
    public:

180
        /// @brief default constructor (does nothing)
181
        /// @param type - specifies allocation type
182
        HashedAllocator(Lease::Type type);
183 184 185 186 187 188

        /// @brief returns an address based on hash calculated from client's DUID.
        ///
        /// @todo: Implement this method
        ///
        /// @param subnet an address will be picked from pool of that subnet
189
        /// @param client_classes list of classes client belongs to
190 191 192
        /// @param duid Client's DUID
        /// @param hint a hint (last address that was picked)
        /// @return selected address
193 194 195 196 197
        virtual isc::asiolink::IOAddress
            pickAddress(const SubnetPtr& subnet,
                        const ClientClasses& client_classes,
                        const DuidPtr& duid,
                        const isc::asiolink::IOAddress& hint);
198 199 200 201
    };

    /// @brief Random allocator that picks address randomly
    ///
202
    /// @todo: This is a skeleton class for now and is missing an implementation.
203
    class RandomAllocator : public Allocator {
204
    public:
205 206

        /// @brief default constructor (does nothing)
207
        /// @param type - specifies allocation type
208
        RandomAllocator(Lease::Type type);
209

210
        /// @brief returns a random address from pool of specified subnet
211 212 213 214
        ///
        /// @todo: Implement this method
        ///
        /// @param subnet an address will be picked from pool of that subnet
215
        /// @param client_classes list of classes client belongs to
216 217 218
        /// @param duid Client's DUID (ignored)
        /// @param hint the last address that was picked (ignored)
        /// @return a random address from the pool
219
        virtual isc::asiolink::IOAddress
220 221 222
        pickAddress(const SubnetPtr& subnet,
                    const ClientClasses& client_classes,
                    const DuidPtr& duid,
223 224
                    const isc::asiolink::IOAddress& hint);
    };
225

226
public:
227 228 229 230 231 232 233 234

    /// @brief specifies allocation type
    typedef enum {
        ALLOC_ITERATIVE, // iterative - one address after another
        ALLOC_HASHED,    // hashed - client's DUID/client-id is hashed
        ALLOC_RANDOM     // random - an address is randomly selected
    } AllocType;

235
    /// @brief Constructor.
236
    ///
237 238 239 240
    /// Instantiates necessary services, required to run DHCP server.
    /// In particular, creates IfaceMgr that will be responsible for
    /// network interaction. Will instantiate lease manager, and load
    /// old or create new DUID.
241
    ///
242 243 244 245
    /// @param engine_type selects allocation algorithm
    /// @param attempts number of attempts for each lease allocation before
    ///        we give up (0 means unlimited)
    /// @param ipv6 specifies if the engine should work for IPv4 or IPv6
246
    AllocEngine(AllocType engine_type, uint64_t attempts, bool ipv6 = true);
247

248 249
    /// @brief Destructor.
    virtual ~AllocEngine() { }
250

251 252 253 254
    /// @brief Returns allocator for a given pool type
    ///
    /// @param type type of pool (V4, IA, TA or PD)
    /// @throw BadValue if allocator for a given type is missing
255
    /// @return pointer to allocator handling a given resource types
256
    AllocatorPtr getAllocator(Lease::Type type);
257

258
private:
259

260 261 262 263 264
    /// @brief a pointer to currently used allocator
    ///
    /// For IPv4, there will be only one allocator: TYPE_V4
    /// For IPv6, there will be 3 allocators: TYPE_NA, TYPE_TA, TYPE_PD
    std::map<Lease::Type, AllocatorPtr> allocators_;
265

266
    /// @brief number of attempts before we give up lease allocation (0=unlimited)
267
    uint64_t attempts_;
268

269 270 271
    // hook name indexes (used in hooks callouts)
    int hook_index_lease4_select_; ///< index for lease4_select hook
    int hook_index_lease6_select_; ///< index for lease6_select hook
272

273
public:
274

275 276 277 278 279
    /// @brief Defines a single hint (an address + prefix-length).
    ///
    /// This is an entry that represents what the client had requested,
    /// either an address or a prefix. Prefix length is 128 for regular
    /// addresses.
280
    typedef std::pair<isc::asiolink::IOAddress, uint8_t> ResourceType;
281 282

    /// @brief Container for client's hints.
283
    typedef std::vector<ResourceType> HintContainer;
284

285 286 287
    /// @brief Container holding allocated prefixes or addresses.
    typedef std::set<ResourceType> ResourceContainer;

288 289 290 291
    /// @brief A tuple holding host identifier type and value.
    typedef std::pair<Host::IdentifierType, std::vector<uint8_t> > IdentifierPair;

    /// @brief Map holding values to be used as host identifiers.
292
    typedef std::list<IdentifierPair> IdentifierList;
293

294 295 296 297 298 299 300 301
    /// @brief Context information for the DHCPv6 leases allocation.
    ///
    /// This structure holds a set of information provided by the DHCPv6
    /// server to the allocation engine. In particular, it holds the
    /// client identifying information, such as HW address or client
    /// identifier. It also holds the information about the subnet that
    /// the client is connected to.
    ///
302
    /// This structure is also used to pass some information from
303 304 305 306 307 308 309 310 311 312 313 314 315
    /// the allocation engine back to the server, i.e. the old leases
    /// which the client had before the allocation.
    ///
    /// This structure is expected to be common for a single client, even
    /// if multiple IAs are used. Some of the fields will need to be
    /// updated for every call (there's a separate call to the allocation
    /// engine for each IA option).
    ///
    /// This structure is meant to be extended in the future, if more
    /// information should be passed to the allocation engine. Note
    /// that the big advantage of using the context structure to pass
    /// information to the allocation engine methods is that adding
    /// new information doesn't modify the API of the allocation engine.
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
    struct ClientContext6 : public boost::noncopyable {

        /// @name Parameters pertaining to DHCPv6 message
        //@{

        /// @brief A pointer to the client's message
        ///
        /// This is used exclusively for hook purposes.
        Pkt6Ptr query_;

        /// @brief Indicates if this is a real or fake allocation.
        ///
        /// The real allocation is when the allocation engine is supposed
        /// to make an update in a lease database: create new lease, or
        /// update existing lease.
        bool fake_allocation_;

333 334 335
        /// @brief Subnet selected for the client by the server.
        Subnet6Ptr subnet_;

336 337 338 339 340
        /// @brief Subnet from which host reservations should be retrieved.
        ///
        /// It can be NULL, in which case @c subnet_ value is used.
        Subnet6Ptr host_subnet_;

341 342 343 344 345 346
        /// @brief Client identifier
        DuidPtr duid_;

        /// @brief Hardware/MAC address (if available, may be NULL)
        HWAddrPtr hwaddr_;

347 348 349 350
        /// @brief A list holding host identifiers extracted from a message
        /// received by the server.
        IdentifierList host_identifiers_;

351 352
        /// @brief Holds a map of hosts belonging to the client within different
        /// subnets.
353
        ///
354 355 356
        /// Multiple hosts may appear when the client belongs to a shared
        /// network.
        std::map<SubnetID, ConstHostPtr> hosts_;
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376

        /// @brief A boolean value which indicates that server takes
        ///        responsibility for the forward DNS Update for this lease
        ///        (if true).
        bool fwd_dns_update_;

        /// @brief A boolean value which indicates that server takes
        ///        responsibility for the reverse DNS Update for this lease
        ///        (if true).
        bool rev_dns_update_;

        /// @brief Hostname.
        ///
        /// The server retrieves the hostname from the Client FQDN option,
        /// Hostname option or the host reservation record for the client.
        std::string hostname_;

        /// @brief Callout handle associated with the client's message.
        hooks::CalloutHandlePtr callout_handle_;

377 378 379
        /// @brief Holds addresses and prefixes allocated for all IAs.
        ResourceContainer allocated_resources_;

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
        //@}

        /// @brief Parameters pertaining to individual IAs.
        struct IAContext {

            /// @brief iaid IAID field from IA_NA or IA_PD that is being
            /// processed
            uint32_t iaid_;

            /// @brief Lease type (IA or PD)
            Lease::Type type_;

            /// @brief client's hints
            ///
            /// There will typically be just one address, but the protocol
            /// allows more than one address or prefix for each IA container.
396
            HintContainer hints_;
397

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
            /// @brief A pointer to any old leases that the client had before
            /// update but are no longer valid after the update/allocation.
            ///
            /// This collection is typically empty, except cases when we are
            /// doing address reassignment, e.g. because there is a host
            /// reservation that gives this address to someone else, so we had
            /// to return the address, and give a new one to this client.
            Lease6Collection old_leases_;

            /// @brief A pointer to any leases that have changed FQDN
            /// information.
            ///
            /// This list may contain old versions of the leases that are still
            /// valid. In particular, it will contain a lease if the client's
            /// FQDN has changed.
            Lease6Collection changed_leases_;

            /// @brief A pointer to the IA_NA/IA_PD option to be sent in
            /// response
            Option6IAPtr ia_rsp_;

            /// @brief Default constructor.
            ///
            /// Initializes @ref type_ to @c Lease::TYPE_NA and @ref iaid_ to 0.
            IAContext();

            /// @brief Convenience method adding new hint.
            ///
            /// @param prefix Prefix or address.
            /// @param prefix_len Prefix length. Default is 128 for addresses.
            void addHint(const asiolink::IOAddress& prefix,
                         const uint8_t prefix_len = 128);
        };

432
        /// @brief Container holding IA specific contexts.
433
        std::vector<IAContext> ias_;
434

435 436 437 438 439 440 441 442 443 444 445 446 447 448
        /// @brief Convenience method adding allocated prefix or address.
        ///
        /// @param prefix Prefix or address.
        /// @param prefix_len Prefix length. Default is 128 for addresses.
        void addAllocatedResource(const asiolink::IOAddress& prefix,
                                  const uint8_t prefix_len = 128);

        /// @brief Checks if specified address or prefix was allocated.
        ///
        /// @param prefix Prefix or address.
        /// @param prefix_len Prefix length. Default is 128 for addresses.
        bool isAllocated(const asiolink::IOAddress& prefix,
                         const uint8_t prefix_len = 128) const;

Francis Dupont's avatar
Francis Dupont committed
449
        /// @brief Convenience function adding host identifier into
450 451 452 453 454 455 456 457
        /// @ref host_identifiers_ list.
        ///
        /// @param id_type Identifier type.
        /// @param identifier Identifier value.
        void addHostIdentifier(const Host::IdentifierType& id_type,
                               const std::vector<uint8_t>& identifier) {
            host_identifiers_.push_back(IdentifierPair(id_type, identifier));
        }
458

459 460 461 462 463
        /// @brief Returns IA specific context for the currently processed IA.
        ///
        /// If IA specific context doesn't exist, it is created.
        ///
        /// @return Reference to IA specific context.
464 465 466 467 468 469 470
        IAContext& currentIA() {
            if (ias_.empty()) {
                createIAContext();
            }
            return (ias_.back());
        }

471 472 473 474
        /// @brief Creates new IA context.
        ///
        /// This method should be invoked prior to processing a next IA included
        /// in the client's message.
475 476 477 478
        void createIAContext() {
            ias_.push_back(IAContext());
        };

479
        /// @brief Returns host from the most preferred subnet.
480 481 482 483
        ///
        /// @return Pointer to the host object.
        ConstHostPtr currentHost() const;

484
        /// @brief Default constructor.
485
        ClientContext6();
486 487 488

        /// @brief Constructor with parameters.
        ///
489
        /// Note that several less frequently used parameters (callout_handle,
490 491 492 493 494 495 496 497 498 499 500 501
        /// old_leases, host) fields are not set. They should be set explicitly,
        /// if needed.
        ///
        /// @param subnet subnet the allocation should come from
        /// @param duid Client's DUID
        /// @param fwd_dns A boolean value which indicates that server takes
        ///        responsibility for the forward DNS Update for this lease
        ///        (if true).
        /// @param rev_dns A boolean value which indicates that server takes
        ///        responsibility for the reverse DNS Update for this lease
        ///        (if true).
        /// @param hostname A fully qualified domain-name of the client.
502 503 504 505 506 507
        /// @param fake_allocation is this real i.e. REQUEST (false) or just
        ///        picking an address for SOLICIT that is not really allocated
        ///        (true)
        /// @param query Pointer to the DHCPv6 message being processed.
        /// @param callout_handle Callout handle associated with a client's
        ///        message
508
        ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid,
509 510 511 512 513
                       const bool fwd_dns, const bool rev_dns,
                       const std::string& hostname, const bool fake_allocation,
                       const Pkt6Ptr& query,
                       const hooks::CalloutHandlePtr& callout_handle =
                       hooks::CalloutHandlePtr());
514 515 516 517
    };

    /// @brief Allocates IPv6 leases for a given IA container
    ///
Francis Dupont's avatar
Francis Dupont committed
518
    /// This method uses the currently selected allocator to pick allocable
519 520 521 522 523
    /// resources (i.e. addresses or prefixes) from specified subnet, creates
    /// a lease (one or more, if needed) for that resources and then inserts
    /// it into LeaseMgr (if this allocation is not fake, i.e. this is not a
    /// response to SOLICIT).
    ///
Francis Dupont's avatar
Francis Dupont committed
524
    /// This method uses host reservation if ctx.hosts_ is set. The easy way to
525
    /// set it is to call @ref findReservationDecl.
526 527
    /// The host reservation is convenient, but incurs performance penalty,
    /// so it can be tweaked on a per subnet basis. There are three possible modes:
528 529 530 531 532 533 534 535 536 537 538 539 540
    /// 1. disabled (no host reservation at all). This is the most performant one
    /// as the code can skip all checks;
    /// 2. out-of-pool (only reservations that are outside
    /// of the dynamic pools are allowed. This is a compromise - it requires
    /// a sysadmin to be more careful with the reservations, but the code
    /// can skip reservation checks while managing in-pool addresses);
    /// 3. in-pool (which also allow out-of-pool; this is the most flexible
    /// mode, but it means that the allocation engine has to do reservation
    /// checks on every lease, even those dynamically assigned, which degrades
    /// performance).
    ///
    /// The logic in this method is as follows:
    /// -# Case 1. if there are no leases, and there are reservations...
541
    ///    Are the reserved addresses/prefixes used by someone else?
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
    ///   -# yes: we have a problem. We can't assign the reserved address yet,
    ///       because it is used by someone else. We can't immediately release
    ///       the lease as there is some other client that is currently using it.
    ///       We will temporarily assign a different, unreserved lease for this
    ///       client. In the mean time, the other client will hopefully get back
    ///       to us, so we could revoke his lease.
    ///   -# no: assign them => done
    /// -# Case 2. if there are leases and there are no reservations...
    ///    Are the leases reserved for someone else?
    ///    -# yes: release them, assign something else
    ///    -#  no: renew them => done
    /// -# Case 3. if there are leases and there are reservations...
    ///    Are the leases matching reservations?
    ///   -# yes: renew them => done
    ///   -#  no: release existing leases, assign new ones based on reservations
    /// -# Case 4. if there are no leases and no reservations...
    ///       assign new leases (this is the "normal" case when the reservations
    ///       are disabled).
    ///
561 562 563 564 565
    /// @param ctx client context that passes all necessary information. See
    ///        @ref ClientContext6 for details.
    ///
    /// The following fields of ClientContext6 are used:
    ///
566 567
    /// @ref ClientContext6::subnet_ subnet the allocation should
    ///        come from<br/>
568
    /// @ref ClientContext6::duid_ Client's DUID<br/>
569
    /// @ref ClientContext6::IAContext::iaid_ iaid field from the IA_NA container
570
    ///        that client sent<br/>
571 572
    /// @ref ClientContext6::IAContext::hints_ a hint that the client provided<br/>
    /// @ref ClientContext6::IAContext::type_ lease type (IA, TA or PD)<br/>
573 574
    /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates
    ///        that server takes responsibility for the forward DNS Update
575
    ///        for this lease (if true).<br/>
576 577
    /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates
    ///        that server takes responsibility for the reverse DNS Update for
578 579
    ///        this lease (if true).<br/>
    /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.<br/>
580 581
    /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false)
    ///        or just picking an address for SOLICIT that is not really
582
    ///        allocated (true)<br/>
583
    /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A
584
    ///        lease callouts will be executed if this parameter is passed.<br/>
585 586
    /// @ref ClientContext6::IAContext::old_leases_ [out] Collection to which this
    ///        function
587 588
    ///        will append old leases. Leases are stored in the same order as in
    ///        the collection of new leases, being returned. For newly allocated
589
    ///        leases (not renewed) the NULL pointers are stored in this
590
    ///        collection as old leases.<br/>
591
    /// @ref ClientContext6::hwaddr_ Hardware address (optional, may be null if
592
    ///        not available)<br/>
Francis Dupont's avatar
Francis Dupont committed
593 594
    /// @ref ClientContext6::hosts_ Host reservations. allocateLeases6 will set
    ///        this field, if appropriate reservations are found.
595
    ///
596 597
    /// @return Allocated IPv6 leases (may be empty if allocation failed)
    Lease6Collection
598
    allocateLeases6(ClientContext6& ctx);
599

600 601 602 603 604 605 606 607 608 609
    /// @brief Renews existing DHCPv6 leases for a given IA.
    ///
    /// This method updates the leases associated with a specified IA container.
    /// It will extend the leases under normal circumstances, but sometimes
    /// there may be reasons why not to do so. Such a reasons may be:
    /// - client attempts to renew an address that is not valid
    /// - client attempts to renew an address that is now reserved for someone
    ///   else (see host reservation)
    /// - client's leases does not match his reservations
    ///
610
    /// This method will call the lease6_renew callout.
611 612 613
    ///
    /// @param ctx Message processing context. It holds various information
    /// extracted from the client's message and required to allocate a lease.
614 615 616 617
    /// In particular, @ref ClientContext6::IAContext::hints_ provides list
    /// of addresses or
    /// prefixes the client had sent. @ref ClientContext6::IAContext::old_leases_
    /// will contain removed leases in this case.
618 619
    ///
    /// @return Returns renewed lease.
620
    Lease6Collection renewLeases6(ClientContext6& ctx);
621

622
    /// @brief Reclaims expired IPv6 leases.
623 624 625 626 627
    ///
    /// This method retrieves a collection of expired leases and reclaims them.
    /// See http://kea.isc.org/wiki/LeaseExpirationDesign#LeasesReclamationRoutine
    /// for the details.
    ///
628 629 630 631 632
    /// This method is executed periodically to act upon expired leases. This
    /// includes for each lease:
    /// - executing "lease_expire6" hook,
    /// - removing DNS record for a lease,
    /// - reclaiming a lease in the database, i.e. setting its state to
Francis Dupont's avatar
Francis Dupont committed
633
    ///   "expired-reclaimed" or removing it from the lease database,
634 635
    /// - updating statistics of assigned and reclaimed leases
    ///
Francis Dupont's avatar
Francis Dupont committed
636
    /// Note: declined leases fall under the same expiration/reclamation
637
    /// processing as normal leases. In principle, it would be more elegant
Francis Dupont's avatar
Francis Dupont committed
638
    /// to have a separate processing for declined leases reclamation. However,
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
    /// due to performance reasons we decided to use them together. Several
    /// aspects were taken into consideration. First, normal leases are expected
    /// to expire frequently, so in a typical deployment this method will have
    /// some leases to process. Second, declined leases are expected to be very
    /// rare event, so in most cases there won't be any declined expired leases.
    /// Third, the calls to LeaseMgr to obtain all leases of specific expiration
    /// criteria are expensive, so it is better to have one call rather than
    /// two, especially if one of those calls is expected to usually return no
    /// leases.
    ///
    /// It doesn't make sense to retain declined leases that are reclaimed,
    /// because those leases don't contain any useful information (all client
    /// identifying information was stripped when the leave was moved to the
    /// declined state). Therefore remove_leases parameter is ignored for
    /// declined leases. They are always removed.
    ///
655
    /// Also, for declined leases @ref reclaimDeclinedLease6 is
656 657
    /// called. It conducts several declined specific operation (extra log
    /// entry, stats dump, hooks).
658
    ///
659
    /// @param max_leases Maximum number of leases to be reclaimed.
Francis Dupont's avatar
Francis Dupont committed
660
    /// @param timeout Maximum amount of time that the reclamation routine
661
    /// may be processing expired leases, expressed in milliseconds.
662 663 664
    /// @param remove_lease A boolean value indicating if the lease should
    /// be removed when it is reclaimed (if true) or it should be left in the
    /// database in the "expired-reclaimed" state (if false).
665 666 667 668
    /// @param max_unwarned_cycles A number of consecutive processing cycles
    /// of expired leases, after which the system issues a warning if there
    /// are still expired leases in the database. If this value is 0, the
    /// warning is never issued.
669
    void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout,
670 671
                               const bool remove_lease,
                               const uint16_t max_unwarned_cycles = 0);
672

673 674 675 676 677 678
    /// @brief Deletes reclaimed leases expired more than specified amount
    /// of time ago.
    ///
    /// @param secs Minimum number of seconds after which the lease can be
    /// deleted.
    void deleteExpiredReclaimedLeases6(const uint32_t secs);
679 680 681 682 683 684 685

    /// @brief Reclaims expired IPv4 leases.
    ///
    /// This method retrieves a collection of expired leases and reclaims them.
    /// See http://kea.isc.org/wiki/LeaseExpirationDesign#LeasesReclamationRoutine
    /// for the details.
    ///
686 687
    /// This method is executed periodically to act upon expired leases. This
    /// includes for each lease:
688
    /// - executing "lease_expire4" hook,
689 690
    /// - removing DNS record for a lease,
    /// - reclaiming a lease in the database, i.e. setting its state to
Francis Dupont's avatar
Francis Dupont committed
691
    ///   "expired-reclaimed" or removing it from the lease database,
692 693
    /// - updating statistics of assigned and reclaimed leases
    ///
Francis Dupont's avatar
Francis Dupont committed
694
    /// Note: declined leases fall under the same expiration/reclamation
695
    /// processing as normal leases. In principle, it would be more elegant
Francis Dupont's avatar
Francis Dupont committed
696
    /// to have a separate processing for declined leases reclamation. However,
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
    /// due to performance reasons we decided to use them together. Several
    /// aspects were taken into consideration. First, normal leases are expected
    /// to expire frequently, so in a typical deployment this method will have
    /// some leases to process. Second, declined leases are expected to be very
    /// rare event, so in most cases there won't be any declined expired leases.
    /// Third, the calls to LeaseMgr to obtain all leases of specific expiration
    /// criteria are expensive, so it is better to have one call rather than
    /// two, especially if one of those calls is expected to usually return no
    /// leases.
    ///
    /// It doesn't make sense to retain declined leases that are reclaimed,
    /// because those leases don't contain any useful information (all client
    /// identifying information was stripped when the leave was moved to the
    /// declined state). Therefore remove_leases parameter is ignored for
    /// declined leases. They are always removed.
    ///
713
    /// Also, for declined leases @ref reclaimDeclinedLease4 is
Francis Dupont's avatar
Francis Dupont committed
714
    /// called. It conducts several declined specific operation (extra log
715
    /// entry, stats dump, hooks).
716
    ///
717
    /// @param max_leases Maximum number of leases to be reclaimed.
Francis Dupont's avatar
Francis Dupont committed
718
    /// @param timeout Maximum amount of time that the reclamation routine
719
    /// may be processing expired leases, expressed in milliseconds.
720 721 722
    /// @param remove_lease A boolean value indicating if the lease should
    /// be removed when it is reclaimed (if true) or it should be left in the
    /// database in the "expired-reclaimed" state (if false).
723 724 725 726
    /// @param max_unwarned_cycles A number of consecutive processing cycles
    /// of expired leases, after which the system issues a warning if there
    /// are still expired leases in the database. If this value is 0, the
    /// warning is never issued.
727
    void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout,
728 729
                               const bool remove_lease,
                               const uint16_t max_unwarned_cycles = 0);
730

731 732 733 734 735 736 737
    /// @brief Deletes reclaimed leases expired more than specified amount
    /// of time ago.
    ///
    /// @param secs Minimum number of seconds after which the lease can be
    /// deleted.
    void deleteExpiredReclaimedLeases4(const uint32_t secs);

738

739
    /// @anchor findReservationDecl
740 741 742 743 744
    /// @brief Attempts to find appropriate host reservation.
    ///
    /// Attempts to find appropriate host reservation in HostMgr. If found, it
    /// will be set in ctx.host_.
    /// @param ctx Client context that contains all necessary information.
745
    static void findReservation(ClientContext6& ctx);
746

747 748
private:

749 750 751 752 753 754 755 756 757 758 759 760 761 762
    /// @brief Type of the function used by @ref findReservationInternal to
    /// retrieve reservations by subnet identifier and host identifier.
    typedef boost::function<ConstHostPtr(const SubnetID&,
                                         const Host::IdentifierType&,
                                         const uint8_t*, const size_t)> HostGetFunc;

    /// @brief Common function for searching host reservations.
    ///
    /// This is a common function called by variants of @ref findReservation
    /// functions.
    ///
    /// @param ctx Reference to a @ref ClientContext6 or @ref ClientContext4.
    /// @param host_get Pointer to the @ref HostMgr functions to be used
    /// to retrieve reservation by subnet identifier and host identifier.
763 764
    /// @param ipv6_only Boolean value indicating if only IPv6 reservations
    /// should be retrieved.
765 766 767
    /// @tparam ContextType Either @ref ClientContext6 or @ref ClientContext4.
    template<typename ContextType>
    static void findReservationInternal(ContextType& ctx,
768 769
                                        const HostGetFunc& host_get,
                                        const bool ipv6_only = false);
770

771
    /// @brief creates a lease and inserts it in LeaseMgr if necessary
772 773
    ///
    /// Creates a lease based on specified parameters and tries to insert it
774
    /// into the database. That may fail in some cases, i.e. when there is another
775 776
    /// allocation process and we lost a race to a specific lease.
    ///
777 778
    /// @param ctx client context that passes all necessary information. See
    ///        @ref ClientContext6 for details.
779
    /// @param addr an address that was selected and is confirmed to be
780
    ///        available
781
    /// @param prefix_len length of the prefix (for PD only)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
782
    ///        should be 128 for other lease types
783 784 785 786 787 788 789
    ///
    /// The following fields of the ctx structure are used:
    /// @ref ClientContext6::subnet_ subnet the lease is allocated from
    /// @ref ClientContext6::duid_ client's DUID
    /// @ref ClientContext6::iaid_ IAID from the IA_NA container the client sent to us
    /// @ref ClientContext6::type_ lease type (IA, TA or PD)
    /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates that server takes
790 791
    ///        responsibility for the forward DNS Update for this lease
    ///        (if true).
792
    /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates that server takes
793 794
    ///        responsibility for the reverse DNS Update for this lease
    ///        (if true).
795 796 797
    /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.
    /// @ref ClientContext6::hwaddr_ Hardware address (optional, may be null for Lease6)
    /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A lease callouts
Tomek Mrugalski's avatar
Tomek Mrugalski committed
798 799
    ///        will be executed if this parameter is passed (and there are callouts
    ///        registered)
800
    /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false) or just picking
Tomek Mrugalski's avatar
Tomek Mrugalski committed
801
    ///        an address for SOLICIT that is not really allocated (true)
802
    /// @return allocated lease (or NULL in the unlikely case of the lease just
803
    ///         became unavailable)
804 805 806
    Lease6Ptr createLease6(ClientContext6& ctx,
                           const isc::asiolink::IOAddress& addr,
                           const uint8_t prefix_len);
807

808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
    /// @brief Allocates a normal, in-pool, unreserved lease from the pool.
    ///
    /// It attempts to pick a hint first, then uses allocator iteratively until
    /// an available (not used, not reserved) lease is found. In principle, it
    /// may return more than one lease, but we currently handle only one.
    /// This may change in the future.
    ///
    /// @param ctx client context that contains all details (subnet, client-id, etc.)
    /// @return collection of newly allocated leases
    Lease6Collection allocateUnreservedLeases6(ClientContext6& ctx);

    /// @brief Creates new leases based on reservations.
    ///
    /// This method allocates new leases, based on host reservation. Existing
    /// leases are specified in existing_leases parameter. A new lease is not created,
    /// if there is a lease for specified address on existing_leases list or there is
    /// a lease used by someone else.
    ///
    /// @param ctx client context that contains all details (subnet, client-id, etc.)
    /// @param existing_leases leases that are already associated with the client
    void
    allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& existing_leases);

    /// @brief Removes leases that are reserved for someone else.
    ///
    /// Goes through the list specified in existing_leases and removes those that
834 835
    /// are reserved by someone else or do not belong to an allowed pool.
    /// The removed leases are added to the ctx.removed_leases_ collection.
836 837 838 839 840 841 842
    ///
    /// @param ctx client context that contains all details (subnet, client-id, etc.)
    /// @param existing_leases [in/out] leases that should be checked
    void
    removeNonmatchingReservedLeases6(ClientContext6& ctx,
                                     Lease6Collection& existing_leases);

843 844 845 846 847 848 849 850 851 852 853
    /// @brief Removes leases that are reserved for someone else.
    ///
    /// Simplified version of removeNonmatchingReservedLeases6 to be
    /// used when host reservations are disabled.
    ///
    /// @param ctx client context that contains all details (subnet, client-id, etc.)
    /// @param existing_leases [in/out] leases that should be checked
    void
    removeNonmatchingReservedNoHostLeases6(ClientContext6& ctx,
                                           Lease6Collection& existing_leases);

854 855 856 857 858 859
    /// @brief Removed leases that are not reserved for this client
    ///
    /// This method iterates over existing_leases and will remove leases that are
    /// not reserved for this client. It will leave at least one lease on the list,
    /// if possible. The reason to run this method is that if there is a reservation
    /// for address A for client X and client X already has a lease for a
Tomek Mrugalski's avatar
Tomek Mrugalski committed
860
    /// different address B, we should assign A and release B. However,
861 862 863 864 865 866 867 868 869 870
    /// if for some reason we can't assign A, keeping B would be better than
    /// not having a lease at all. Hence we may keep B if that's the only lease
    /// left.
    ///
    /// @param ctx client context that contains all details (subnet, client-id, etc.)
    /// @param existing_leases [in/out] leases that should be checked
    void
    removeNonreservedLeases6(ClientContext6& ctx,
                             Lease6Collection& existing_leases);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
871
    /// @brief Reuses expired IPv6 lease
872 873 874 875 876 877
    ///
    /// Updates existing expired lease with new information. Lease database
    /// is updated if this is real (i.e. REQUEST, fake_allocation = false), not
    /// dummy allocation request (i.e. SOLICIT, fake_allocation = true).
    ///
    /// @param expired old, expired lease
878
    /// @param ctx client context that contains all details.
879
    /// @param prefix_len prefix length (for PD leases)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
880
    ///        Should be 128 for other lease types
881 882 883 884 885 886
    ///
    /// The following parameters are used from the ctx structure:
    /// @ref ClientContext6::subnet_ subnet the lease is allocated from
    /// @ref ClientContext6::duid_ client's DUID
    /// @ref ClientContext6::iaid_ IAID from the IA_NA container the client sent to us
    /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates that server takes
887 888
    ///        responsibility for the forward DNS Update for this lease
    ///        (if true).
889
    /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates that server takes
890 891
    ///        responsibility for the reverse DNS Update for this lease
    ///        (if true).
892
    /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.
893 894 895 896 897
    /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A
    ///        lease callouts will be executed if this parameter is passed.
    /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false)
    ///        or just picking an address for SOLICIT that is not really
    ///        allocated (true)
898
    ///
899 900
    /// @return refreshed lease
    /// @throw BadValue if trying to recycle lease that is still valid
901 902 903
    Lease6Ptr reuseExpiredLease(Lease6Ptr& expired,
                                ClientContext6& ctx,
                                uint8_t prefix_len);
904

Francis Dupont's avatar
Francis Dupont committed
905 906
    /// @brief Updates FQDN and Client's Last Transmission Time
    /// for a collection of leases.
907 908 909 910 911 912
    ///
    /// This method is executed when the server finds existing leases for a
    /// client and updates some date for these leases if needed:
    /// - client's last transmission time (cltt), if the lease to be returned
    ///   to the client should have its lifetime extended,
    /// - FQDN data, when the client has negotiated new FQDN with the server.
913
    ///
914 915 916 917
    /// @param ctx IPv6 client context (old versions of the leases that had
    ///            FQDN data changed will be stored in ctx.changed_leases_,
    ///            ctx.fwd_dns_update, ctx.rev_dns_update, ctx.hostname_
    ///            and ctx.fake_allocation_ will be used.
918
    /// @param leases Collection of leases for which lease data should be
919 920
    /// updated.
    ///
921
    /// @return Collection of leases with updated data. Note that returned
922
    /// collection holds updated FQDN data even for fake allocation.
923 924
    Lease6Collection updateLeaseData(ClientContext6& ctx,
                                     const Lease6Collection& leases);
925

926 927 928 929 930 931 932 933
    /// @brief Utility function that removes all leases with a specified address
    /// @param container A collection of Lease6 pointers
    /// @param addr address to be removed
    /// @return true if removed (false otherwise)
    static bool
    removeLeases(Lease6Collection& container,
                 const asiolink::IOAddress& addr);

934 935 936 937 938
    /// @brief Extends specified IPv6 lease
    ///
    /// This method attempts to extend the lease. It will call the lease6_renew
    /// or lease6_rebind hooks (depending on the client's message specified in
    /// ctx.query). The lease will be extended in LeaseMgr, unless the hooks
939 940 941
    /// library will set the skip flag.  The old lease is added to the
    /// the context's changed_leases_ list which allows the server to make
    /// decisions regarding DNS updates.
942 943 944 945 946 947
    ///
    /// @param ctx client context that passes all necessary information. See
    ///        @ref ClientContext6 for details.
    /// @param lease IPv6 lease to be extended.
    void extendLease6(ClientContext6& ctx, Lease6Ptr lease);

948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
    /// @brief Reclamation mode used by the variants of @c reclaimExpiredLease
    /// methods.
    ///
    /// The following operations are supported:
    /// - remove lease upon reclamation,
    /// - update lease's state upon reclamation to 'expired-reclaimed',
    /// - leave the lease in the database unchanged.
    enum DbReclaimMode {
        DB_RECLAIM_REMOVE,
        DB_RECLAIM_UPDATE,
        DB_RECLAIM_LEAVE_UNCHANGED
    };

    /// @brief Reclaim DHCPv4 or DHCPv6 lease with updating lease database.
    ///
    /// This method is called by the lease reclamation routine to reclaim the
    /// lease and update the lease database according to the value of the
    /// @c remove_lease parameter.
    ///
    /// @param lease Pointer to the DHCPv4 or DHCPv6 lease.
    /// @param remove_lease A boolean flag indicating if the lease should be
Shawn Routhier's avatar
Shawn Routhier committed
969
    /// removed from the lease database (if true) upon reclamation.
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
    /// @param callout_handle Pointer to the callout handle.
    /// @tparam LeasePtrPtr Lease type, i.e. @c Lease4Ptr or @c Lease6Ptr.
    template<typename LeasePtrType>
    void reclaimExpiredLease(const LeasePtrType& lease,
                             const bool remove_lease,
                             const hooks::CalloutHandlePtr& callout_handle);

    /// @brief Reclaim DHCPv4 or DHCPv6 lease without updating lease database.
    ///
    /// This method is called by the methods allocating leases, when the lease
    /// being allocated needs to be first reclaimed. These methods update the
    /// lease database on their own, so this reclamation method doesn't update
    /// the database on reclamation.
    ///
    /// @param lease Pointer to the DHCPv4 or DHCPv6 lease.
    /// @param callout_handle Pointer to the callout handle.
    /// @tparam LeasePtrType Lease type, i.e. @c Lease4Ptr or @c Lease6Ptr.
    template<typename LeasePtrType>
    void reclaimExpiredLease(const LeasePtrType& lease,
                             const hooks::CalloutHandlePtr& callout_handle);

    /// @brief Reclaim DHCPv6 lease.
    ///
    /// This method variant accepts the @c reclaim_mode parameter which
    /// controls if the reclaimed lease should be left in the database with
    /// no change or if it should be removed or updated.
    ///
    /// @param lease Pointer to the DHCPv6 lease.
    /// @param reclaim_mode Indicates what the method should do with the reclaimed
    /// lease in the lease database.
    /// @param callout_handle Pointer to the callout handle.
    void reclaimExpiredLease(const Lease6Ptr& lease,
                             const DbReclaimMode& reclaim_mode,
                             const hooks::CalloutHandlePtr& callout_handle);

    /// @brief Reclaim DHCPv4 lease.
    ///
    /// This method variant accepts the @c reclaim_mode parameter which
    /// controls if the reclaimed lease should be left in the database with
    /// no change or if it should be removed or updated.
    ///
    /// @param lease Pointer to the DHCPv4 lease.
    /// @param reclaim_mode Indicates what the method should do with the reclaimed
    /// lease in the lease database.
    /// @param callout_handle Pointer to the callout handle.
    void reclaimExpiredLease(const Lease4Ptr& lease,
                             const DbReclaimMode& reclaim_mode,
                             const hooks::CalloutHandlePtr& callout_handle);
1018

1019 1020
    /// @brief Marks lease as reclaimed in the database.
    ///
Francis Dupont's avatar
Francis Dupont committed
1021
    /// This method is called internally by the leases reclamation routines.
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
    /// Depending on the value of the @c remove_lease parameter this method
    /// will delete the reclaimed lease from the database or set its sate
    /// to "expired-reclaimed". In the latter case it will also clear the
    /// FQDN information.
    ///
    /// This method may throw exceptions if the operation on the lease database
    /// fails for any reason.
    ///
    /// @param lease Pointer to the lease.
    /// @param remove_lease Boolean flag indicating if the lease should be
    /// removed from the database (if true).
    /// @param lease_update_fun Pointer to the function in the @c LeaseMgr to
    /// be used to update the lease if the @c remove_lease is set to false.
    ///
    /// @tparam LeasePtrType One of the @c Lease6Ptr or @c Lease4Ptr.
    template<typename LeasePtrType>
    void reclaimLeaseInDatabase(const LeasePtrType& lease,
                                const bool remove_lease,
                                const boost::function<void (const LeasePtrType&)>&
                                lease_update_fun) const;

1043
    /// @anchor reclaimDeclinedLease4
1044
    /// @brief Conducts steps necessary for reclaiming declined IPv4 lease.
1045
    ///
Francis Dupont's avatar
Francis Dupont committed
1046
    /// These are the additional steps required when recovering a declined lease:
1047 1048
    /// - bump decline recovered stat
    /// - log lease recovery
1049
    /// - call lease4_recover hook
1050 1051
    ///
    /// @param lease Lease to be reclaimed from Declined state
1052 1053 1054
    /// @return true if it's ok to remove the lease (false = hooks status says
    ///         to keep it)
    bool reclaimDeclined(const Lease4Ptr& lease);
1055

1056
    /// @anchor reclaimDeclinedLease6
1057 1058
    /// @brief Conducts steps necessary for reclaiming declined IPv6 lease.
    ///
Francis Dupont's avatar
Francis Dupont committed
1059
    /// These are the additional steps required when recovering a declined lease:
1060 1061
    /// - bump decline recovered stat
    /// - log lease recovery
1062
    /// - call lease6_recover hook
1063 1064
    ///
    /// @param lease Lease to be reclaimed from Declined state
1065 1066 1067
    /// @return true if it's ok to remove the lease (false = hooks status says
    ///         to keep it)
    bool reclaimDeclined(const Lease6Ptr& lease);
1068

1069 1070 1071
public:

    /// @brief Context information for the DHCPv4 lease allocation.
Tomek Mrugalski's avatar