alloc_engine.h 75.5 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
        /// @brief A collection of newly allocated leases.
        Lease6Collection new_leases_;

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
        //@}

        /// @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.
399
            HintContainer hints_;
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 432 433 434
            /// @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);
        };

435
        /// @brief Container holding IA specific contexts.
436
        std::vector<IAContext> ias_;
437

438 439 440 441 442 443 444 445 446 447 448 449 450 451
        /// @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
452
        /// @brief Convenience function adding host identifier into
453 454 455 456 457 458 459 460
        /// @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));
        }
461

462 463 464 465 466
        /// @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.
467 468 469 470 471 472 473
        IAContext& currentIA() {
            if (ias_.empty()) {
                createIAContext();
            }
            return (ias_.back());
        }

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

482
        /// @brief Returns host from the most preferred subnet.
483 484 485 486
        ///
        /// @return Pointer to the host object.
        ConstHostPtr currentHost() const;

487 488 489 490
        /// @brief Returns global host reservation if there is one
        ///
        /// If the current subnet's reservation mode is global and
        /// there is a global host (i.e. reservation belonging to
491
        /// the global subnet), return it.  Otherwise return an
492 493 494 495 496 497 498 499 500 501 502 503
        /// empty pointer.
        ///
        /// @return Pointer to the host object.
        ConstHostPtr globalHost() const;

        /// @brief Determines if a global reservation exists
        ///
        /// @return true if there current subnet's reservation mode is
        /// global and there is global host containing the given
        /// lease reservation, false otherwise
        bool hasGlobalReservation(const IPv6Resrv& resv) const;

504
        /// @brief Default constructor.
505
        ClientContext6();
506 507 508

        /// @brief Constructor with parameters.
        ///
509
        /// Note that several less frequently used parameters (callout_handle,
510 511 512 513 514 515 516 517 518 519 520 521
        /// 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.
522 523 524 525 526 527
        /// @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
528
        ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid,
529 530 531 532 533
                       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());
534 535 536 537
    };

    /// @brief Allocates IPv6 leases for a given IA container
    ///
Francis Dupont's avatar
Francis Dupont committed
538
    /// This method uses the currently selected allocator to pick allocable
539 540 541 542 543
    /// 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
544
    /// This method uses host reservation if ctx.hosts_ is set. The easy way to
545
    /// set it is to call @ref findReservationDecl.
546 547
    /// The host reservation is convenient, but incurs performance penalty,
    /// so it can be tweaked on a per subnet basis. There are three possible modes:
548 549 550 551 552 553 554 555 556 557 558 559 560
    /// 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...
561
    ///    Are the reserved addresses/prefixes used by someone else?
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
    ///   -# 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).
    ///
581 582 583 584 585
    /// @param ctx client context that passes all necessary information. See
    ///        @ref ClientContext6 for details.
    ///
    /// The following fields of ClientContext6 are used:
    ///
586 587
    /// @ref ClientContext6::subnet_ subnet the allocation should
    ///        come from<br/>
588
    /// @ref ClientContext6::duid_ Client's DUID<br/>
589
    /// @ref ClientContext6::IAContext::iaid_ iaid field from the IA_NA container
590
    ///        that client sent<br/>
591 592
    /// @ref ClientContext6::IAContext::hints_ a hint that the client provided<br/>
    /// @ref ClientContext6::IAContext::type_ lease type (IA, TA or PD)<br/>
593 594
    /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates
    ///        that server takes responsibility for the forward DNS Update
595
    ///        for this lease (if true).<br/>
596 597
    /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates
    ///        that server takes responsibility for the reverse DNS Update for
598 599
    ///        this lease (if true).<br/>
    /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.<br/>
600 601
    /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false)
    ///        or just picking an address for SOLICIT that is not really
602
    ///        allocated (true)<br/>
603
    /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A
604
    ///        lease callouts will be executed if this parameter is passed.<br/>
605 606
    /// @ref ClientContext6::IAContext::old_leases_ [out] Collection to which this
    ///        function
607 608
    ///        will append old leases. Leases are stored in the same order as in
    ///        the collection of new leases, being returned. For newly allocated
609
    ///        leases (not renewed) the NULL pointers are stored in this
610
    ///        collection as old leases.<br/>
611
    /// @ref ClientContext6::hwaddr_ Hardware address (optional, may be null if
612
    ///        not available)<br/>
Francis Dupont's avatar
Francis Dupont committed
613 614
    /// @ref ClientContext6::hosts_ Host reservations. allocateLeases6 will set
    ///        this field, if appropriate reservations are found.
615
    ///
616 617
    /// @return Allocated IPv6 leases (may be empty if allocation failed)
    Lease6Collection
618
    allocateLeases6(ClientContext6& ctx);
619

620 621 622 623 624 625 626 627 628 629
    /// @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
    ///
630
    /// This method will call the lease6_renew callout.
631 632 633
    ///
    /// @param ctx Message processing context. It holds various information
    /// extracted from the client's message and required to allocate a lease.
634 635 636 637
    /// 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.
638 639
    ///
    /// @return Returns renewed lease.
640
    Lease6Collection renewLeases6(ClientContext6& ctx);
641

642
    /// @brief Reclaims expired IPv6 leases.
643 644
    ///
    /// This method retrieves a collection of expired leases and reclaims them.
645
    /// See http://oldkea.isc.org/wiki/LeaseExpirationDesign#LeasesReclamationRoutine
646 647
    /// for the details.
    ///
648 649 650 651 652
    /// 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
653
    ///   "expired-reclaimed" or removing it from the lease database,
654 655
    /// - updating statistics of assigned and reclaimed leases
    ///
Francis Dupont's avatar
Francis Dupont committed
656
    /// Note: declined leases fall under the same expiration/reclamation
657
    /// processing as normal leases. In principle, it would be more elegant
Francis Dupont's avatar
Francis Dupont committed
658
    /// to have a separate processing for declined leases reclamation. However,
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
    /// 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.
    ///
675
    /// Also, for declined leases @ref reclaimDeclinedLease6 is
676 677
    /// called. It conducts several declined specific operation (extra log
    /// entry, stats dump, hooks).
678
    ///
679
    /// @param max_leases Maximum number of leases to be reclaimed.
Francis Dupont's avatar
Francis Dupont committed
680
    /// @param timeout Maximum amount of time that the reclamation routine
681
    /// may be processing expired leases, expressed in milliseconds.
682 683 684
    /// @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).
685 686 687 688
    /// @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.
689
    void reclaimExpiredLeases6(const size_t max_leases, const uint16_t timeout,
690 691
                               const bool remove_lease,
                               const uint16_t max_unwarned_cycles = 0);
692

693 694 695 696 697 698
    /// @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);
699 700 701 702

    /// @brief Reclaims expired IPv4 leases.
    ///
    /// This method retrieves a collection of expired leases and reclaims them.
703
    /// See http://oldkea.isc.org/wiki/LeaseExpirationDesign#LeasesReclamationRoutine
704 705
    /// for the details.
    ///
706 707
    /// This method is executed periodically to act upon expired leases. This
    /// includes for each lease:
708
    /// - executing "lease_expire4" hook,
709 710
    /// - 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
711
    ///   "expired-reclaimed" or removing it from the lease database,
712 713
    /// - updating statistics of assigned and reclaimed leases
    ///
Francis Dupont's avatar
Francis Dupont committed
714
    /// Note: declined leases fall under the same expiration/reclamation
715
    /// processing as normal leases. In principle, it would be more elegant
Francis Dupont's avatar
Francis Dupont committed
716
    /// to have a separate processing for declined leases reclamation. However,
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
    /// 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.
    ///
733
    /// Also, for declined leases @ref reclaimDeclinedLease4 is
Francis Dupont's avatar
Francis Dupont committed
734
    /// called. It conducts several declined specific operation (extra log
735
    /// entry, stats dump, hooks).
736
    ///
737
    /// @param max_leases Maximum number of leases to be reclaimed.
Francis Dupont's avatar
Francis Dupont committed
738
    /// @param timeout Maximum amount of time that the reclamation routine
739
    /// may be processing expired leases, expressed in milliseconds.
740 741 742
    /// @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).
743 744 745 746
    /// @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.
747
    void reclaimExpiredLeases4(const size_t max_leases, const uint16_t timeout,
748 749
                               const bool remove_lease,
                               const uint16_t max_unwarned_cycles = 0);
750

751 752 753 754 755 756 757
    /// @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);

758

759
    /// @anchor findReservationDecl
760 761 762 763 764
    /// @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.
765
    static void findReservation(ClientContext6& ctx);
766

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
    /// @brief Attempts to find the host reservation for the client.
    ///
    /// This method attempts to find a "global" host reservation matching the
    /// client identifier.  It will return the first global reservation that
    /// matches per the configured list of host identifiers, or an empty
    /// pointer if no matches are found.
    ///
    /// @param ctx Client context holding various information about the client.
    /// @return Pointer to the reservation found, or an empty pointer.
    static ConstHostPtr findGlobalReservation(ClientContext6& ctx);

    /// @brief Creates an IPv6Resrv instance from a Lease6
    ///
    /// @param lease Reference to the Lease6
    /// @return The newly formed IPv6Resrv instance
    static IPv6Resrv makeIPv6Resrv(const Lease6& lease) {
        if (lease.type_ == Lease::TYPE_NA) {
            return (IPv6Resrv(IPv6Resrv::TYPE_NA, lease.addr_,
                              (lease.prefixlen_ ? lease.prefixlen_ : 128)));
786
        }
787 788 789 790

        return (IPv6Resrv(IPv6Resrv::TYPE_PD, lease.addr_, lease.prefixlen_));
    }

791 792
private:

793
    /// @brief creates a lease and inserts it in LeaseMgr if necessary
794 795
    ///
    /// Creates a lease based on specified parameters and tries to insert it
796
    /// into the database. That may fail in some cases, i.e. when there is another
797 798
    /// allocation process and we lost a race to a specific lease.
    ///
799 800
    /// @param ctx client context that passes all necessary information. See
    ///        @ref ClientContext6 for details.
801
    /// @param addr an address that was selected and is confirmed to be
802
    ///        available
803
    /// @param prefix_len length of the prefix (for PD only)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
804
    ///        should be 128 for other lease types
805
    /// @param [out] callout_status callout returned by the lease6_select
806 807 808 809 810 811 812
    ///
    /// 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
813 814
    ///        responsibility for the forward DNS Update for this lease
    ///        (if true).
815
    /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates that server takes
816 817
    ///        responsibility for the reverse DNS Update for this lease
    ///        (if true).
818 819 820
    /// @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
821 822
    ///        will be executed if this parameter is passed (and there are callouts
    ///        registered)
823
    /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false) or just picking
Tomek Mrugalski's avatar
Tomek Mrugalski committed
824
    ///        an address for SOLICIT that is not really allocated (true)
825
    /// @return allocated lease (or NULL in the unlikely case of the lease just
826
    ///         became unavailable)
827 828
    Lease6Ptr createLease6(ClientContext6& ctx,
                           const isc::asiolink::IOAddress& addr,
829 830
                           const uint8_t prefix_len,
                           hooks::CalloutHandle::CalloutNextStep& callout_status);
831

832 833 834 835 836 837 838 839 840 841 842 843 844
    /// @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.
    ///
845 846 847 848 849 850 851 852
    /// This method allcoates new leases,  based on host reservations.
    /// Existing leases are specified in the existing_leases parameter.
    /// It first calls @c allocateGlobalReservedLeases6 to accomodate
    /// subnets using global reservations.  If that method allocates
    /// addresses, we return, otherwise we continue and check for non-global
    /// reservations.  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.
853 854 855 856 857 858
    ///
    /// @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);

859 860 861 862 863 864 865 866 867 868 869 870 871
    /// @brief Creates new leases based on global reservations.
    ///
    /// This method is used by @allocateReservedLeases6, to allocate new leases based
    /// on global reservation if one exists and global reservations are enabled for
    /// the selected subnet. It differs from it's caller by looking only at the global
    /// reservation and therefore has no need to iterate over the selected subnet or it's
    /// siblings looking for host reservations.  Like it's caller, 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
872 873 874
    bool
    allocateGlobalReservedLeases6(ClientContext6& ctx, Lease6Collection& existing_leases);

875 876 877
    /// @brief Removes leases that are reserved for someone else.
    ///
    /// Goes through the list specified in existing_leases and removes those that
878 879
    /// are reserved by someone else or do not belong to an allowed pool.
    /// The removed leases are added to the ctx.removed_leases_ collection.
880 881 882 883 884 885 886
    ///
    /// @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);

887 888 889 890 891 892 893 894 895 896 897
    /// @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);

898 899 900 901 902 903
    /// @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
904
    /// different address B, we should assign A and release B. However,
905 906 907 908 909 910 911 912 913 914
    /// 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
915
    /// @brief Reuses expired IPv6 lease
916 917 918 919 920 921
    ///
    /// 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
922
    /// @param ctx client context that contains all details.
923
    /// @param prefix_len prefix length (for PD leases)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
924
    ///        Should be 128 for other lease types
925
    /// @param [out] callout_status callout returned by the lease6_select
926 927 928 929 930 931
    ///
    /// 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
932 933
    ///        responsibility for the forward DNS Update for this lease
    ///        (if true).
934
    /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates that server takes
935 936
    ///        responsibility for the reverse DNS Update for this lease
    ///        (if true).
937
    /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.
938 939 940 941 942
    /// @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)
943
    ///
944 945
    /// @return refreshed lease
    /// @throw BadValue if trying to recycle lease that is still valid
946 947 948 949 950
    Lease6Ptr
    reuseExpiredLease(Lease6Ptr& expired,
                      ClientContext6& ctx,
                      uint8_t prefix_len,
                      hooks::CalloutHandle::CalloutNextStep& callout_status);
951

Francis Dupont's avatar
Francis Dupont committed
952 953
    /// @brief Updates FQDN and Client's Last Transmission Time
    /// for a collection of leases.
954 955 956 957 958 959
    ///
    /// 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.
960
    ///
961 962 963 964
    /// @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.
965
    /// @param leases Collection of leases for which lease data should be
966 967
    /// updated.
    ///
968
    /// @return Collection of leases with updated data. Note that returned
969
    /// collection holds updated FQDN data even for fake allocation.
970 971
    Lease6Collection updateLeaseData(ClientContext6& ctx,
                                     const Lease6Collection& leases);
972

973 974 975 976 977 978 979 980
    /// @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);

981 982 983 984 985
    /// @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
986 987 988
    /// 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.
989 990 991 992 993 994
    ///
    /// @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);

995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
    /// @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
1016
    /// removed from the lease database (if true) upon reclamation.
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
    /// @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);
1065

1066 1067
    /// @brief Marks lease as reclaimed in the database.
    ///
Francis Dupont's avatar
Francis Dupont committed
1068
    /// This method is called internally by the leases reclamation routines.
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
    /// 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 L