1 // Copyright (C) 2012-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 SUBNET_H 8 #define SUBNET_H 9 10 #include <asiolink/io_address.h> 11 #include <cc/data.h> 12 #include <cc/user_context.h> 13 #include <dhcp/option_space_container.h> 14 #include <dhcpsrv/lease.h> 15 #include <dhcpsrv/network.h> 16 #include <dhcpsrv/pool.h> 17 #include <dhcpsrv/subnet_id.h> 18 #include <dhcpsrv/triplet.h> 19 #include <boost/multi_index/mem_fun.hpp> 20 #include <boost/multi_index/indexed_by.hpp> 21 #include <boost/multi_index/ordered_index.hpp> 22 #include <boost/multi_index/random_access_index.hpp> 23 #include <boost/multi_index_container.hpp> 24 #include <boost/date_time/posix_time/posix_time.hpp> 25 #include <boost/pointer_cast.hpp> 26 #include <boost/scoped_ptr.hpp> 27 #include <boost/shared_ptr.hpp> 28 #include <cstdint> 29 #include <map> 30 #include <mutex> 31 #include <utility> 32 33 namespace isc { 34 namespace dhcp { 35 36 class Subnet : public virtual Network { 37 public: 38 39 /// @brief checks if specified address is in range. 40 /// 41 /// @param addr this address will be checked if it is included in a specific 42 /// range 43 /// @return true if address is in range, false otherwise 44 bool inRange(const isc::asiolink::IOAddress& addr) const; 45 46 /// @brief checks if the specified address is in pools. 47 /// 48 /// Note the difference between inRange() and inPool() for addresses 49 /// (i.e. *not* prefixes). For a given subnet (e.g. 2001::/64) there 50 /// may be one or more pools defined that may or may not cover 51 /// entire subnet, e.g. pool 2001::1-2001::10). inPool() returning 52 /// true implies inRange(), but the reverse implication is not 53 /// always true. For the given example, 2001::1234:abcd would return 54 /// true for inRange(), but false for inPool() check. 55 /// 56 /// @param type type of pools to iterate over 57 /// @param addr this address will be checked if it belongs to any pools in 58 /// that subnet 59 /// @return true if the address is in any of the pools 60 bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const; 61 62 /// @brief checks if the specified address is in allowed pools. 63 /// 64 /// This takes also into account client classes 65 /// 66 /// @param type type of pools to iterate over 67 /// @param addr this address will be checked if it belongs to any pools in 68 /// that subnet 69 /// @param client_classes client class list which must be allowed 70 /// @return true if the address is in any of the allowed pools 71 bool inPool(Lease::Type type, 72 const isc::asiolink::IOAddress& addr, 73 const ClientClasses& client_classes) const; 74 75 /// @brief returns the last address that was tried from this subnet. 76 /// 77 /// This method returns the last address that was attempted to be allocated 78 /// from this subnet. This is used as helper information for the next 79 /// iteration of the allocation algorithm. 80 /// 81 /// @note: this routine is Kea thread safe. 82 /// 83 /// @todo: Define map<SubnetID, ClientClass, IOAddress> somewhere in the 84 /// AllocEngine::IterativeAllocator and keep the data there 85 /// 86 /// @param type lease type to be returned 87 /// @return address/prefix that was last tried from this subnet 88 isc::asiolink::IOAddress getLastAllocated(Lease::Type type) const; 89 90 /// @brief Returns the timestamp when the @c setLastAllocated function 91 /// was called. 92 /// 93 /// @note: this routine is Kea thread safe. 94 /// 95 /// @param lease_type Lease type for which last allocation timestamp should 96 /// be returned. 97 /// 98 /// @return Time when a lease of a specified type has been allocated from 99 /// this subnet. The negative infinity time is returned if a lease type is 100 /// not recognized (which is unlikely). 101 boost::posix_time::ptime 102 getLastAllocatedTime(const Lease::Type& lease_type) const; 103 104 /// @brief sets the last address that was tried from this subnet. 105 /// 106 /// This method sets the last address that was attempted to be allocated 107 /// from this subnet. This is used as helper information for the next 108 /// iteration of the allocation algorithm. 109 /// 110 /// @note: this routine is Kea thread safe. 111 /// 112 /// @todo: Define map<SubnetID, ClientClass, IOAddress> somewhere in the 113 /// AllocEngine::IterativeAllocator and keep the data there 114 /// @param addr address/prefix to that was tried last 115 /// @param type lease type to be set 116 void setLastAllocated(Lease::Type type, 117 const isc::asiolink::IOAddress& addr); 118 119 /// @brief Returns unique ID for that subnet. 120 /// 121 /// @return unique ID for that subnet getID()122 SubnetID getID() const { return (id_); } 123 124 /// @brief Returns subnet parameters (prefix and prefix length). 125 /// 126 /// @return (prefix, prefix length) pair get()127 std::pair<isc::asiolink::IOAddress, uint8_t> get() const { 128 return (std::make_pair(prefix_, prefix_len_)); 129 } 130 131 /// @brief Adds a new pool for the subnet. 132 /// 133 /// This method checks that the address range represented by the pool 134 /// matches the subnet prefix, if the pool type is different than 135 /// IA_PD. The prefixes from the IA_PD pools don't need to match the 136 /// prefix from the subnet from which they are handed out to the 137 /// requesting router because the requesting router may use the 138 /// delegated prefixes in different networks (using different subnets). 139 /// 140 /// A DHCPv4 pool being added must not overlap with any existing DHCPv4 141 /// pool. A DHCPv6 pool being added must not overlap with any existing 142 /// DHCPv6 pool. 143 /// 144 /// Pools held within a subnet are sorted by first pool address/prefix 145 /// from the lowest to the highest. 146 /// 147 /// @param pool pool to be added 148 /// 149 /// @throw isc::BadValue if the pool type is invalid, the pool 150 /// is not an IA_PD pool and the address range of this pool does not 151 /// match the subnet prefix, or the pool overlaps with an existing pool 152 /// within the subnet. 153 void addPool(const PoolPtr& pool); 154 155 /// @brief Deletes all pools of specified type. 156 /// 157 /// This method is used for testing purposes only 158 /// 159 /// @param type type of pools to be deleted 160 void delPools(Lease::Type type); 161 162 /// @brief Returns a pool that specified address belongs to. 163 /// 164 /// This method uses binary search to retrieve the pool. Thus, the number 165 /// of comparisons performed by this method is logarithmic in the number 166 /// of pools belonging to a subnet. 167 /// 168 /// If there is no pool that the address belongs to (hint is invalid), other 169 /// pool of specified type will be returned. 170 /// 171 /// With anypool set to true, this is means give me a pool, preferably 172 /// the one that addr belongs to. With anypool set to false, it means 173 /// give me a pool that addr belongs to (or NULL if here is no such pool) 174 /// 175 /// @param type pool type that the pool is looked for 176 /// @param addr address that the returned pool should cover (optional) 177 /// @param anypool other pool may be returned as well, not only the one 178 /// that addr belongs to 179 /// @return found pool (or NULL) 180 const PoolPtr getPool(Lease::Type type, const isc::asiolink::IOAddress& addr, 181 bool anypool = true) const; 182 183 /// @brief Returns a pool that specified address belongs to with classes. 184 /// 185 /// Variant using only pools allowing given classes. 186 /// 187 /// @param type pool type that the pool is looked for 188 /// @param client_classes client class list which must be allowed 189 /// @param addr address that the returned pool should cover (optional) 190 const PoolPtr getPool(Lease::Type type, 191 const ClientClasses& client_classes, 192 const isc::asiolink::IOAddress& addr) const; 193 194 /// @brief Returns a pool without any address specified. 195 /// 196 /// @param type pool type that the pool is looked for 197 /// @return returns one of the pools defined getAnyPool(Lease::Type type)198 PoolPtr getAnyPool(Lease::Type type) { 199 return (getPool(type, default_pool())); 200 } 201 202 /// @brief Returns the default address that will be used for pool selection. 203 /// 204 /// It must be implemented in derived classes (should return :: for Subnet6 205 /// and 0.0.0.0 for Subnet4). 206 virtual isc::asiolink::IOAddress default_pool() const = 0; 207 208 /// @brief Returns all pools (const variant). 209 /// 210 /// The reference is only valid as long as the object that returned it. 211 /// 212 /// @param type lease type to be set 213 /// @return a collection of all pools 214 const PoolCollection& getPools(Lease::Type type) const; 215 216 /// @brief Returns the number of possible leases for specified lease type. 217 /// 218 /// @param type type of the lease 219 uint64_t getPoolCapacity(Lease::Type type) const; 220 221 /// @brief Returns the number of possible leases for specified lease type 222 /// allowed for a client which belongs to classes. 223 /// 224 /// @param type type of the lease 225 /// @param client_classes list of classes the client belongs to 226 /// @return number of leases matching lease type and classes 227 uint64_t getPoolCapacity(Lease::Type type, 228 const ClientClasses& client_classes) const; 229 230 /// @brief Returns textual representation of the subnet (e.g. 231 /// "2001:db8::/64"). 232 /// 233 /// @return textual representation 234 virtual std::string toText() const; 235 236 /// @brief Resets subnet-id counter to its initial value (1). 237 /// 238 /// This should be called during reconfiguration, before any new 239 /// subnet objects are created. It will ensure that the subnet_id will 240 /// be consistent between reconfigures. resetSubnetID()241 static void resetSubnetID() { 242 static_id_ = 1; 243 } 244 245 /// @brief Retrieves pointer to a shared network associated with a subnet. 246 /// 247 /// By implementing it as a template function we overcome a need to 248 /// include shared_network.h header file to specify return type explicitly. 249 /// The header can't be included because it would cause circular dependency 250 /// between subnet.h and shared_network.h. 251 /// 252 /// This method uses an argument to hold a return value to allow the compiler 253 /// to infer the return type without a need to call this function with an 254 /// explicit return type as template argument. 255 /// 256 /// @param [out] shared_network Pointer to the shared network where returned 257 /// value should be assigned. 258 /// 259 /// @tparam Type of the shared network, i.e. @ref SharedNetwork4 or a 260 /// @ref SharedNetwork6. 261 template<typename SharedNetworkPtrType> getSharedNetwork(SharedNetworkPtrType & shared_network)262 void getSharedNetwork(SharedNetworkPtrType& shared_network) const { 263 shared_network = boost::dynamic_pointer_cast< 264 typename SharedNetworkPtrType::element_type>(parent_network_.lock()); 265 } 266 267 /// @brief Assigns shared network to a subnet. 268 /// 269 /// This method replaces any shared network associated with a subnet with 270 /// a new shared network. 271 /// 272 /// @param shared_network Pointer to a new shared network to be associated 273 /// with the subnet. setSharedNetwork(const NetworkPtr & shared_network)274 void setSharedNetwork(const NetworkPtr& shared_network) { 275 parent_network_ = shared_network; 276 } 277 278 /// @brief Returns shared network name. 279 /// 280 /// @return shared network name getSharedNetworkName()281 std::string getSharedNetworkName() const { 282 return (shared_network_name_); 283 } 284 285 /// @brief Sets new shared network name. 286 /// 287 /// In certain cases the subnet must be associated with the shared network 288 /// but the shared network object is not available. In particular, subnets 289 /// are returned from the configuration database with only names of the 290 /// shared networks. The actual shared networks must be fetched from the 291 /// database using a separate query. In order to not loose associations 292 /// of subnets with shared networks, the configuration backends will use 293 /// this method to store the shared network names. The servers will later 294 /// use those names to associate subnets with shared network instances. 295 /// 296 /// @param shared_network_name New shared network name. setSharedNetworkName(const std::string & shared_network_name)297 void setSharedNetworkName(const std::string& shared_network_name) { 298 shared_network_name_ = shared_network_name; 299 } 300 301 /// @brief Returns all pools (non-const variant). 302 /// 303 /// The reference is only valid as long as the object that returned it. 304 /// 305 /// @param type lease type to be set 306 /// @return a collection of all pools 307 PoolCollection& getPoolsWritable(Lease::Type type); 308 309 protected: 310 311 /// @brief Protected constructor. 312 // 313 /// By making the constructor protected, we make sure that no one will 314 /// ever instantiate that class. Subnet4 and Subnet6 should be used instead. 315 /// 316 /// This constructor assigns a new subnet-id (see @ref generateNextID). 317 /// This subnet-id has unique value that is strictly monotonously increasing 318 /// for each subnet, until it is explicitly reset back to 1 during 319 /// reconfiguration process. 320 /// 321 /// @param prefix subnet prefix 322 /// @param len prefix length for the subnet 323 /// @param id arbitrary subnet id, value of 0 triggers autogeneration 324 /// of subnet id 325 Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, 326 const SubnetID id); 327 328 /// @brief virtual destructor. 329 /// 330 /// A virtual destructor is needed because other classes 331 /// derive from this class. ~Subnet()332 virtual ~Subnet() { }; 333 334 /// @brief keeps the subnet-id value. 335 /// 336 /// It is incremented every time a new Subnet object is created. It is reset 337 /// (@ref resetSubnetID) every time reconfiguration 338 /// occurs. 339 /// 340 /// Static value initialized in subnet.cc. 341 static SubnetID static_id_; 342 343 /// @brief returns the next unique Subnet-ID. 344 /// 345 /// This method generates and returns the next unique subnet-id. 346 /// It is a strictly monotonously increasing value (1,2,3,...) for 347 /// each new Subnet object created. It can be explicitly reset 348 /// back to 1 during reconfiguration (@ref resetSubnetID). 349 /// 350 /// @return the next unique Subnet-ID generateNextID()351 static SubnetID generateNextID() { 352 if (static_id_ == SUBNET_ID_MAX) { 353 resetSubnetID(); 354 } 355 356 return (static_id_++); 357 } 358 359 /// @brief Checks if used pool type is valid. 360 /// 361 /// Allowed type for Subnet4 is Pool::TYPE_V4. 362 /// Allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}. 363 /// This method is implemented in derived classes. 364 /// 365 /// @param type type to be checked 366 /// @throw BadValue if invalid value is used 367 virtual void checkType(Lease::Type type) const = 0; 368 369 /// @brief Returns a sum of possible leases in all pools. 370 /// 371 /// @param pools list of pools 372 /// @return sum of possible leases 373 uint64_t sumPoolCapacity(const PoolCollection& pools) const; 374 375 /// @brief Returns a sum of possible leases in all pools allowing classes. 376 /// 377 /// @param pools list of pools 378 /// @param client_classes list of classes 379 /// @return sum of possible/allowed leases 380 uint64_t sumPoolCapacity(const PoolCollection& pools, 381 const ClientClasses& client_classes) const; 382 383 /// @brief Checks if the specified pool overlaps with an existing pool. 384 /// 385 /// @param pool_type Pool type. 386 /// @param pool Pointer to a pool for which the method should check if 387 /// it overlaps with any existing pool within this subnet. 388 /// 389 /// @return true if pool overlaps with an existing pool of a specified 390 /// type, false otherwise 391 bool poolOverlaps(const Lease::Type& pool_type, const PoolPtr& pool) const; 392 393 /// @brief Unparse a subnet object. 394 /// 395 /// @return A pointer to unparsed subnet configuration. 396 virtual data::ElementPtr toElement() const; 397 398 /// @brief Converts subnet prefix to a pair of prefix/length pair. 399 /// 400 /// IPv4 and IPv6 specific conversion functions should apply extra checks 401 /// on the returned values, i.e. whether length is in range and the IP 402 /// address has a valid type. 403 /// 404 /// @param prefix Prefix to be parsed. 405 /// @throw BadValue if provided prefix is not valid. 406 static std::pair<asiolink::IOAddress, uint8_t> 407 parsePrefixCommon(const std::string& prefix); 408 409 /// @brief subnet-id 410 /// 411 /// Subnet-id is a unique value that can be used to find or identify 412 /// a Subnet4 or Subnet6. 413 SubnetID id_; 414 415 /// @brief collection of IPv4 or non-temporary IPv6 pools in that subnet. 416 PoolCollection pools_; 417 418 /// @brief collection of IPv6 temporary address pools in that subnet. 419 PoolCollection pools_ta_; 420 421 /// @brief collection of IPv6 prefix pools in that subnet. 422 PoolCollection pools_pd_; 423 424 /// @brief a prefix of the subnet. 425 isc::asiolink::IOAddress prefix_; 426 427 /// @brief a prefix length of the subnet. 428 uint8_t prefix_len_; 429 430 /// @brief last allocated address. 431 /// 432 /// This is the last allocated address that was previously allocated from 433 /// this particular subnet. Some allocation algorithms (e.g. iterative) use 434 /// that value, others do not. It should be noted that although the value 435 /// is usually correct, there are cases when it is invalid, e.g. after 436 /// removing a pool, restarting or changing allocation algorithms. For 437 /// that purpose it should be only considered a help that should not be 438 /// fully trusted. 439 isc::asiolink::IOAddress last_allocated_ia_; 440 441 /// @brief last allocated temporary address. 442 /// 443 /// See @ref last_allocated_ia_ for details. 444 isc::asiolink::IOAddress last_allocated_ta_; 445 446 /// @brief last allocated IPv6 prefix. 447 /// 448 /// See @ref last_allocated_ia_ for details. 449 isc::asiolink::IOAddress last_allocated_pd_; 450 451 /// @brief Timestamp indicating when a lease of a specified type has been 452 /// last allocated from this subnet. 453 /// 454 /// @note: This map is protected by the mutex. 455 std::map<Lease::Type, boost::posix_time::ptime> last_allocated_time_; 456 457 /// @brief Shared network name. 458 std::string shared_network_name_; 459 460 private: 461 462 /// @brief returns the last address that was tried from this subnet. 463 /// 464 /// Should be called in a thread safe context. 465 /// 466 /// This method returns the last address that was attempted to be allocated 467 /// from this subnet. This is used as helper information for the next 468 /// iteration of the allocation algorithm. 469 /// 470 /// @todo: Define map<SubnetID, ClientClass, IOAddress> somewhere in the 471 /// AllocEngine::IterativeAllocator and keep the data there 472 /// 473 /// @param type lease type to be returned 474 /// @return address/prefix that was last tried from this subnet 475 isc::asiolink::IOAddress getLastAllocatedInternal(Lease::Type type) const; 476 477 /// @brief Returns the timestamp when the @c setLastAllocated function 478 /// was called. 479 /// 480 /// Should be called in a thread safe context. 481 /// 482 /// @param lease_type Lease type for which last allocation timestamp should 483 /// be returned. 484 /// 485 /// @return Time when a lease of a specified type has been allocated from 486 /// this subnet. The negative infinity time is returned if a lease type is 487 /// not recognized (which is unlikely). 488 boost::posix_time::ptime 489 getLastAllocatedTimeInternal(const Lease::Type& lease_type) const; 490 491 /// @brief sets the last address that was tried from this subnet. 492 /// 493 /// Should be called in a thread safe context. 494 /// 495 /// This method sets the last address that was attempted to be allocated 496 /// from this subnet. This is used as helper information for the next 497 /// iteration of the allocation algorithm. 498 /// 499 /// @note: this routine is Kea thread safe. 500 /// 501 /// @todo: Define map<SubnetID, ClientClass, IOAddress> somewhere in the 502 /// AllocEngine::IterativeAllocator and keep the data there 503 /// @param addr address/prefix to that was tried last 504 /// @param type lease type to be set 505 void setLastAllocatedInternal(Lease::Type type, 506 const isc::asiolink::IOAddress& addr); 507 508 /// @brief Mutex to protect the internal state. 509 boost::scoped_ptr<std::mutex> mutex_; 510 }; 511 512 /// @brief A generic pointer to either Subnet4 or Subnet6 object 513 typedef boost::shared_ptr<Subnet> SubnetPtr; 514 515 516 class Subnet4; 517 518 /// @brief A const pointer to a @c Subnet4 object. 519 typedef boost::shared_ptr<const Subnet4> ConstSubnet4Ptr; 520 521 /// @brief A pointer to a @c Subnet4 object. 522 typedef boost::shared_ptr<Subnet4> Subnet4Ptr; 523 524 /// @brief A configuration holder for IPv4 subnet. 525 /// 526 /// This class represents an IPv4 subnet. 527 /// @note Subnet and Network use virtual inheritance to avoid 528 /// a diamond issue with UserContext 529 class Subnet4 : public Subnet, public Network4 { 530 public: 531 532 /// @brief Constructor with all parameters. 533 /// 534 /// This constructor calls Subnet::Subnet, where subnet-id is generated. 535 /// 536 /// @param prefix Subnet4 prefix 537 /// @param length prefix length 538 /// @param t1 renewal timer (in seconds) 539 /// @param t2 rebind timer (in seconds) 540 /// @param valid_lifetime preferred lifetime of leases (in seconds) 541 /// @param id arbitrary subnet id, default value of 0 triggers 542 /// autogeneration of subnet id 543 Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length, 544 const Triplet<uint32_t>& t1, 545 const Triplet<uint32_t>& t2, 546 const Triplet<uint32_t>& valid_lifetime, 547 const SubnetID id = 0); 548 549 /// @brief Factory function creating an instance of the @c Subnet4. 550 /// 551 /// This function should be used to create an instance of the subnet 552 /// object within a hooks library in cases when the library may be 553 /// unloaded before the object is destroyed. This ensures that the 554 /// ownership of the object by the Kea process is retained. 555 /// 556 /// @param prefix Subnet4 prefix 557 /// @param length prefix length 558 /// @param t1 renewal timer (in seconds) 559 /// @param t2 rebind timer (in seconds) 560 /// @param valid_lifetime preferred lifetime of leases (in seconds) 561 /// @param id arbitrary subnet id, default value of 0 triggers 562 /// autogeneration of subnet id 563 /// 564 /// @return Pointer to the @c Subnet4 instance. 565 static Subnet4Ptr 566 create(const isc::asiolink::IOAddress& prefix, uint8_t length, 567 const Triplet<uint32_t>& t1, 568 const Triplet<uint32_t>& t2, 569 const Triplet<uint32_t>& valid_lifetime, 570 const SubnetID id = 0); 571 572 /// @brief Returns next subnet within shared network. 573 /// 574 /// If the current subnet doesn't belong to any shared network or if 575 /// the next subnet is the same as first subnet (specified in the 576 /// argument) a NULL pointer is returned. 577 /// 578 /// @param first_subnet Pointer to the subnet from which iterations have 579 /// started. 580 /// 581 /// @return Pointer to the next subnet or NULL pointer if the next subnet 582 /// is the first subnet or if the current subnet doesn't belong to a 583 /// shared network. 584 Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet) const; 585 586 /// @brief Returns next subnet within shared network that matches 587 /// client classes. 588 /// 589 /// @param first_subnet Pointer to the subnet from which iterations have 590 /// started. 591 /// @param client_classes List of classes that the client belongs to. 592 /// The subnets not matching the classes aren't returned by this 593 /// method. 594 /// 595 /// @return Pointer to the next subnet or NULL pointer if the next subnet 596 /// is the first subnet or if the current subnet doesn't belong to a 597 /// shared network. 598 Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet, 599 const ClientClasses& client_classes) const; 600 601 /// @brief Checks whether this subnet and parent shared network supports 602 /// the client that belongs to specified classes. 603 /// 604 /// This method extends the @ref Network::clientSupported method with 605 /// additional checks whether shared network owning this class supports 606 /// the client belonging to specified classes. If the class doesn't 607 /// belong to a shared network this method only checks if the subnet 608 /// supports specified classes. 609 /// 610 /// @param client_classes List of classes the client belongs to. 611 /// @return true if client can be supported, false otherwise. 612 virtual bool 613 clientSupported(const isc::dhcp::ClientClasses& client_classes) const; 614 615 /// @brief Returns DHCP4o6 configuration parameters. 616 /// 617 /// This structure is always available. If the 4o6 is not enabled, its 618 /// enabled_ field will be set to false. get4o6()619 Cfg4o6& get4o6() { 620 return (dhcp4o6_); 621 } 622 623 /// @brief Returns const DHCP4o6 configuration parameters. 624 /// 625 /// This structure is always available. If the 4o6 is not enabled, its 626 /// enabled_ field will be set to false. get4o6()627 const Cfg4o6& get4o6() const { 628 return (dhcp4o6_); 629 } 630 631 /// @brief Unparse a subnet object. 632 /// 633 /// @return A pointer to unparsed subnet configuration. 634 virtual data::ElementPtr toElement() const; 635 636 /// @brief Converts subnet prefix to a pair of prefix/length pair. 637 /// 638 /// @param prefix Prefix to be parsed. 639 /// @throw BadValue if provided invalid IPv4 prefix. 640 static std::pair<asiolink::IOAddress, uint8_t> 641 parsePrefix(const std::string& prefix); 642 643 private: 644 645 /// @brief Returns default address for pool selection. 646 /// 647 /// @return ANY IPv4 address default_pool()648 virtual isc::asiolink::IOAddress default_pool() const { 649 return (isc::asiolink::IOAddress("0.0.0.0")); 650 } 651 652 /// @brief Checks if used pool type is valid. 653 /// 654 /// Allowed type for Subnet4 is Pool::TYPE_V4. 655 /// 656 /// @param type type to be checked 657 /// @throw BadValue if invalid value is used 658 virtual void checkType(Lease::Type type) const; 659 660 /// @brief All the information related to DHCP4o6 661 Cfg4o6 dhcp4o6_; 662 }; 663 664 class Subnet6; 665 666 /// @brief A const pointer to a @c Subnet6 object. 667 typedef boost::shared_ptr<const Subnet6> ConstSubnet6Ptr; 668 669 /// @brief A pointer to a Subnet6 object 670 typedef boost::shared_ptr<Subnet6> Subnet6Ptr; 671 672 /// @brief A configuration holder for IPv6 subnet. 673 /// 674 /// This class represents an IPv6 subnet. 675 /// @note Subnet and Network use virtual inheritance to avoid 676 /// a diamond issue with UserContext 677 class Subnet6 : public Subnet, public Network6 { 678 public: 679 680 /// @brief Constructor with all parameters. 681 /// 682 /// This constructor calls Subnet::Subnet, where subnet-id is generated. 683 /// 684 /// @param prefix Subnet6 prefix 685 /// @param length prefix length 686 /// @param t1 renewal timer (in seconds) 687 /// @param t2 rebind timer (in seconds) 688 /// @param preferred_lifetime preferred lifetime of leases (in seconds) 689 /// @param valid_lifetime preferred lifetime of leases (in seconds) 690 /// @param id arbitrary subnet id, default value of 0 triggers 691 /// autogeneration of subnet id 692 Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length, 693 const Triplet<uint32_t>& t1, 694 const Triplet<uint32_t>& t2, 695 const Triplet<uint32_t>& preferred_lifetime, 696 const Triplet<uint32_t>& valid_lifetime, 697 const SubnetID id = 0); 698 699 /// @brief Factory function creating an instance of the @c Subnet4. 700 /// 701 /// This function should be used to create an instance of the subnet 702 /// object within a hooks library in cases when the library may be 703 /// unloaded before the object is destroyed. This ensures that the 704 /// ownership of the object by the Kea process is retained. 705 /// 706 /// @param prefix Subnet6 prefix 707 /// @param length prefix length 708 /// @param t1 renewal timer (in seconds) 709 /// @param t2 rebind timer (in seconds) 710 /// @param preferred_lifetime preferred lifetime of leases (in seconds) 711 /// @param valid_lifetime preferred lifetime of leases (in seconds) 712 /// @param id arbitrary subnet id, default value of 0 triggers 713 /// autogeneration of subnet id 714 /// 715 /// @return Pointer to the @c Subnet6 instance. 716 static Subnet6Ptr 717 create(const isc::asiolink::IOAddress& prefix, uint8_t length, 718 const Triplet<uint32_t>& t1, 719 const Triplet<uint32_t>& t2, 720 const Triplet<uint32_t>& preferred_lifetime, 721 const Triplet<uint32_t>& valid_lifetime, 722 const SubnetID id = 0); 723 724 /// @brief Returns next subnet within shared network. 725 /// 726 /// If the current subnet doesn't belong to any shared network or if 727 /// the next subnet is the same as first subnet (specified in the 728 /// arguments) a NULL pointer is returned. 729 /// 730 /// @param first_subnet Pointer to the subnet from which iterations have 731 /// started. 732 /// 733 /// @return Pointer to the next subnet or NULL pointer if the next subnet 734 /// is the first subnet or if the current subnet doesn't belong to a 735 /// shared network. 736 Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet) const; 737 738 /// @brief Returns next subnet within shared network that matches 739 /// client classes. 740 /// 741 /// @param first_subnet Pointer to the subnet from which iterations have 742 /// started. 743 /// @param client_classes List of classes that the client belongs to. 744 /// The subnets not matching the classes aren't returned by this 745 /// method. 746 /// 747 /// @return Pointer to the next subnet or NULL pointer if the next subnet 748 /// is the first subnet or if the current subnet doesn't belong to a 749 /// shared network. 750 Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet, 751 const ClientClasses& client_classes) const; 752 753 /// @brief Checks whether this subnet and parent shared network supports 754 /// the client that belongs to specified classes. 755 /// 756 /// This method extends the @ref Network::clientSupported method with 757 /// additional checks whether shared network owning this class supports 758 /// the client belonging to specified classes. If the class doesn't 759 /// belong to a shared network this method only checks if the subnet 760 /// supports specified classes. 761 /// 762 /// @param client_classes List of classes the client belongs to. 763 /// @return true if client can be supported, false otherwise. 764 virtual bool 765 clientSupported(const isc::dhcp::ClientClasses& client_classes) const; 766 767 /// @brief Unparse a subnet object. 768 /// 769 /// @return A pointer to unparsed subnet configuration. 770 virtual data::ElementPtr toElement() const; 771 772 /// @brief Converts subnet prefix to a pair of prefix/length pair. 773 /// 774 /// @param prefix Prefix to be parsed. 775 /// @throw BadValue if provided invalid IPv4 prefix. 776 static std::pair<asiolink::IOAddress, uint8_t> 777 parsePrefix(const std::string& prefix); 778 779 private: 780 781 /// @brief Returns default address for pool selection 782 /// @return ANY IPv6 address default_pool()783 virtual isc::asiolink::IOAddress default_pool() const { 784 return (isc::asiolink::IOAddress("::")); 785 } 786 787 /// @brief Checks if used pool type is valid 788 /// 789 /// allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}. 790 /// 791 /// @param type type to be checked 792 /// @throw BadValue if invalid value is used 793 virtual void checkType(Lease::Type type) const; 794 795 }; 796 797 /// @name Definition of the multi index container holding subnet information 798 /// 799 //@{ 800 801 /// @brief Tag for the index for searching by subnet identifier. 802 struct SubnetSubnetIdIndexTag { }; 803 804 /// @brief Tag for the index for searching by subnet prefix. 805 struct SubnetPrefixIndexTag { }; 806 807 /// @brief Tag for the index for searching by server identifier. 808 struct SubnetServerIdIndexTag { }; 809 810 /// @brief Tag for the index for searching by subnet modification time. 811 struct SubnetModificationTimeIndexTag { }; 812 813 /// @brief A collection of @c Subnet4 objects. 814 /// 815 /// This container provides a set of indexes which can be used to retrieve 816 /// subnets by various properties. 817 /// 818 /// This multi index container can hold pointers to @ref Subnet4 819 /// objects representing subnets. It provides indexes for subnet lookups 820 /// using subnet properties such as: subnet identifier, 821 /// subnet prefix or server identifier specified for a subnet. It also 822 /// provides a random access index which allows for using the container 823 /// like a vector. 824 /// 825 /// The random access index is used by the DHCP servers which perform 826 /// a full scan on subnets to find the one that matches some specific 827 /// criteria for subnet selection. 828 /// 829 /// The remaining indexes are used for searching for a specific subnet 830 /// as a result of receiving a command over the control API, e.g. 831 /// when 'subnet-get' command is received. 832 /// 833 /// @todo We should consider optimizing subnet selection by leveraging 834 /// the indexing capabilities of this container, e.g. searching for 835 /// a subnet by interface name, relay address etc. 836 typedef boost::multi_index_container< 837 // Multi index container holds pointers to the subnets. 838 Subnet4Ptr, 839 // The following holds all indexes. 840 boost::multi_index::indexed_by< 841 // First index allows for searching using subnet identifier. 842 boost::multi_index::ordered_unique< 843 boost::multi_index::tag<SubnetSubnetIdIndexTag>, 844 boost::multi_index::const_mem_fun<Subnet, SubnetID, &Subnet::getID> 845 >, 846 // Second index allows for searching using an output from toText function. 847 boost::multi_index::ordered_unique< 848 boost::multi_index::tag<SubnetPrefixIndexTag>, 849 boost::multi_index::const_mem_fun<Subnet, std::string, &Subnet::toText> 850 >, 851 852 // Third index allows for searching using an output from getServerId. 853 boost::multi_index::ordered_non_unique< 854 boost::multi_index::tag<SubnetServerIdIndexTag>, 855 boost::multi_index::const_mem_fun<Network4, asiolink::IOAddress, 856 &Network4::getServerId> 857 >, 858 859 // Forth index allows for searching using subnet modification time. 860 boost::multi_index::ordered_non_unique< 861 boost::multi_index::tag<SubnetModificationTimeIndexTag>, 862 boost::multi_index::const_mem_fun<data::BaseStampedElement, 863 boost::posix_time::ptime, 864 &data::BaseStampedElement::getModificationTime> 865 > 866 > 867 > Subnet4Collection; 868 869 /// @brief A collection of @c Subnet6 objects 870 /// 871 /// This container provides a set of indexes which can be used to retrieve 872 /// subnets by various properties. 873 /// 874 /// This multi index container can hold pointers to @ref Subnet6 objects 875 /// representing subnets. It provides indexes for subnet lookups using 876 /// subnet properties such as: subnet identifier or subnet prefix. It 877 /// also provides a random access index which allows for using the 878 /// container like a vector. 879 /// 880 /// The random access index is used by the DHCP servers which perform 881 /// a full scan on subnets to find the one that matches some specific 882 /// criteria for subnet selection. 883 /// 884 /// The remaining indexes are used for searching for a specific subnet 885 /// as a result of receiving a command over the control API, e.g. 886 /// when 'subnet-get' command is received. 887 /// 888 /// @todo We should consider optimizing subnet selection by leveraging 889 /// the indexing capabilities of this container, e.g. searching for 890 /// a subnet by interface name, relay address etc. 891 typedef boost::multi_index_container< 892 // Multi index container holds pointers to the subnets. 893 Subnet6Ptr, 894 // The following holds all indexes. 895 boost::multi_index::indexed_by< 896 // First index allows for searching using subnet identifier. 897 boost::multi_index::ordered_unique< 898 boost::multi_index::tag<SubnetSubnetIdIndexTag>, 899 boost::multi_index::const_mem_fun<Subnet, SubnetID, &Subnet::getID> 900 >, 901 // Second index allows for searching using an output from toText function. 902 boost::multi_index::ordered_unique< 903 boost::multi_index::tag<SubnetPrefixIndexTag>, 904 boost::multi_index::const_mem_fun<Subnet, std::string, &Subnet::toText> 905 >, 906 // Third index allows for searching using subnet modification time. 907 boost::multi_index::ordered_non_unique< 908 boost::multi_index::tag<SubnetModificationTimeIndexTag>, 909 boost::multi_index::const_mem_fun<data::BaseStampedElement, 910 boost::posix_time::ptime, 911 &data::BaseStampedElement::getModificationTime> 912 > 913 > 914 > Subnet6Collection; 915 916 /// @brief A class containing static convenience methods to fetch the subnets 917 /// from the containers. 918 /// 919 /// @tparam ReturnPtrType Type of the returned object, i.e. @c Subnet4Ptr 920 /// or @c Subnet6Ptr. 921 /// @tparam CollectionType One of the @c Subnet4Collection or @c Subnet6Collection. 922 template<typename ReturnPtrType, typename CollectionType> 923 class SubnetFetcher { 924 public: 925 926 /// @brief Fetches subnets by id. 927 /// 928 /// @param collection Const reference to the collection from which the 929 /// subnet is to be fetched. 930 /// @param subnet_id Id of the subnet to be fetched. 931 /// @return Pointer to the fetched subnet or null if no such subnet 932 /// could be found. get(const CollectionType & collection,const SubnetID & subnet_id)933 static ReturnPtrType get(const CollectionType& collection, 934 const SubnetID& subnet_id) { 935 auto& index = collection.template get<SubnetSubnetIdIndexTag>(); 936 auto s = index.find(subnet_id); 937 if (s != index.end()) { 938 return (*s); 939 } 940 // No subnet found. Return null pointer. 941 return (ReturnPtrType()); 942 } 943 }; 944 945 /// @brief Type of the @c SubnetFetcher used for IPv4. 946 using SubnetFetcher4 = SubnetFetcher<Subnet4Ptr, Subnet4Collection>; 947 948 /// @brief Type of the @c SubnetFetcher used for IPv6. 949 using SubnetFetcher6 = SubnetFetcher<Subnet6Ptr, Subnet6Collection>; 950 951 952 //@} 953 954 } // end of isc::dhcp namespace 955 } // end of isc namespace 956 957 #endif // SUBNET_H 958