1 // Copyright (C) 2012-2020 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 POOL_H
8 #define POOL_H
9 
10 #include <asiolink/io_address.h>
11 #include <cc/data.h>
12 #include <cc/user_context.h>
13 #include <dhcp/classify.h>
14 #include <dhcp/option6_pdexclude.h>
15 #include <dhcpsrv/cfg_option.h>
16 #include <dhcpsrv/lease.h>
17 #include <dhcpsrv/ip_range_permutation.h>
18 
19 #include <boost/shared_ptr.hpp>
20 
21 #include <vector>
22 
23 namespace isc {
24 namespace dhcp {
25 
26 /// @brief base class for Pool4 and Pool6
27 ///
28 /// Stores information about pool of IPv4 or IPv6 addresses.
29 /// That is a basic component of a configuration.
30 class Pool : public isc::data::UserContext, public isc::data::CfgToElement {
31 
32 public:
33     /// @note:
34     /// PoolType enum was removed. Please use Lease::Type instead
35 
36     /// @brief returns Pool-id
37     ///
38     /// @return pool-id value
39     /// Pool-id is an unique value that can be used to identify a pool.
getId()40     uint32_t getId() const {
41         return (id_);
42     }
43 
44     /// @brief Returns the first address in a pool.
45     ///
46     /// @return first address in a pool
getFirstAddress()47     const isc::asiolink::IOAddress& getFirstAddress() const {
48         return (first_);
49     }
50 
51     /// @brief Returns the last address in a pool.
52     /// @return last address in a pool
getLastAddress()53     const isc::asiolink::IOAddress& getLastAddress() const {
54         return (last_);
55     }
56 
57     /// @brief Checks if a given address is in the range.
58     ///
59     /// @return true, if the address is in pool
60     bool inRange(const isc::asiolink::IOAddress& addr) const;
61 
62     /// @brief Returns pool type (v4, v6 non-temporary, v6 temp, v6 prefix)
63     /// @return returns pool type
getType()64     Lease::Type getType() const {
65         return (type_);
66     }
67 
68     /// @brief returns textual representation of the pool
69     ///
70     /// @return textual representation
71     virtual std::string toText() const;
72 
73     /// @brief virtual destructor
74     ///
75     /// We need Pool to be a polymorphic class, so we could dynamic cast
76     /// from PoolPtr to Pool6Ptr if we need to. A class becomes polymorphic,
77     /// when there is at least one virtual method.
~Pool()78     virtual ~Pool() {
79     }
80 
81     /// @brief Returns the number of all leases in this pool.
82     ///
83     /// Note that this is the upper bound, assuming that no leases are used
84     /// and there are no host reservations. This is just a theoretical calculation.
85     /// @return number of possible leases in this pool
getCapacity()86     uint64_t getCapacity() const {
87         return (capacity_);
88     }
89 
90     /// @brief Returns pointer to the option data configuration for this pool.
getCfgOption()91     CfgOptionPtr getCfgOption() {
92         return (cfg_option_);
93     }
94 
95     /// @brief Returns const pointer to the option data configuration for
96     /// this pool.
getCfgOption()97     ConstCfgOptionPtr getCfgOption() const {
98         return (cfg_option_);
99     }
100 
101     /// @brief Checks whether this pool supports client that belongs to
102     /// specified classes.
103     ///
104     /// @todo: currently doing the same as network which needs improving.
105     ///
106     /// @param client_classes list of all classes the client belongs to
107     /// @return true if client can be supported, false otherwise
108     bool clientSupported(const ClientClasses& client_classes) const;
109 
110     /// @brief Sets the supported class to  class class_name
111     ///
112     /// @param class_name client class to be supported by this pool
113     void allowClientClass(const ClientClass& class_name);
114 
115     /// @brief returns the client class
116     ///
117     /// @note The returned reference is only valid as long as the object
118     /// returned is valid.
119     ///
120     /// @return client class @ref client_class_
getClientClass()121     const ClientClass& getClientClass() const {
122         return (client_class_);
123     }
124 
125     /// @brief Adds class class_name to classes required to be evaluated
126     ///
127     /// @param class_name client class required to be evaluated
requireClientClass(const ClientClass & class_name)128     void requireClientClass(const ClientClass& class_name) {
129         if (!required_classes_.contains(class_name)) {
130             required_classes_.insert(class_name);
131         }
132     }
133 
134     /// @brief Returns classes which are required to be evaluated
getRequiredClasses()135     const ClientClasses& getRequiredClasses() const {
136         return (required_classes_);
137     }
138 
139     /// @brief returns the last address that was tried from this pool
140     ///
141     /// @return address/prefix that was last tried from this pool
getLastAllocated()142     isc::asiolink::IOAddress getLastAllocated() const {
143         return last_allocated_;
144     }
145 
146     /// @brief checks if the last address is valid
147     /// @return true if the last address is valid
isLastAllocatedValid()148     bool isLastAllocatedValid() const {
149         return last_allocated_valid_;
150     }
151 
152     /// @brief sets the last address that was tried from this pool
153     ///
154     /// @param addr address/prefix to that was tried last
setLastAllocated(const isc::asiolink::IOAddress & addr)155     void setLastAllocated(const isc::asiolink::IOAddress& addr) {
156         last_allocated_ = addr;
157         last_allocated_valid_ = true;
158     }
159 
160     /// @brief resets the last address to invalid
resetLastAllocated()161     void resetLastAllocated() {
162         last_allocated_valid_ = false;
163     }
164 
165     /// @brief Unparse a pool object.
166     ///
167     /// @return A pointer to unparsed pool configuration.
168     virtual data::ElementPtr toElement() const;
169 
170     /// @brief Returns pointer to the permutation associated with the pool.
171     ///
172     /// @return Pointer to the address range permutation.
getPermutation()173     IPRangePermutationPtr getPermutation() const {
174         return (permutation_);
175     }
176 
177 protected:
178 
179     /// @brief protected constructor
180     ///
181     /// This constructor is protected to prevent anyone from instantiating
182     /// Pool class directly. Instances of Pool4 and Pool6 should be created
183     /// instead.
184     ///
185     /// @param type type of lease that will be served from this pool
186     /// @param first first address of a range
187     /// @param last last address of a range
188     Pool(Lease::Type type,
189          const isc::asiolink::IOAddress& first,
190          const isc::asiolink::IOAddress& last);
191 
192     /// @brief returns the next unique Pool-ID
193     ///
194     /// @return the next unique Pool-ID
getNextID()195     static uint32_t getNextID() {
196         static uint32_t id = 0;
197         return (id++);
198     }
199 
200     /// @brief pool-id
201     ///
202     /// This ID is used to identify this specific pool.
203     uint32_t id_;
204 
205     /// @brief The first address in a pool
206     isc::asiolink::IOAddress first_;
207 
208     /// @brief The last address in a pool
209     isc::asiolink::IOAddress last_;
210 
211     /// @brief defines a lease type that will be served from this pool
212     Lease::Type type_;
213 
214     /// @brief Stores number of possible leases.
215     ///
216     /// This could be calculated on the fly, but the calculations are somewhat
217     /// involved, so it is more efficient to calculate it once and just store
218     /// the result. Note that for very large pools, the number is capped at
219     /// max value of uint64_t.
220     uint64_t capacity_;
221 
222     /// @brief Pointer to the option data configuration for this pool.
223     CfgOptionPtr cfg_option_;
224 
225     /// @brief Optional definition of a client class
226     ///
227     /// @ref Network::client_class_
228     ClientClass client_class_;
229 
230     /// @brief Required classes
231     ///
232     /// @ref isc::dhcp::Network::required_classes_
233     ClientClasses required_classes_;
234 
235     /// @brief Pointer to the user context (may be NULL)
236     data::ConstElementPtr user_context_;
237 
238     /// @brief Last allocated address
239     /// See @ref isc::dhcp::Subnet::last_allocated_ia_
240     /// Initialized and reset to first
241     isc::asiolink::IOAddress last_allocated_;
242 
243     /// @brief Status of last allocated address
244     bool last_allocated_valid_;
245 
246     /// @brief Pointer to the permutation object.
247     ///
248     /// It may be initialized for some pools to provide address
249     /// or delegated prefix randomization capabilities.
250     IPRangePermutationPtr permutation_;
251 };
252 
253 class Pool4;
254 
255 /// @brief a pointer an IPv4 Pool
256 typedef boost::shared_ptr<Pool4> Pool4Ptr;
257 
258 /// @brief Pool information for IPv4 addresses
259 ///
260 /// It holds information about pool4, i.e. a range of IPv4 address space that
261 /// is configured for DHCP allocation.
262 class Pool4 : public Pool {
263 public:
264     /// @brief the constructor for Pool4 "min-max" style definition
265     ///
266     /// @param first the first address in a pool
267     /// @param last the last address in a pool
268     Pool4(const isc::asiolink::IOAddress& first,
269           const isc::asiolink::IOAddress& last);
270 
271     /// @brief the constructor for Pool4 "prefix/len" style definition
272     ///
273     /// @param prefix specifies prefix of the pool
274     /// @param prefix_len specifies length of the prefix of the pool
275     Pool4(const isc::asiolink::IOAddress& prefix,
276           uint8_t prefix_len);
277 
278     /// @brief Factory function for creating an instance of the @c Pool4.
279     ///
280     /// This function should be used to create an instance of the pool
281     /// within a hooks library in cases when the library may be unloaded
282     /// before the object is destroyed. This ensures that the ownership
283     /// of the object by the Kea process is retained.
284     ///
285     /// @param first the first address in a pool
286     /// @param last the last address in a pool
287     ///
288     /// @return Pointer to the @c Pool4 instance.
289     static Pool4Ptr create(const isc::asiolink::IOAddress& first,
290                            const isc::asiolink::IOAddress& last);
291 
292     /// @brief Factory function for creating an instance of the @c Pool4.
293     ///
294     /// This function should be used to create an instance of the pool
295     /// within a hooks library in cases when the library may be unloaded
296     /// before the object is destroyed. This ensures that the ownership
297     /// of the object by the Kea process is retained.
298     ///
299     /// @param prefix specifies prefix of the pool.
300     /// @param prefix_len specifies length of the prefix of the pool.
301     ///
302     /// @return Pointer to the @c Pool4 instance.
303     static Pool4Ptr create(const isc::asiolink::IOAddress& prefix,
304                            uint8_t prefix_len);
305 
306     /// @brief Unparse a Pool4 object.
307     ///
308     /// @return A pointer to unparsed Pool4 configuration.
309     virtual data::ElementPtr toElement() const;
310 };
311 
312 class Pool6;
313 
314 /// @brief a pointer an IPv6 Pool
315 typedef boost::shared_ptr<Pool6> Pool6Ptr;
316 
317 /// @brief Pool information for IPv6 addresses and prefixes
318 ///
319 /// It holds information about pool6, i.e. a range of IPv6 address space that
320 /// is configured for DHCP allocation.
321 class Pool6 : public Pool {
322 public:
323 
324     /// @brief the constructor for Pool6 "min-max" style definition
325     ///
326     /// @throw BadValue if PD is define (PD can be only prefix/len)
327     ///
328     /// @param type type of the pool (IA or TA)
329     /// @param first the first address in a pool
330     /// @param last the last address in a pool
331     Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
332           const isc::asiolink::IOAddress& last);
333 
334     /// @brief the constructor for Pool6 "prefix/len" style definition
335     ///
336     /// For addressed, this is just a prefix/len definition. For prefixes,
337     /// there is one extra additional parameter delegated_len. It specifies
338     /// a size of delegated prefixes that the pool will be split into. For
339     /// example pool 2001:db8::/56, delegated_len=64 means that there is a
340     /// pool 2001:db8::/56. It will be split into 256 prefixes of length /64,
341     /// e.g. 2001:db8:0:1::/64, 2001:db8:0:2::/64 etc.
342     ///
343     /// Naming convention:
344     /// A smaller prefix length yields a shorter prefix which describes a larger
345     /// set of addresses. A larger length yields a longer prefix which describes
346     /// a smaller set of addresses.
347     ///
348     /// Obviously, prefix_len must define shorter or equal prefix length than
349     /// delegated_len, so prefix_len <= delegated_len. Note that it is slightly
350     /// confusing: bigger (larger) prefix actually has smaller prefix length,
351     /// e.g. /56 is a bigger prefix than /64, but has shorter (smaller) prefix
352     /// length.
353     ///
354     /// @throw BadValue if delegated_len is defined for non-PD types or
355     ///        when delegated_len < prefix_len
356     ///
357     /// @param type type of the pool (IA, TA or PD)
358     /// @param prefix specifies prefix of the pool
359     /// @param prefix_len specifies prefix length of the pool
360     /// @param delegated_len specifies length of the delegated prefixes
361     Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
362           uint8_t prefix_len, uint8_t delegated_len = 128);
363 
364     /// @brief Constructor for DHCPv6 prefix pool with an excluded prefix.
365     ///
366     /// If @c excluded_prefix is equal to '::' and the @c excluded_prefix_len
367     /// is equal to 0, the excluded prefix is assumed to be unspecified for
368     /// the pool. In this case, the server will not send the Prefix Exclude
369     /// option to a client.
370     ///
371     /// @param prefix specified a prefix of the pool.
372     /// @param prefix_len specifies prefix length of the pool.
373     /// @param delegated_len specifies length of the delegated prefixes.
374     /// @param excluded_prefix specifies an excluded prefix as per RFC6603.
375     /// @param excluded_prefix_len specifies length of an excluded prefix.
376     Pool6(const asiolink::IOAddress& prefix, const uint8_t prefix_len,
377           const uint8_t delegated_len,
378           const asiolink::IOAddress& excluded_prefix,
379           const uint8_t excluded_prefix_len);
380 
381     /// @brief Factory function for creating an instance of the @c Pool6.
382     ///
383     /// This function should be used to create an instance of the pool
384     /// within a hooks library in cases when the library may be unloaded
385     /// before the object is destroyed. This ensures that the ownership
386     /// of the object by the Kea process is retained.
387     ///
388     /// @param type type of the pool (IA or TA)
389     /// @param first the first address in a pool
390     /// @param last the last address in a pool
391     ///
392     /// @return Pointer to the @c Pool6 instance.
393     static Pool6Ptr create(Lease::Type type,
394                            const isc::asiolink::IOAddress& first,
395                            const isc::asiolink::IOAddress& last);
396 
397     /// @brief Factory function for creating an instance of the @c Pool6.
398     ///
399     /// This function should be used to create an instance of the pool
400     /// within a hooks library in cases when the library may be unloaded
401     /// before the object is destroyed. This ensures that the ownership
402     /// of the object by the Kea process is retained.
403     ///
404     /// @param type type of the pool (IA, TA or PD)
405     /// @param prefix specifies prefix of the pool
406     /// @param prefix_len specifies prefix length of the pool
407     /// @param delegated_len specifies length of the delegated prefixes
408     ///
409     /// @return Pointer to the @c Pool6 instance.
410     static Pool6Ptr create(Lease::Type type,
411                            const isc::asiolink::IOAddress& prefix,
412                            uint8_t prefix_len,
413                            uint8_t delegated_len = 128);
414 
415     /// @brief Factory function for creating an instance of the @c Pool6.
416     ///
417     /// If @c excluded_prefix is equal to '::' and the @c excluded_prefix_len
418     /// is equal to 0, the excluded prefix is assumed to be unspecified for
419     /// the pool. In this case, the server will not send the Prefix Exclude
420     /// option to a client.
421     ///
422     /// @param prefix specifies a prefix of the pool.
423     /// @param prefix_len specifies prefix length of the pool.
424     /// @param delegated_len specifies length of the delegated prefixes.
425     /// @param excluded_prefix specifies an excluded prefix as per RFC6603.
426     /// @param excluded_prefix_len specifies length of an excluded prefix.
427     ///
428     /// @return Pointer to the @c Pool6 instance.
429     static Pool6Ptr create(const asiolink::IOAddress& prefix,
430                            const uint8_t prefix_len,
431                            const uint8_t delegated_len,
432                            const asiolink::IOAddress& excluded_prefix,
433                            const uint8_t excluded_prefix_len);
434 
435     /// @brief returns pool type
436     ///
437     /// @return pool type
getType()438     Lease::Type getType() const {
439         return (type_);
440     }
441 
442     /// @brief returns delegated prefix length
443     ///
444     /// This may be useful for "prefix/len" style definition for
445     /// addresses, but is mostly useful for prefix pools.
446     /// @return prefix length (1-128)
getLength()447     uint8_t getLength() const {
448         return (prefix_len_);
449     }
450 
451     /// @brief Returns instance of the pool specific Prefix Exclude option.
452     ///
453     /// @return An instance of the Prefix Exclude option (RFC 6603) or NULL
454     /// if such option hasn't been specified for the pool.
getPrefixExcludeOption()455     Option6PDExcludePtr getPrefixExcludeOption() const {
456         return (pd_exclude_option_);
457     }
458 
459     /// @brief Unparse a Pool6 object.
460     ///
461     /// @return A pointer to unparsed Pool6 configuration.
462     virtual data::ElementPtr toElement() const;
463 
464     /// @brief returns textual representation of the pool
465     ///
466     /// @return textual representation
467     virtual std::string toText() const;
468 
469 private:
470 
471     /// @brief Generic method initializing a DHCPv6 pool.
472     ///
473     /// This method should be called by the constructors to initialize
474     /// DHCPv6 pools.
475     ///
476     /// @param Lease/pool type.
477     /// @param prefix An address or delegated prefix (depending on the
478     /// pool type specified as @c type).
479     /// @param prefix_len Prefix length. If a pool is an address pool,
480     /// this value should be set to 128.
481     /// @param delegated_len Length of the delegated prefixes. If a pool
482     /// is an address pool, this value should be set to 128.
483     /// @param excluded_prefix An excluded prefix as per RFC6603. This
484     /// value should only be specified for prefix pools. The value of
485     /// '::' means "unspecified".
486     /// @param excluded_prefix_len Length of the excluded prefix. This
487     /// is only specified for prefix pools. The value of 0 should be
488     /// used when @c excluded_prefix is not specified.
489     void init(const Lease::Type& type,
490               const asiolink::IOAddress& prefix,
491               const uint8_t prefix_len,
492               const uint8_t delegated_len,
493               const asiolink::IOAddress& excluded_prefix,
494               const uint8_t excluded_prefix_len);
495 
496     /// @brief Defines prefix length (for TYPE_PD only)
497     uint8_t prefix_len_;
498 
499     /// @brief A pointer to the Prefix Exclude option (RFC 6603).
500     Option6PDExcludePtr pd_exclude_option_;
501 
502 };
503 
504 /// @brief a pointer to either IPv4 or IPv6 Pool
505 typedef boost::shared_ptr<Pool> PoolPtr;
506 
507 /// @brief a container for either IPv4 or IPv6 Pools
508 typedef std::vector<PoolPtr> PoolCollection;
509 
510 
511 } // end of isc::dhcp namespace
512 } // end of isc namespace
513 
514 
515 #endif // POOL_H
516