1 // Copyright (C) 2013-2021 Internet Systems Consortium, Inc. ("ISC") 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, v. 2.0. If a copy of the MPL was not distributed with this 5 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 #ifndef LEASE_H 8 #define LEASE_H 9 10 #include <asiolink/io_address.h> 11 #include <dhcp/duid.h> 12 #include <dhcp/option.h> 13 #include <dhcp/hwaddr.h> 14 #include <cc/user_context.h> 15 #include <cc/cfg_to_element.h> 16 17 namespace isc { 18 namespace dhcp { 19 20 /// @brief Unique identifier for a subnet (both v4 and v6) 21 /// 22 /// Let's copy SubnetID definition from subnet.h. We can't include it directly, 23 /// because subnet.h needs Lease::Type, so it includes lease.h 24 typedef uint32_t SubnetID; 25 26 struct Lease; 27 28 /// @brief Pointer to the lease object. 29 typedef boost::shared_ptr<Lease> LeasePtr; 30 31 /// @brief a common structure for IPv4 and IPv6 leases 32 /// 33 /// This structure holds all information that is common between IPv4 and IPv6 34 /// leases. 35 struct Lease : public isc::data::UserContext, public isc::data::CfgToElement { 36 37 /// @brief Infinity (means static, i.e. never expire) 38 static const uint32_t INFINITY_LFT = 0xffffffff; 39 40 /// @brief Print lifetime 41 /// 42 /// This converts a lifetime to a string taking into account the 43 /// infinity special value. 44 /// 45 /// @param lifetime lifetime to print 46 /// @return a string representing the finite value or "infinity" 47 static std::string lifetimeToText(uint32_t lifetime); 48 49 /// @brief Type of lease or pool 50 typedef enum { 51 TYPE_NA = 0, ///< the lease contains non-temporary IPv6 address 52 TYPE_TA = 1, ///< the lease contains temporary IPv6 address 53 TYPE_PD = 2, ///< the lease contains IPv6 prefix (for prefix delegation) 54 TYPE_V4 = 3 ///< IPv4 lease 55 } Type; 56 57 /// @brief returns text representation of a lease type 58 /// @param type lease or pool type to be converted 59 /// @return text description 60 static std::string typeToText(Type type); 61 62 /// @brief Converts type name to the actual type. 63 /// 64 /// @param text lease type as text. 65 /// @return converted type. 66 /// @throw BadValue if the text contains unsupported value. 67 static Type textToType(const std::string& text); 68 69 /// @name Common lease states constants. 70 //@{ 71 /// 72 /// @brief A lease in the default state. 73 static const uint32_t STATE_DEFAULT; 74 75 /// @brief Declined lease. 76 static const uint32_t STATE_DECLINED; 77 78 /// @brief Expired and reclaimed lease. 79 static const uint32_t STATE_EXPIRED_RECLAIMED; 80 81 /// @brief Returns name(s) of the basic lease state(s). 82 /// 83 /// @param state A numeric value holding a state information. 84 /// Some states may be composite, i.e. the single state value 85 /// maps to multiple logical states of the lease. 86 /// 87 /// @return Comma separated list of state names. 88 static std::string basicStatesToText(const uint32_t state); 89 90 /// @brief Constructor 91 /// 92 /// @param addr IP address 93 /// @param valid_lft Lifetime of the lease 94 /// @param subnet_id Subnet identification 95 /// @param cltt Client last transmission time 96 /// @param fqdn_fwd If true, forward DNS update is performed for a lease. 97 /// @param fqdn_rev If true, reverse DNS update is performed for a lease. 98 /// @param hostname FQDN of the client which gets the lease. 99 /// @param hwaddr Hardware/MAC address 100 /// 101 /// @note When creating a new Lease object, current_cltt_ matches cltt_ and 102 /// current_valid_lft_ matches valid_lft_. Any update operation that changes 103 /// cltt_ or valid_lft_ in the database must also update the current_cltt_ 104 /// and current_valid_lft_ after the database response so that additional 105 /// operations can be performed on the same object. Failing to do so will 106 /// result in the new actions to be rejected by the database. 107 Lease(const isc::asiolink::IOAddress& addr, 108 uint32_t valid_lft, SubnetID subnet_id, time_t cltt, 109 const bool fqdn_fwd, const bool fqdn_rev, 110 const std::string& hostname, 111 const HWAddrPtr& hwaddr); 112 113 /// @brief Destructor ~LeaseLease114 virtual ~Lease() {} 115 116 /// @brief IPv4 ot IPv6 address 117 /// 118 /// IPv4, IPv6 address or, in the case of a prefix delegation, the prefix. 119 isc::asiolink::IOAddress addr_; 120 121 /// @brief Valid lifetime 122 /// 123 /// Expressed as number of seconds since cltt. 124 uint32_t valid_lft_; 125 126 /// @brief Current valid lifetime 127 /// 128 /// Expressed as number of seconds since cltt before update. 129 uint32_t current_valid_lft_; 130 131 /// @brief Remaining valid lifetime 132 /// 133 /// Expressed as number of seconds since current time, also 134 /// valid lifetime - age where age is old cltt - new cltt. 135 /// The value 0 is used for the "cannot be reused" condition. 136 uint32_t reuseable_valid_lft_; 137 138 /// @brief Client last transmission time 139 /// 140 /// Specifies a timestamp giving the time when the last transmission from a 141 /// client was received. 142 time_t cltt_; 143 144 /// @brief Current client last transmission time 145 /// 146 /// Specifies a timestamp giving the time when the last transmission from a 147 /// client was received before update. 148 time_t current_cltt_; 149 150 /// @brief Subnet identifier 151 /// 152 /// Specifies the identification of the subnet to which the lease belongs. 153 SubnetID subnet_id_; 154 155 /// @brief Client hostname 156 /// 157 /// This field is in lower case and may be empty. 158 std::string hostname_; 159 160 /// @brief Forward zone updated? 161 /// 162 /// Set true if the DNS AAAA record for this lease has been updated. 163 bool fqdn_fwd_; 164 165 /// @brief Reverse zone updated? 166 /// 167 /// Set true if the DNS PTR record for this lease has been updated. 168 bool fqdn_rev_; 169 170 /// @brief Client's MAC/hardware address 171 /// 172 /// This information may not be available in certain cases. 173 HWAddrPtr hwaddr_; 174 175 /// @brief Holds the lease state(s). 176 /// 177 /// This is the field that holds the lease state(s). Typically, a 178 /// lease remains in a single states. However, it is possible to 179 /// define a value for state which indicates that the lease remains 180 /// in multiple logical states. 181 /// 182 /// The defined states are represented by the "STATE_*" constants 183 /// belonging to this class. 184 uint32_t state_; 185 186 /// @brief Convert Lease to Printable Form 187 /// 188 /// @return String form of the lease 189 virtual std::string toText() const = 0; 190 191 /// @brief returns true if the lease is expired 192 /// @return true if the lease is expired 193 bool expired() const; 194 195 /// @brief Indicates if the lease is in the "expired-reclaimed" state. 196 /// 197 /// @return true if the lease is in the "expired-reclaimed" state, false 198 /// otherwise. 199 bool stateExpiredReclaimed() const; 200 201 /// @brief Indicates if the lease is in the "declined" state. 202 /// 203 /// @return true if the lease is in the "declined" state, false otherwise. 204 bool stateDeclined() const; 205 206 /// @brief Returns true if the other lease has equal FQDN data. 207 /// 208 /// The comparison of the hostname is case insensitive. 209 /// 210 /// @param other Lease which FQDN data is to be compared with our lease. 211 /// 212 /// @return Boolean value which indicates whether FQDN data of the other 213 /// lease is equal to the FQDN data of our lease (true) or not (false). 214 bool hasIdenticalFqdn(const Lease& other) const; 215 216 /// @brief Returns raw (as vector) hardware address 217 /// 218 /// This method is needed in multi-index container as key extractor. 219 /// The const reference is only valid as long as the object that returned it. 220 /// In the unlikely case when Lease4 does not have a hardware address, 221 /// the function will return an empty vector. 222 /// 223 /// @return const reference to the hardware address 224 const std::vector<uint8_t>& getHWAddrVector() const; 225 226 /// @brief Returns lease expiration time. 227 /// 228 /// The lease expiration time is a sum of a client last transmission time 229 /// and valid lifetime. 230 int64_t getExpirationTime() const; 231 232 /// @brief Sets lease to DECLINED state. 233 /// 234 /// All client identifying parameters will be stripped off (HWaddr, 235 /// client_id, hostname), cltt will be set to current time and 236 /// valid_lft to parameter specified as probation period. 237 /// Note that This method only sets fields in the structure. 238 /// It is caller's responsibility to clean up DDNS, bump up stats, 239 /// log, call hooks ets. 240 /// 241 /// @param probation_period lease lifetime will be set to this value 242 virtual void decline(uint32_t probation_period) = 0; 243 244 /// Avoid a clang spurious error 245 using isc::data::CfgToElement::toElement; 246 247 /// Sync lease current expiration time with new value from another lease, 248 /// so that additional operations can be done without performing extra read 249 /// from the database. 250 /// 251 /// @note The lease current expiration time is represented by the 252 /// @ref current_cltt_ and @ref current_valid_lft_ and the new value by 253 /// @ref cltt_ and @ref valid_lft_ 254 /// 255 /// @param from The lease with latest value of expiration time. 256 /// @param [out] to The lease that needs to be updated. 257 static void syncCurrentExpirationTime(const Lease& from, Lease& to); 258 259 /// Update lease current expiration time with new value, 260 /// so that additional operations can be done without performing extra read 261 /// from the database. 262 /// 263 /// @note The lease current expiration time is represented by the 264 /// @ref current_cltt_ and @ref current_valid_lft_ and the new value by 265 /// @ref cltt_ and @ref valid_lft_ 266 void updateCurrentExpirationTime(); 267 268 protected: 269 270 /// @brief Sets common (for v4 and v6) properties of the lease object. 271 /// 272 /// This method is called by the @c fromElement methods of the @c Lease 273 /// class derivations. 274 /// 275 /// @param [out] lease pointer to the lease object for which common 276 /// properties should be set. 277 /// @param element pointer to the data element object to be parsed. 278 static void fromElementCommon(const LeasePtr& lease, 279 const data::ConstElementPtr& element); 280 281 }; 282 283 struct Lease4; 284 285 /// @brief Pointer to a Lease4 structure. 286 typedef boost::shared_ptr<Lease4> Lease4Ptr; 287 288 /// @brief Structure that holds a lease for IPv4 address 289 /// 290 /// For performance reasons it is a simple structure, not a class. If we chose 291 /// make it a class, all fields would have to made private and getters/setters 292 /// would be required. As this is a critical part of the code that will be used 293 /// extensively, direct access is warranted. 294 struct Lease4 : public Lease { 295 296 /// @brief Client identifier 297 /// 298 /// @todo Should this be a pointer to a client ID or the ID itself? 299 /// Compare with the DUID in the Lease6 structure. 300 ClientIdPtr client_id_; 301 302 /// @brief Constructor 303 /// 304 /// @param addr IPv4 address. 305 /// @param hwaddr A pointer to HWAddr structure 306 /// @param clientid Client identification buffer 307 /// @param clientid_len Length of client identification buffer 308 /// @param valid_lft Lifetime of the lease 309 /// @param cltt Client last transmission time 310 /// @param subnet_id Subnet identification 311 /// @param fqdn_fwd If true, forward DNS update is performed for a lease. 312 /// @param fqdn_rev If true, reverse DNS update is performed for a lease. 313 /// @param hostname FQDN of the client which gets the lease. 314 Lease4(const isc::asiolink::IOAddress& addr, const HWAddrPtr& hwaddr, 315 const uint8_t* clientid, size_t clientid_len, uint32_t valid_lft, 316 time_t cltt, uint32_t subnet_id, 317 const bool fqdn_fwd = false, const bool fqdn_rev = false, 318 const std::string& hostname = "") LeaseLease4319 : Lease(addr, valid_lft, subnet_id, cltt, fqdn_fwd, fqdn_rev, 320 hostname, hwaddr) { 321 if (clientid_len) { 322 client_id_.reset(new ClientId(clientid, clientid_len)); 323 } 324 } 325 326 /// @brief Constructor. 327 /// 328 /// @param address IPv4 address. 329 /// @param hw_address Pointer to client's HW address. 330 /// @param client_id pointer to the client id structure. 331 /// @param valid_lifetime Valid lifetime value. 332 /// @param cltt Timestamp when the lease is acquired, renewed. 333 /// @param subnet_id Subnet identifier. 334 /// @param fqdn_fwd Forward DNS update performed. 335 /// @param fqdn_rev Reverse DNS update performed. 336 /// @param hostname Client's name for the DNS update.. 337 Lease4(const isc::asiolink::IOAddress& address, 338 const HWAddrPtr& hw_address, 339 const ClientIdPtr& client_id, 340 const uint32_t valid_lifetime, 341 const time_t cltt, 342 const SubnetID subnet_id, 343 const bool fqdn_fwd = false, 344 const bool fqdn_rev = false, 345 const std::string& hostname = ""); 346 347 348 /// @brief Default constructor 349 /// 350 /// Initialize fields that don't have a default constructor. Lease4Lease4351 Lease4() : Lease(0, 0, 0, 0, false, false, "", HWAddrPtr()) 352 { 353 } 354 355 /// @brief Copy constructor 356 /// 357 /// @param other the @c Lease4 object to be copied. 358 Lease4(const Lease4& other); 359 360 /// @brief Returns name of the lease states specific to DHCPv4. 361 /// 362 /// @todo Currently it simply returns common states for DHCPv4 and DHCPv6. 363 /// This method will have to be extended to handle DHCPv4 specific states 364 /// when they are defined. 365 /// 366 /// @param state Numeric value holding lease states. 367 /// @return Comma separated list of lease state names. 368 static std::string statesToText(const uint32_t state); 369 370 /// @brief Returns a client identifier. 371 /// 372 /// @warning Since the function returns the reference to a vector (not a 373 /// copy), the returned object should be used with caution because it will 374 /// remain valid only for the period of time when an object which returned 375 /// it exists. 376 /// 377 /// @return A reference to a vector holding client identifier, 378 /// or an empty vector if client identifier is NULL. 379 const std::vector<uint8_t>& getClientIdVector() const; 380 381 /// @brief Check if the lease belongs to the client with the given 382 /// identifiers. 383 /// 384 /// This method checks if the lease belongs to the client using the 385 /// specified HW address and/or client identifier. Note that any of the 386 /// pointers passed to this method may be set to null, in which case 387 /// they are treated as unspecified and are not used for matching the 388 /// client with the lease. 389 /// 390 /// According to the DHCPv4 specifications, the client identifier takes 391 /// precedence over the HW address when identifying the lease for the 392 /// client on the server side. In particular, the RFC4361 introduces the 393 /// use of DUID for DHCPv4 which should be a stable identifier for the 394 /// client. The use of stable identifier allows for the correlation of the 395 /// DHCPv4 and DHCPv6 clients in the dual stack networks. It also allows 396 /// for allocating the same lease to the client which hardware (and thus 397 /// MAC address) has changed. 398 /// 399 /// By default, Kea respects the precedence of the client identifier over 400 /// MAC address and when this method finds the match of the client 401 /// identifier with the client identifier stored in the lease, it will 402 /// treat the lease as the lease of this client, even when the HW 403 /// address doesn't match. 404 /// 405 /// The HW address is used for matching the client with the lease only 406 /// when the lease is not associated with any client identifier (client 407 /// identifier for the lease is null) or when the client identifier 408 /// parameter passed to this method is null. This facilitates the following 409 /// cases: 410 /// - client didn't generate client identifier and is only using the chaddr 411 /// field to identify itself. 412 /// - server's administrator configured the server to NOT match client 413 /// identifiers, the client obtained the new lease, and the administrator 414 /// reconfigured the server to match the client identifiers. The client 415 /// is trying to renew its lease and both the client identifier and HW 416 /// address is used for matching the lease which doesn't have the record 417 /// of the client identifier. 418 /// - client obtained the lease using the HW address and client identifier, 419 /// the server's administrator configured the server to NOT match the 420 /// client identifiers, and the client returns to renew the lease. This 421 /// time, the lease has a record of both client identifier and the HW 422 /// address but only the HW address is used for matching the client to 423 /// the lease. 424 /// 425 /// Note that the typical case when the server's administrator may want to 426 /// disable matching the client identifier passed in the client's message 427 /// is when the client is performing multi-stage boot. In such case, the 428 /// client identifiers may change on various stages of the boot, but the 429 /// HW address will remain stable. The server's administrator prefers 430 /// using the HW address for client identification in this case. 431 /// 432 /// It may also be useful to disable matching client identifiers to 433 /// mitigate the problem of broken client implementations which generate 434 /// new client identifiers every time they connect to the network. 435 /// 436 /// @param hw_address Pointer to the HW address of the client. 437 /// @param client_id Pointer to the client identifier structure. 438 /// 439 /// @return true if the lease belongs to the client using the specified 440 /// hardware address and/or client identifier. 441 bool belongsToClient(const HWAddrPtr& hw_address, 442 const ClientIdPtr& client_id) const; 443 444 /// @brief Assignment operator. 445 /// 446 /// @param other the @c Lease4 object to be assigned. 447 Lease4& operator=(const Lease4& other); 448 449 /// @brief Compare two leases for equality 450 /// 451 /// @param other lease6 object with which to compare 452 bool operator==(const Lease4& other) const; 453 454 /// @brief Compare two leases for inequality 455 /// 456 /// @param other lease6 object with which to compare 457 bool operator!=(const Lease4& other) const { 458 return (!operator==(other)); 459 } 460 461 /// @brief Convert lease to printable form 462 /// 463 /// @return Textual representation of lease data 464 virtual std::string toText() const; 465 466 /// @brief Sets IPv4 lease to declined state. 467 /// 468 /// See @ref Lease::decline for detailed description. 469 /// 470 /// @param probation_period valid lifetime will be set to this value 471 void decline(uint32_t probation_period); 472 473 /// @brief Return the JSON representation of a lease 474 virtual isc::data::ElementPtr toElement() const; 475 476 /// @brief Returns pointer to the IPv4 lease created from JSON 477 /// representation. 478 /// 479 /// @param element pointer to the data element object to be parsed. 480 /// @return Pointer to the created lease. 481 static Lease4Ptr fromElement(const data::ConstElementPtr& element); 482 483 /// @todo: Add DHCPv4 failover related fields here 484 }; 485 486 /// @brief A collection of IPv4 leases. 487 typedef std::vector<Lease4Ptr> Lease4Collection; 488 489 /// @brief A shared pointer to the collection of IPv4 leases. 490 typedef boost::shared_ptr<Lease4Collection> Lease4CollectionPtr; 491 492 struct Lease6; 493 494 /// @brief Pointer to a Lease6 structure. 495 typedef boost::shared_ptr<Lease6> Lease6Ptr; 496 497 /// @brief Structure that holds a lease for IPv6 address and/or prefix 498 /// 499 /// For performance reasons it is a simple structure, not a class. If we chose 500 /// make it a class, all fields would have to made private and getters/setters 501 /// would be required. As this is a critical part of the code that will be used 502 /// extensively, direct access is warranted. 503 struct Lease6 : public Lease { 504 505 /// @brief Lease type 506 /// 507 /// One of normal address, temporary address, or prefix. 508 Lease::Type type_; 509 510 /// @brief IPv6 prefix length 511 /// 512 /// This is used only for prefix delegations and is ignored otherwise. 513 uint8_t prefixlen_; 514 515 /// @brief Identity Association Identifier (IAID) 516 /// 517 /// DHCPv6 stores all addresses and prefixes in IA containers (IA_NA, 518 /// IA_TA, IA_PD). All containers may appear more than once in a message. 519 /// To differentiate between them, the IAID field is present 520 uint32_t iaid_; 521 522 /// @brief Client identifier 523 DuidPtr duid_; 524 525 /// @brief Preferred lifetime 526 /// 527 /// This parameter specifies the preferred lifetime since the lease was 528 /// assigned or renewed (cltt), expressed in seconds. 529 uint32_t preferred_lft_; 530 531 /// @brief Remaining preferred lifetime 532 /// 533 /// Expressed as number of seconds since current time, also 534 /// preferred lifetime - age where age is old cltt - new cltt. 535 /// This parameter is used only when reuseable_valid_lft_ is not zero, 536 /// i.e. when the lease can be reused. 537 uint32_t reuseable_preferred_lft_; 538 539 /// @todo: Add DHCPv6 failover related fields here 540 541 /// @brief Constructor 542 /// @param type Lease type. 543 /// @param addr Assigned address. 544 /// @param duid A pointer to an object representing DUID. 545 /// @param iaid IAID. 546 /// @param preferred Preferred lifetime. 547 /// @param valid Valid lifetime. 548 /// @param subnet_id A Subnet identifier. 549 /// @param hwaddr hardware/MAC address (optional) 550 /// @param prefixlen An address prefix length (optional, defaults to 128) 551 Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr, DuidPtr duid, 552 uint32_t iaid, uint32_t preferred, uint32_t valid, 553 SubnetID subnet_id, const HWAddrPtr& hwaddr = HWAddrPtr(), 554 uint8_t prefixlen = 128); 555 556 /// @brief Constructor, including FQDN data. 557 /// 558 /// @param type Lease type. 559 /// @param addr Assigned address. 560 /// @param duid A pointer to an object representing DUID. 561 /// @param iaid IAID. 562 /// @param preferred Preferred lifetime. 563 /// @param valid Valid lifetime. 564 /// @param subnet_id A Subnet identifier. 565 /// @param fqdn_fwd If true, forward DNS update is performed for a lease. 566 /// @param fqdn_rev If true, reverse DNS update is performed for a lease. 567 /// @param hostname FQDN of the client which gets the lease. 568 /// @param hwaddr hardware address (MAC), may be NULL 569 /// @param prefixlen An address prefix length (optional, defaults to 128) 570 Lease6(Lease::Type type, const isc::asiolink::IOAddress& addr, DuidPtr duid, 571 uint32_t iaid, uint32_t preferred, uint32_t valid, 572 SubnetID subnet_id, const bool fqdn_fwd, 573 const bool fqdn_rev, const std::string& hostname, 574 const HWAddrPtr& hwaddr = HWAddrPtr(), uint8_t prefixlen = 128); 575 576 /// @brief Constructor 577 /// 578 /// Initialize fields that don't have a default constructor. 579 Lease6(); 580 581 /// @brief Returns name of the lease states specific to DHCPv6. 582 /// 583 /// @todo Currently it simply returns common states for DHCPv4 and DHCPv6. 584 /// This method will have to be extended to handle DHCPv6 specific states 585 /// when they are defined. 586 /// 587 /// @param state Numeric value holding lease states. 588 /// @return Comma separated list of lease state names. 589 static std::string statesToText(const uint32_t state); 590 591 /// @brief Returns a reference to a vector representing a DUID. 592 /// 593 /// @warning Since the function returns the reference to a vector (not a 594 /// copy), the returned object should be used with caution because it will 595 /// remain valid only for the period of time when an object which returned 596 /// it exists. 597 /// 598 /// @return A reference to a vector holding a DUID. 599 const std::vector<uint8_t>& getDuidVector() const; 600 601 /// @brief Sets IPv6 lease to declined state. 602 /// 603 /// See @ref Lease::decline for detailed description. 604 /// 605 /// @param probation_period valid lifetime will be set to this value 606 void decline(uint32_t probation_period); 607 608 /// @brief Compare two leases for equality 609 /// 610 /// @param other lease6 object with which to compare 611 bool operator==(const Lease6& other) const; 612 613 /// @brief Compare two leases for inequality 614 /// 615 /// @param other lease6 object with which to compare 616 bool operator!=(const Lease6& other) const { 617 return (!operator==(other)); 618 } 619 620 /// @brief Convert Lease to Printable Form 621 /// 622 /// @return String form of the lease 623 virtual std::string toText() const; 624 625 /// @brief Return the JSON representation of a lease 626 virtual isc::data::ElementPtr toElement() const; 627 628 /// @brief Returns pointer to the IPv6 lease created from JSON 629 /// representation. 630 /// 631 /// @param element pointer to the data element object to be parsed. 632 /// @return Pointer to the created lease. 633 static Lease6Ptr fromElement(const data::ConstElementPtr& element); 634 }; 635 636 /// @brief Pointer to a const Lease6 structure. 637 typedef boost::shared_ptr<const Lease6> ConstLease6Ptr; 638 639 /// @brief A collection of IPv6 leases. 640 typedef std::vector<Lease6Ptr> Lease6Collection; 641 642 643 /// @brief A shared pointer to the collection of IPv6 leases. 644 typedef boost::shared_ptr<Lease6Collection> Lease6CollectionPtr; 645 646 /// @brief Stream output operator. 647 /// 648 /// Dumps the output of Lease::toText to the given stream. 649 /// @param os output stream to which the output is 650 /// @param lease reference to Lease object to dump 651 /// @return a reference to the output stream parameter 652 std::ostream& 653 operator<<(std::ostream& os, const Lease& lease); 654 655 }; // end of isc::dhcp namespace 656 }; // end of isc namespace 657 658 #endif // LEASE_H 659