alloc_engine.h 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  1. // Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef ALLOC_ENGINE_H
  15. #define ALLOC_ENGINE_H
  16. #include <asiolink/io_address.h>
  17. #include <dhcp/duid.h>
  18. #include <dhcp/hwaddr.h>
  19. #include <dhcp/pkt6.h>
  20. #include <dhcp/option6_ia.h>
  21. #include <dhcpsrv/host.h>
  22. #include <dhcpsrv/subnet.h>
  23. #include <dhcpsrv/lease_mgr.h>
  24. #include <hooks/callout_handle.h>
  25. #include <boost/shared_ptr.hpp>
  26. #include <boost/noncopyable.hpp>
  27. #include <map>
  28. namespace isc {
  29. namespace dhcp {
  30. /// An exception that is thrown when allocation module fails (e.g. due to
  31. /// lack of available addresses)
  32. class AllocFailed : public isc::Exception {
  33. public:
  34. /// @brief constructor
  35. ///
  36. /// @param file name of the file, where exception occurred
  37. /// @param line line of the file, where exception occurred
  38. /// @param what text description of the issue that caused exception
  39. AllocFailed(const char* file, size_t line, const char* what)
  40. : isc::Exception(file, line, what) {}
  41. };
  42. /// @brief DHCPv4 and DHCPv6 allocation engine
  43. ///
  44. /// This class represents a DHCP allocation engine. It is responsible
  45. /// for picking subnets, choosing and allocating a lease, extending,
  46. /// renewing, releasing and possibly expiring leases.
  47. ///
  48. /// @todo: Does not handle out of leases well
  49. /// @todo: Does not handle out of allocation attempts well
  50. class AllocEngine : public boost::noncopyable {
  51. protected:
  52. /// @brief base class for all address/prefix allocation algorithms
  53. ///
  54. /// This is an abstract class that should not be used directly, but rather
  55. /// specialized implementations should be used instead.
  56. class Allocator {
  57. public:
  58. /// @brief picks one address out of available pools in a given subnet
  59. ///
  60. /// This method returns one address from the available pools in the
  61. /// specified subnet. It should not check if the address is used or
  62. /// reserved - AllocEngine will check that and will call pickAddress
  63. /// again if necessary. The number of times this method is called will
  64. /// increase as the number of available leases will decrease.
  65. ///
  66. /// This method can also be used to pick a prefix. We should not rename
  67. /// it to pickLease(), because at this early stage there is no concept
  68. /// of a lease yet. Here it is a matter of selecting one address or
  69. /// prefix from the defined pool, without going into details who it is
  70. /// for or who uses it. I thought that pickAddress() is less confusing
  71. /// than pickResource(), because nobody would immediately know what the
  72. /// resource means in this context.
  73. ///
  74. /// @param subnet next address will be returned from pool of that subnet
  75. /// @param duid Client's DUID
  76. /// @param hint client's hint
  77. ///
  78. /// @return the next address
  79. virtual isc::asiolink::IOAddress
  80. pickAddress(const SubnetPtr& subnet, const DuidPtr& duid,
  81. const isc::asiolink::IOAddress& hint) = 0;
  82. /// @brief Default constructor.
  83. ///
  84. /// Specifies which type of leases this allocator will assign
  85. /// @param pool_type specifies pool type (addresses, temp. addr or prefixes)
  86. Allocator(Lease::Type pool_type)
  87. :pool_type_(pool_type) {
  88. }
  89. /// @brief virtual destructor
  90. virtual ~Allocator() {
  91. }
  92. protected:
  93. /// @brief defines pool type allocation
  94. Lease::Type pool_type_;
  95. };
  96. /// defines a pointer to allocator
  97. typedef boost::shared_ptr<Allocator> AllocatorPtr;
  98. /// @brief Address/prefix allocator that iterates over all addresses
  99. ///
  100. /// This class implements an iterative algorithm that returns all addresses in
  101. /// a pool iteratively, one after another. Once the last address is reached,
  102. /// it starts allocating from the beginning of the first pool (i.e. it loops
  103. /// over).
  104. class IterativeAllocator : public Allocator {
  105. public:
  106. /// @brief default constructor
  107. ///
  108. /// Does not do anything
  109. /// @param type - specifies allocation type
  110. IterativeAllocator(Lease::Type type);
  111. /// @brief returns the next address from pools in a subnet
  112. ///
  113. /// @param subnet next address will be returned from pool of that subnet
  114. /// @param duid Client's DUID (ignored)
  115. /// @param hint client's hint (ignored)
  116. /// @return the next address
  117. virtual isc::asiolink::IOAddress
  118. pickAddress(const SubnetPtr& subnet,
  119. const DuidPtr& duid,
  120. const isc::asiolink::IOAddress& hint);
  121. protected:
  122. /// @brief Returns the next prefix
  123. ///
  124. /// This method works for IPv6 addresses only. It increases the
  125. /// specified prefix by a given prefix_len. For example, 2001:db8::
  126. /// increased by prefix length /32 will become 2001:db9::. This method
  127. /// is used to iterate over IPv6 prefix pools
  128. ///
  129. /// @param prefix prefix to be increased
  130. /// @param prefix_len length of the prefix to be increased
  131. /// @return result prefix
  132. static isc::asiolink::IOAddress
  133. increasePrefix(const isc::asiolink::IOAddress& prefix,
  134. const uint8_t prefix_len);
  135. };
  136. /// @brief Address/prefix allocator that gets an address based on a hash
  137. ///
  138. /// @todo: This is a skeleton class for now and is missing an implementation.
  139. class HashedAllocator : public Allocator {
  140. public:
  141. /// @brief default constructor (does nothing)
  142. /// @param type - specifies allocation type
  143. HashedAllocator(Lease::Type type);
  144. /// @brief returns an address based on hash calculated from client's DUID.
  145. ///
  146. /// @todo: Implement this method
  147. ///
  148. /// @param subnet an address will be picked from pool of that subnet
  149. /// @param duid Client's DUID
  150. /// @param hint a hint (last address that was picked)
  151. /// @return selected address
  152. virtual isc::asiolink::IOAddress pickAddress(const SubnetPtr& subnet,
  153. const DuidPtr& duid,
  154. const isc::asiolink::IOAddress& hint);
  155. };
  156. /// @brief Random allocator that picks address randomly
  157. ///
  158. /// @todo: This is a skeleton class for now and is missing an implementation.
  159. class RandomAllocator : public Allocator {
  160. public:
  161. /// @brief default constructor (does nothing)
  162. /// @param type - specifies allocation type
  163. RandomAllocator(Lease::Type type);
  164. /// @brief returns a random address from pool of specified subnet
  165. ///
  166. /// @todo: Implement this method
  167. ///
  168. /// @param subnet an address will be picked from pool of that subnet
  169. /// @param duid Client's DUID (ignored)
  170. /// @param hint the last address that was picked (ignored)
  171. /// @return a random address from the pool
  172. virtual isc::asiolink::IOAddress
  173. pickAddress(const SubnetPtr& subnet, const DuidPtr& duid,
  174. const isc::asiolink::IOAddress& hint);
  175. };
  176. public:
  177. /// @brief specifies allocation type
  178. typedef enum {
  179. ALLOC_ITERATIVE, // iterative - one address after another
  180. ALLOC_HASHED, // hashed - client's DUID/client-id is hashed
  181. ALLOC_RANDOM // random - an address is randomly selected
  182. } AllocType;
  183. /// @brief Constructor.
  184. ///
  185. /// Instantiates necessary services, required to run DHCP server.
  186. /// In particular, creates IfaceMgr that will be responsible for
  187. /// network interaction. Will instantiate lease manager, and load
  188. /// old or create new DUID.
  189. ///
  190. /// @param engine_type selects allocation algorithm
  191. /// @param attempts number of attempts for each lease allocation before
  192. /// we give up (0 means unlimited)
  193. /// @param ipv6 specifies if the engine should work for IPv4 or IPv6
  194. AllocEngine(AllocType engine_type, unsigned int attempts, bool ipv6 = true);
  195. /// @brief Destructor.
  196. virtual ~AllocEngine() { }
  197. /// @brief Returns allocator for a given pool type
  198. ///
  199. /// @param type type of pool (V4, IA, TA or PD)
  200. /// @throw BadValue if allocator for a given type is missing
  201. /// @return pointer to allocator handling a given resource types
  202. AllocatorPtr getAllocator(Lease::Type type);
  203. private:
  204. /// @brief a pointer to currently used allocator
  205. ///
  206. /// For IPv4, there will be only one allocator: TYPE_V4
  207. /// For IPv6, there will be 3 allocators: TYPE_NA, TYPE_TA, TYPE_PD
  208. std::map<Lease::Type, AllocatorPtr> allocators_;
  209. /// @brief number of attempts before we give up lease allocation (0=unlimited)
  210. unsigned int attempts_;
  211. // hook name indexes (used in hooks callouts)
  212. int hook_index_lease4_select_; ///< index for lease4_select hook
  213. int hook_index_lease6_select_; ///< index for lease6_select hook
  214. public:
  215. /// @brief Defines a single hint (an address + prefix-length).
  216. ///
  217. /// This is an entry that represents what the client had requested,
  218. /// either an address or a prefix. Prefix length is 128 for regular
  219. /// addresses.
  220. typedef std::pair<isc::asiolink::IOAddress, uint8_t> HintType;
  221. /// @brief Container for client's hints.
  222. typedef std::vector<HintType> HintContainer;
  223. /// @brief Context information for the DHCPv6 leases allocation.
  224. ///
  225. /// This structure holds a set of information provided by the DHCPv6
  226. /// server to the allocation engine. In particular, it holds the
  227. /// client identifying information, such as HW address or client
  228. /// identifier. It also holds the information about the subnet that
  229. /// the client is connected to.
  230. ///
  231. /// This structure is also used to pass some information from
  232. /// the allocation engine back to the server, i.e. the old leases
  233. /// which the client had before the allocation.
  234. ///
  235. /// This structure is expected to be common for a single client, even
  236. /// if multiple IAs are used. Some of the fields will need to be
  237. /// updated for every call (there's a separate call to the allocation
  238. /// engine for each IA option).
  239. ///
  240. /// This structure is meant to be extended in the future, if more
  241. /// information should be passed to the allocation engine. Note
  242. /// that the big advantage of using the context structure to pass
  243. /// information to the allocation engine methods is that adding
  244. /// new information doesn't modify the API of the allocation engine.
  245. struct ClientContext6 {
  246. /// @brief Subnet selected for the client by the server.
  247. Subnet6Ptr subnet_;
  248. /// @brief Client identifier
  249. DuidPtr duid_;
  250. /// @brief iaid IAID field from IA_NA or IA_PD that is being processed
  251. uint32_t iaid_;
  252. /// @brief Lease type (IA or PD)
  253. Lease::Type type_;
  254. /// @brief Hardware/MAC address (if available, may be NULL)
  255. HWAddrPtr hwaddr_;
  256. /// @brief client's hints
  257. ///
  258. /// There will typically be just one address, but the protocol allows
  259. /// more than one address or prefix for each IA container.
  260. HintContainer hints_;
  261. /// @brief A boolean value which indicates that server takes
  262. /// responsibility for the forward DNS Update for this lease
  263. /// (if true).
  264. bool fwd_dns_update_;
  265. /// @brief A boolean value which indicates that server takes
  266. /// responsibility for the reverse DNS Update for this lease
  267. /// (if true).
  268. bool rev_dns_update_;
  269. /// @brief Hostname.
  270. ///
  271. /// The server retrieves the hostname from the Client FQDN option,
  272. /// Hostname option or the host reservation record for the client.
  273. std::string hostname_;
  274. /// @brief Callout handle associated with the client's message.
  275. hooks::CalloutHandlePtr callout_handle_;
  276. /// @brief Indicates if this is a real or fake allocation.
  277. ///
  278. /// The real allocation is when the allocation engine is supposed
  279. /// to make an update in a lease database: create new lease, or
  280. /// update existing lease.
  281. bool fake_allocation_;
  282. /// @brief A pointer to any old leases that the client had before update
  283. /// but are no longer valid after the update/allocation.
  284. ///
  285. /// This collection is typically empty, except cases when we are doing
  286. /// address reassignment, e.g. because there is a host reservation that
  287. /// gives this address to someone else, so we had to return the address,
  288. /// and give a new one to this client.
  289. Lease6Collection old_leases_;
  290. /// @brief A pointer to any leases that have changed FQDN information.
  291. ///
  292. /// This list may contain old versions of the leases that are still
  293. /// valid. In particular, it will contain a lease if the client's
  294. /// FQDN has changed.
  295. Lease6Collection changed_leases_;
  296. /// @brief A pointer to the object identifying host reservations.
  297. ///
  298. /// May be NULL if there are no reservations.
  299. ConstHostPtr host_;
  300. /// @brief A pointer to the client's message
  301. ///
  302. /// This is used exclusively for hook purposes.
  303. Pkt6Ptr query_;
  304. /// @brief A pointer to the IA_NA/IA_PD option to be sent in response
  305. Option6IAPtr ia_rsp_;
  306. /// @brief Specifies whether new leases in Renew/Rebind are allowed
  307. ///
  308. /// This field controls what to do when renewing or rebinding client
  309. /// does not have any leases. RFC3315 and the stateful-issues draft do
  310. /// not specify it and it is left up to the server configuration policy.
  311. /// False (the default) means that the client will not get any new
  312. /// unreserved leases if his existing leases are no longer suitable.
  313. /// True means that the allocation engine will do its best to assign
  314. /// something.
  315. bool allow_new_leases_in_renewals_;
  316. /// @brief Default constructor.
  317. ClientContext6();
  318. /// @brief Constructor with parameters.
  319. ///
  320. /// Note that several less frequently used parameters (callout_handle,
  321. /// old_leases, host) fields are not set. They should be set explicitly,
  322. /// if needed.
  323. ///
  324. /// @param subnet subnet the allocation should come from
  325. /// @param duid Client's DUID
  326. /// @param iaid iaid field from the IA_NA container that client sent
  327. /// @param hint a hint that the client provided
  328. /// @param type lease type (IA, TA or PD)
  329. /// @param fwd_dns A boolean value which indicates that server takes
  330. /// responsibility for the forward DNS Update for this lease
  331. /// (if true).
  332. /// @param rev_dns A boolean value which indicates that server takes
  333. /// responsibility for the reverse DNS Update for this lease
  334. /// (if true).
  335. /// @param hostname A fully qualified domain-name of the client.
  336. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  337. /// an address for SOLICIT that is not really allocated (true)
  338. ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid,
  339. const uint32_t iaid, const isc::asiolink::IOAddress& hint,
  340. const Lease::Type type, const bool fwd_dns, const bool
  341. rev_dns, const std::string& hostname, const bool
  342. fake_allocation);
  343. };
  344. /// @brief Allocates IPv6 leases for a given IA container
  345. ///
  346. /// This method uses the currently selected allocator to pick allocatable
  347. /// resources (i.e. addresses or prefixes) from specified subnet, creates
  348. /// a lease (one or more, if needed) for that resources and then inserts
  349. /// it into LeaseMgr (if this allocation is not fake, i.e. this is not a
  350. /// response to SOLICIT).
  351. ///
  352. /// This method uses host reservation if ctx.host_ is set. The easy way to
  353. /// set it is to call @ref AllocEngine::findReservation(ctx). The host reservation
  354. /// is convenient, but incurs performance penalty, so it can be tweaked on
  355. /// a per subnet basis. There are three possible modes:
  356. /// 1. disabled (no host reservation at all). This is the most performant one
  357. /// as the code can skip all checks;
  358. /// 2. out-of-pool (only reservations that are outside
  359. /// of the dynamic pools are allowed. This is a compromise - it requires
  360. /// a sysadmin to be more careful with the reservations, but the code
  361. /// can skip reservation checks while managing in-pool addresses);
  362. /// 3. in-pool (which also allow out-of-pool; this is the most flexible
  363. /// mode, but it means that the allocation engine has to do reservation
  364. /// checks on every lease, even those dynamically assigned, which degrades
  365. /// performance).
  366. ///
  367. /// The logic in this method is as follows:
  368. /// -# Case 1. if there are no leases, and there are reservations...
  369. /// Are the reserved addresses/prefixes used by someone else?
  370. /// -# yes: we have a problem. We can't assign the reserved address yet,
  371. /// because it is used by someone else. We can't immediately release
  372. /// the lease as there is some other client that is currently using it.
  373. /// We will temporarily assign a different, unreserved lease for this
  374. /// client. In the mean time, the other client will hopefully get back
  375. /// to us, so we could revoke his lease.
  376. /// -# no: assign them => done
  377. /// -# Case 2. if there are leases and there are no reservations...
  378. /// Are the leases reserved for someone else?
  379. /// -# yes: release them, assign something else
  380. /// -# no: renew them => done
  381. /// -# Case 3. if there are leases and there are reservations...
  382. /// Are the leases matching reservations?
  383. /// -# yes: renew them => done
  384. /// -# no: release existing leases, assign new ones based on reservations
  385. /// -# Case 4. if there are no leases and no reservations...
  386. /// assign new leases (this is the "normal" case when the reservations
  387. /// are disabled).
  388. ///
  389. /// @param ctx client context that passes all necessary information. See
  390. /// @ref ClientContext6 for details.
  391. ///
  392. /// The following fields of ClientContext6 are used:
  393. ///
  394. /// @ref ClientContext6::subnet_ subnet the allocation should come from<br/>
  395. /// @ref ClientContext6::duid_ Client's DUID<br/>
  396. /// @ref ClientContext6::iaid_ iaid field from the IA_NA container
  397. /// that client sent<br/>
  398. /// @ref ClientContext6::hints_ a hint that the client provided<br/>
  399. /// @ref ClientContext6::type_ lease type (IA, TA or PD)<br/>
  400. /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates
  401. /// that server takes responsibility for the forward DNS Update
  402. /// for this lease (if true).<br/>
  403. /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates
  404. /// that server takes responsibility for the reverse DNS Update for
  405. /// this lease (if true).<br/>
  406. /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.<br/>
  407. /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false)
  408. /// or just picking an address for SOLICIT that is not really
  409. /// allocated (true)<br/>
  410. /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A
  411. /// lease callouts will be executed if this parameter is passed.<br/>
  412. /// @ref ClientContext6::old_leases_ [out] Collection to which this function
  413. /// will append old leases. Leases are stored in the same order as in
  414. /// the collection of new leases, being returned. For newly allocated
  415. /// leases (not renewed) the NULL pointers are stored in this
  416. /// collection as old leases.<br/>
  417. /// @ref ClientContext6::hwaddr_ Hardware address (optional, may be null if
  418. /// not available)<br/>
  419. /// @ref ClientContext6::host_ Host reservation. allocateLeases6 will set
  420. /// this field, if appropriate reservation is found.
  421. ///
  422. /// @return Allocated IPv6 leases (may be empty if allocation failed)
  423. Lease6Collection
  424. allocateLeases6(ClientContext6& ctx);
  425. /// @brief Renews existing DHCPv6 leases for a given IA.
  426. ///
  427. /// This method updates the leases associated with a specified IA container.
  428. /// It will extend the leases under normal circumstances, but sometimes
  429. /// there may be reasons why not to do so. Such a reasons may be:
  430. /// - client attempts to renew an address that is not valid
  431. /// - client attempts to renew an address that is now reserved for someone
  432. /// else (see host reservation)
  433. /// - client's leases does not match his reservations
  434. ///
  435. /// This method will call the lease6_renew callout.
  436. ///
  437. /// @param ctx Message processing context. It holds various information
  438. /// extracted from the client's message and required to allocate a lease.
  439. /// In particular, @ref ClientContext6::hints_ provides list of addresses or
  440. /// prefixes the client had sent. @ref ClientContext6::old_leases_ will
  441. /// contain removed leases in this case.
  442. ///
  443. /// @return Returns renewed lease.
  444. Lease6Collection renewLeases6(ClientContext6& ctx);
  445. /// @brief Attempts to find appropriate host reservation.
  446. ///
  447. /// Attempts to find appropriate host reservation in HostMgr. If found, it
  448. /// will be set in ctx.host_.
  449. /// @param ctx Client context that contains all necessary information.
  450. void findReservation(ClientContext6& ctx) const;
  451. private:
  452. /// @brief creates a lease and inserts it in LeaseMgr if necessary
  453. ///
  454. /// Creates a lease based on specified parameters and tries to insert it
  455. /// into the database. That may fail in some cases, i.e. when there is another
  456. /// allocation process and we lost a race to a specific lease.
  457. ///
  458. /// @param ctx client context that passes all necessary information. See
  459. /// @ref ClientContext6 for details.
  460. /// @param addr an address that was selected and is confirmed to be
  461. /// available
  462. /// @param prefix_len length of the prefix (for PD only)
  463. /// should be 128 for other lease types
  464. ///
  465. /// The following fields of the ctx structure are used:
  466. /// @ref ClientContext6::subnet_ subnet the lease is allocated from
  467. /// @ref ClientContext6::duid_ client's DUID
  468. /// @ref ClientContext6::iaid_ IAID from the IA_NA container the client sent to us
  469. /// @ref ClientContext6::type_ lease type (IA, TA or PD)
  470. /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates that server takes
  471. /// responsibility for the forward DNS Update for this lease
  472. /// (if true).
  473. /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates that server takes
  474. /// responsibility for the reverse DNS Update for this lease
  475. /// (if true).
  476. /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.
  477. /// @ref ClientContext6::hwaddr_ Hardware address (optional, may be null for Lease6)
  478. /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A lease callouts
  479. /// will be executed if this parameter is passed (and there are callouts
  480. /// registered)
  481. /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false) or just picking
  482. /// an address for SOLICIT that is not really allocated (true)
  483. /// @return allocated lease (or NULL in the unlikely case of the lease just
  484. /// became unavailable)
  485. Lease6Ptr createLease6(ClientContext6& ctx,
  486. const isc::asiolink::IOAddress& addr,
  487. const uint8_t prefix_len);
  488. /// @brief Allocates a normal, in-pool, unreserved lease from the pool.
  489. ///
  490. /// It attempts to pick a hint first, then uses allocator iteratively until
  491. /// an available (not used, not reserved) lease is found. In principle, it
  492. /// may return more than one lease, but we currently handle only one.
  493. /// This may change in the future.
  494. ///
  495. /// @param ctx client context that contains all details (subnet, client-id, etc.)
  496. /// @return collection of newly allocated leases
  497. Lease6Collection allocateUnreservedLeases6(ClientContext6& ctx);
  498. /// @brief Creates new leases based on reservations.
  499. ///
  500. /// This method allocates new leases, based on host reservation. Existing
  501. /// leases are specified in existing_leases parameter. A new lease is not created,
  502. /// if there is a lease for specified address on existing_leases list or there is
  503. /// a lease used by someone else.
  504. ///
  505. /// @param ctx client context that contains all details (subnet, client-id, etc.)
  506. /// @param existing_leases leases that are already associated with the client
  507. void
  508. allocateReservedLeases6(ClientContext6& ctx, Lease6Collection& existing_leases);
  509. /// @brief Removes leases that are reserved for someone else.
  510. ///
  511. /// Goes through the list specified in existing_leases and removes those that
  512. /// are reserved by someone else. The removed leases are added to the
  513. /// ctx.removed_leases_ collection.
  514. ///
  515. /// @param ctx client context that contains all details (subnet, client-id, etc.)
  516. /// @param existing_leases [in/out] leases that should be checked
  517. void
  518. removeNonmatchingReservedLeases6(ClientContext6& ctx,
  519. Lease6Collection& existing_leases);
  520. /// @brief Removed leases that are not reserved for this client
  521. ///
  522. /// This method iterates over existing_leases and will remove leases that are
  523. /// not reserved for this client. It will leave at least one lease on the list,
  524. /// if possible. The reason to run this method is that if there is a reservation
  525. /// for address A for client X and client X already has a lease for a
  526. /// different address B, we should assign A and release B. However,
  527. /// if for some reason we can't assign A, keeping B would be better than
  528. /// not having a lease at all. Hence we may keep B if that's the only lease
  529. /// left.
  530. ///
  531. /// @param ctx client context that contains all details (subnet, client-id, etc.)
  532. /// @param existing_leases [in/out] leases that should be checked
  533. void
  534. removeNonreservedLeases6(ClientContext6& ctx,
  535. Lease6Collection& existing_leases);
  536. /// @brief Reuses expired IPv6 lease
  537. ///
  538. /// Updates existing expired lease with new information. Lease database
  539. /// is updated if this is real (i.e. REQUEST, fake_allocation = false), not
  540. /// dummy allocation request (i.e. SOLICIT, fake_allocation = true).
  541. ///
  542. /// @param expired old, expired lease
  543. /// @param ctx client context that contains all details.
  544. /// @param prefix_len prefix length (for PD leases)
  545. /// Should be 128 for other lease types
  546. ///
  547. /// The following parameters are used from the ctx structure:
  548. /// @ref ClientContext6::subnet_ subnet the lease is allocated from
  549. /// @ref ClientContext6::duid_ client's DUID
  550. /// @ref ClientContext6::iaid_ IAID from the IA_NA container the client sent to us
  551. /// @ref ClientContext6::fwd_dns_update_ A boolean value which indicates that server takes
  552. /// responsibility for the forward DNS Update for this lease
  553. /// (if true).
  554. /// @ref ClientContext6::rev_dns_update_ A boolean value which indicates that server takes
  555. /// responsibility for the reverse DNS Update for this lease
  556. /// (if true).
  557. /// @ref ClientContext6::hostname_ A fully qualified domain-name of the client.
  558. /// @ref ClientContext6::callout_handle_ a callout handle (used in hooks). A
  559. /// lease callouts will be executed if this parameter is passed.
  560. /// @ref ClientContext6::fake_allocation_ is this real i.e. REQUEST (false)
  561. /// or just picking an address for SOLICIT that is not really
  562. /// allocated (true)
  563. ///
  564. /// @return refreshed lease
  565. /// @throw BadValue if trying to recycle lease that is still valid
  566. Lease6Ptr reuseExpiredLease(Lease6Ptr& expired,
  567. ClientContext6& ctx,
  568. uint8_t prefix_len);
  569. /// @brief Updates FQDN data for a collection of leases.
  570. ///
  571. /// @param ctx IPv6 client context (old versions of the leases that had
  572. /// FQDN data changed will be stored in ctx.changed_leases_,
  573. /// ctx.fwd_dns_update, ctx.rev_dns_update, ctx.hostname_
  574. /// and ctx.fake_allocation_ will be used.
  575. /// @param leases Collection of leases for which FQDN data should be
  576. /// updated.
  577. ///
  578. /// @return Collection of leases with updated FQDN data. Note that returned
  579. /// collection holds updated FQDN data even for fake allocation.
  580. Lease6Collection updateFqdnData(ClientContext6& ctx,
  581. const Lease6Collection& leases);
  582. /// @brief Utility function that removes all leases with a specified address
  583. /// @param container A collection of Lease6 pointers
  584. /// @param addr address to be removed
  585. /// @return true if removed (false otherwise)
  586. static bool
  587. removeLeases(Lease6Collection& container,
  588. const asiolink::IOAddress& addr);
  589. /// @brief Extends specified IPv6 lease
  590. ///
  591. /// This method attempts to extend the lease. It will call the lease6_renew
  592. /// or lease6_rebind hooks (depending on the client's message specified in
  593. /// ctx.query). The lease will be extended in LeaseMgr, unless the hooks
  594. /// library will set the skip flag.
  595. ///
  596. /// @param ctx client context that passes all necessary information. See
  597. /// @ref ClientContext6 for details.
  598. /// @param lease IPv6 lease to be extended.
  599. void extendLease6(ClientContext6& ctx, Lease6Ptr lease);
  600. public:
  601. /// @brief Context information for the DHCPv4 lease allocation.
  602. ///
  603. /// This structure holds a set of information provided by the DHCPv4
  604. /// server to the allocation engine. In particular, it holds the
  605. /// client identifying information, such as HW address or client
  606. /// identifier. It also holds the information about the subnet that
  607. /// the client is connected to.
  608. ///
  609. /// This structure is also used to pass some information from
  610. /// the allocation engine back to the server, i.e. the old lease
  611. /// which the client had before the allocation.
  612. ///
  613. /// This structure is meant to be extended in the future, if more
  614. /// information should be passed to the allocation engine. Note
  615. /// that the big advantage of using the context structure to pass
  616. /// information to the allocation engine methods is that adding
  617. /// new information doesn't modify the API of the allocation engine.
  618. struct ClientContext4 {
  619. /// @brief Subnet selected for the client by the server.
  620. Subnet4Ptr subnet_;
  621. /// @brief Client identifier from the DHCP message.
  622. ClientIdPtr clientid_;
  623. /// @brief HW address from the DHCP message.
  624. HWAddrPtr hwaddr_;
  625. /// @brief An address that the client desires.
  626. ///
  627. /// If this address is set to 0 it indicates that this address
  628. /// is unspecified.
  629. asiolink::IOAddress requested_address_;
  630. /// @brief Perform forward DNS update.
  631. bool fwd_dns_update_;
  632. /// @brief Perform reverse DNS update.
  633. bool rev_dns_update_;
  634. /// @brief Hostname.
  635. ///
  636. /// The server retrieves the hostname from the Client FQDN option,
  637. /// Hostname option or the host reservation record for the client.
  638. std::string hostname_;
  639. /// @brief Callout handle associated with the client's message.
  640. hooks::CalloutHandlePtr callout_handle_;
  641. /// @brief Indicates if this is a real or fake allocation.
  642. ///
  643. /// The real allocation is when the allocation engine is supposed
  644. /// to make an update in a lease database: create new lease, or
  645. /// update existing lease.
  646. bool fake_allocation_;
  647. /// @brief A pointer to an old lease that the client had before update.
  648. Lease4Ptr old_lease_;
  649. /// @brief A pointer to the object identifying host reservations.
  650. ConstHostPtr host_;
  651. /// @brief A pointer to the object representing a lease in conflict.
  652. ///
  653. /// This pointer is set by some of the allocation methods when
  654. /// the lease can't be allocated because there is another lease
  655. /// which is in conflict with this allocation.
  656. Lease4Ptr conflicting_lease_;
  657. /// @brief Default constructor.
  658. ClientContext4();
  659. /// @brief Constructor with parameters
  660. ///
  661. /// @param subnet subnet the allocation should come from (mandatory)
  662. /// @param clientid Client identifier (optional)
  663. /// @param hwaddr Client's hardware address info (mandatory)
  664. /// @param requested_addr A hint that the client provided (may be 0.0.0.0)
  665. /// @param fwd_dns_update Indicates whether forward DNS
  666. /// update will be performed for the client (true) or not (false).
  667. /// @param rev_dns_update Indicates whether reverse DNS
  668. /// update will be performed for the client (true) or not (false).
  669. /// @param hostname A string carrying hostname to be used for DNS updates.
  670. /// @param fake_allocation Is this real i.e. REQUEST (false)
  671. /// or just picking an address for DISCOVER that is not really
  672. /// allocated (true)
  673. ClientContext4(const Subnet4Ptr& subnet, const ClientIdPtr& clientid,
  674. const HWAddrPtr& hwaddr,
  675. const asiolink::IOAddress& requested_addr,
  676. const bool fwd_dns_update, const bool rev_dns_update,
  677. const std::string& hostname, const bool fake_allocation);
  678. /// @brief Check if the specified lease belongs to the client.
  679. ///
  680. /// This method compares the hardware address and the client id
  681. /// in the lease with the relevant values in the context. That
  682. /// way the method determines whether the lease belongs to the
  683. /// client which message the server is processing.
  684. ///
  685. /// @return true if the lease belongs to the client for which
  686. /// the context has been created, false otherwise.
  687. bool myLease(const Lease4& lease) const;
  688. /// @brief Check if the lease conflicts with the context.
  689. ///
  690. /// This method is used in cases when there is a lease in the lease database
  691. /// for the client and the server receives the message from another client
  692. /// which may be potentially using the same client identifier or HW address.
  693. ///
  694. /// Currently the allocation engine allows for allocating a lease for the
  695. /// client which is using the same HW address or client identifier as the
  696. /// client which already has a lease in the database. However, the value of
  697. /// one of the identifiers must be unique. In other words, two clients may
  698. /// have the same client identifier but different HW addresses and the
  699. /// leases can be allocated for both (there is no conflict).
  700. ///
  701. /// The other possible case is that one of the clients uses both HW address
  702. /// and client identifier, and another client is using only one of those
  703. /// and its value is the same as for the former client. The allocation
  704. /// engine treats it as a conflict because there is no unique value in the
  705. /// lease database by which the server could distinguish the clients.
  706. /// Hence, it doesn't allocate the lease from the context in conflict.
  707. ///
  708. /// This method detects the conflict described above.
  709. ///
  710. /// @param lease Existing lease to be checked.
  711. ///
  712. /// @return true if the lease is in conflict with the context, false
  713. /// otherwise.
  714. bool isInConflict(const Lease4& lease) const;
  715. };
  716. /// @brief Pointer to the @c ClientContext4.
  717. typedef boost::shared_ptr<ClientContext4> ClientContext4Ptr;
  718. /// @brief Returns IPv4 lease.
  719. ///
  720. /// This method finds a lease for a client using the following algorithm:
  721. /// - If a lease exists for the combination of the HW address or client id
  722. /// and a subnet, try to use this lease for the client. If the client
  723. /// has a reservation for an address for which the lease was created or
  724. /// the client desires to renew the lease for this address (ciaddr or
  725. /// requested IP address option), the server renews the lease for the
  726. /// client. If the client desires a different address or the server has
  727. /// a (potentially new) reservation for a different address for this
  728. /// client, the existing lease is replaced with a new lease.
  729. /// - If the client has no lease in the lease database the server will try
  730. /// to allocate a new lease. If the client has a reservation for the
  731. /// particular address or if it has specified a desired address the
  732. /// server will check if the particular address is not allocated to
  733. /// another client. If the address is available, the server will allocate
  734. /// this address for the client.
  735. /// - If the desired address is unavailable the server checks if the
  736. /// lease for this address has expired. If the lease is expired, the
  737. /// server will allocate this lease to the client. The relevant
  738. /// information will be updated, e.g. new client HW address, host name
  739. /// etc.
  740. /// - If the desired address is in use by another client, the server will
  741. /// try to allocate a different address. The server picks addresses from
  742. /// a dynamic pool and checks if the address is available and that
  743. /// it is not reserved for another client. If it is in use by another
  744. /// client or if it is reserved for another client, the address is not
  745. /// allocated. The server picks the next address and repeats this check.
  746. /// Note that the server ceases allocation after the configured number
  747. /// of unsuccessful attempts.
  748. ///
  749. /// The lease allocation process is slightly different for the
  750. /// DHCPDISCOVER and DHCPREQUEST messages. In the former case, the client
  751. /// may specify the requested IP address option with a desired address and
  752. /// the server treats this address as a hint. This means that the server may
  753. /// allocate a different address at its discretion and send it to the
  754. /// client in the DHCPOFFER. If the client accepts this offer it specifies
  755. /// this address in the requested IP address option in the DHCPREQUEST.
  756. /// At this point, the allocation engine will use the requested IP address
  757. /// as a hard requirement and if this address can't be allocated for
  758. /// any reason, the allocation engine returns NULL lease. As a result,
  759. /// the DHCP server sends a DHCPNAK to the client and the client
  760. /// falls back to the DHCP server discovery.
  761. ///
  762. /// The only exception from this rule is when the client doesn't specify
  763. /// a requested IP address option (invalid behavior) in which case the
  764. /// allocation engine will try to allocate any address.
  765. ///
  766. /// If there is an address reservation specified for the particular client
  767. /// the reserved address always takes precedence over addresses from the
  768. /// dynamic pool or even an address currently allocated for this client.
  769. ///
  770. /// It is possible that the address reserved for the particular client
  771. /// is in use by another client, e.g. as a result of pools reconfiguration.
  772. /// In this case, when the client requests allocation of the reserved
  773. /// address and the server determines that it is leased to someone else,
  774. /// the allocation engine allocates a different address for this client.
  775. ///
  776. /// When the client having a lease returns to renew, the allocation engine
  777. /// doesn't extend the lease for it and returns a NULL pointer. The client
  778. /// falls back to the 4-way exchange and a different lease is allocated.
  779. /// At this point, the reserved address is freed and can be allocated to
  780. /// the client which holds this reservation. However, this client has a
  781. /// lease for a different address at this time. When the client renews its
  782. /// lease it receives the DHCPNAK and falls back to the DHCP server
  783. /// discovery and obtains the lease for the reserved address.
  784. ///
  785. /// When a server should do DNS updates, it is required that allocation
  786. /// returns the information about how the lease was obtained by the allocation
  787. /// engine. In particular, the DHCP server should be able to check whether
  788. /// an existing lease was returned, or a new lease was allocated. When an
  789. /// existing lease was returned, the server should check whether the FQDN has
  790. /// changed between the allocation of the old and new lease. If so, the server
  791. /// should perform the appropriate DNS update. If not, the server may choose
  792. /// to not perform the update. The information about the old lease is returned via
  793. /// @c old_lease parameter. If NULL value is returned, it is an indication
  794. /// that a new lease was allocated for the client. If non-NULL value is
  795. /// returned, it is an indication that allocation engine reused/renewed an
  796. /// existing lease.
  797. ///
  798. /// @param ctx client context that passes all necessary information. See
  799. /// @ref ClientContext4 for details.
  800. ///
  801. /// The following fields of @ref ClientContext4 are used:
  802. ///
  803. /// - @ref ClientContext4::subnet_ subnet the allocation should come from
  804. /// - @ref ClientContext4::clientid_ Client identifier
  805. /// - @ref ClientContext4::hwaddr_ Client's hardware address info
  806. /// - @ref ClientContext4::requested_address_ A hint that the client provided
  807. /// - @ref ClientContext4::fwd_dns_update_ Indicates whether forward DNS
  808. /// update will be performed for the client (true) or not (false).
  809. /// - @ref ClientContext4::rev_dns_update_ Indicates whether reverse DNS
  810. /// update will be performed for the client (true) or not (false).
  811. /// - @ref ClientContext4::hostname_ A string carrying hostname to be used for
  812. /// DNS updates.
  813. /// - @ref ClientContext4::fake_allocation_ Is this real i.e. REQUEST (false)
  814. /// or just picking an address for DISCOVER that is not really
  815. /// allocated (true)
  816. /// - @ref ClientContext4::host_ Pointer to the object representing the
  817. // static reservations (host reservations) for the client.
  818. /// - @ref ClientContext4::callout_handle_ A callout handle (used in hooks).
  819. /// A lease callouts will be executed if this parameter is passed.
  820. /// - @ref ClientContext4::old_lease_ [out] Holds the pointer to a previous
  821. /// instance of a lease. The NULL pointer indicates that lease didn't
  822. /// exist prior to calling this function (e.g. new lease has been allocated).
  823. ///
  824. /// @return Allocated IPv4 lease (or NULL if allocation failed).
  825. Lease4Ptr allocateLease4(ClientContext4& ctx);
  826. /// @brief Attempts to find the host reservation for the client.
  827. ///
  828. /// This method attempts to find the host reservation for the client. If
  829. /// found, it is set in the @c ctx.host_. If the host reservations are
  830. /// disabled for the particular subnet or the reservation is not found
  831. /// for the client, the @c ctx.host_ is set to NULL.
  832. ///
  833. /// @param ctx Client context holding various information about the client.
  834. static void findReservation(ClientContext4& ctx);
  835. private:
  836. /// @brief Offers the lease.
  837. ///
  838. /// This method is called by the @c AllocEngine::allocateLease4 when
  839. /// the server is processing a DHCPDISCOVER message, i.e. the fake
  840. /// allocation case.
  841. ///
  842. /// This method doesn't modify leases in the lease database. It finds
  843. /// the most suitable lease for the client and returns it to the caller.
  844. /// The server uses this lease when it sends the DHCPOFFER to the
  845. /// client from which it has received a DHCPDISCOVER message.
  846. ///
  847. /// The lease is found using the following algorithm:
  848. /// -# If there is a reservation for the client, try to use the reserved
  849. /// address. This may fail if the particular address is in use by
  850. /// another client. In such case:
  851. /// -# If the client has a lease, try to offer this lease. This may fail
  852. /// if it turns out that this address is reserved for another client
  853. /// or the address doesn't belong to the address pool. In such case:
  854. /// -# Try to allocate the address provided by the client as a hint.
  855. /// This may fail if the address is in use or is reserved by some
  856. /// other client. In such case:
  857. /// -# Try to offer an address from the dynamic pool.
  858. ///
  859. /// @throw various exceptions if the allocation goes wrong.
  860. ///
  861. /// @param ctx Client context holding the data extracted from the
  862. /// client's message.
  863. ///
  864. /// @return A pointer to the offered lease, or NULL if no suitable lease
  865. /// has been found.
  866. Lease4Ptr discoverLease4(ClientContext4& ctx);
  867. /// @brief Allocates the lease.
  868. ///
  869. /// This method is called by the @c AllocEngine::allocateLease4 when
  870. /// the server is processing a DHCPREQUEST message, i.e. the real
  871. /// allocation case.
  872. ///
  873. /// This method modifies the lease information in the lease database.
  874. /// It adds new leases, modifies existing leases or deletes them.
  875. ///
  876. /// The method returns NULL to indicate that the lease allocation
  877. /// has failed when any of the following occur:
  878. /// -# The requested address is specified but is reserved for another
  879. /// client.
  880. /// -# The requested address is in use by another client.
  881. /// -# There is a reservation for the particular client, the
  882. /// reserved address is not in use by another client and the
  883. /// requested address is different than the reserved address.
  884. /// -# There is no reservation for the client and the requested address
  885. /// is not in the dynamic pool.
  886. ///
  887. /// If none of the above occurs, the method will try to allocate the
  888. /// lease for the client using the following algorithm:
  889. /// -# If the client has a lease and the client is requesting the
  890. /// address for which it has a lease, renew its lease.
  891. /// -# If the client is requesting a different address than that for
  892. /// which it has a lease, try to allocate the requested address.
  893. /// This may fail if the address is in use by another client.
  894. /// -# If the client is not requesting any specific address, allocate
  895. /// the address from the dynamic pool.
  896. ///
  897. /// @throws various exceptions if the allocation goes wrong.
  898. ///
  899. /// @param ctx Client context holding the data extracted from the
  900. /// client's message.
  901. ///
  902. /// @return A pointer to the allocated lease, or NULL if no suitable
  903. /// lease could be allocated.
  904. Lease4Ptr requestLease4(ClientContext4& ctx);
  905. /// @brief Creates a lease and inserts it in LeaseMgr if necessary
  906. ///
  907. /// Creates a lease based on specified parameters and tries to insert it
  908. /// into the database. That may fail in some cases, e.g. when there is another
  909. /// allocation process and we lost a race to a specific lease.
  910. ///
  911. /// @param ctx client context that contains additional parameters.
  912. /// @param addr An address that was selected and is confirmed to be available
  913. ///
  914. /// In particular, the following fields from Client context are used:
  915. /// - @ref ClientContext4::subnet_ Subnet the lease is allocated from
  916. /// - @ref ClientContext4::clientid_ Client identifier
  917. /// - @ref ClientContext4::hwaddr_ Client's hardware address
  918. /// - @ref ClientContext4::fwd_dns_update_ Indicates whether forward DNS update
  919. /// will be performed for the client (true) or not (false).
  920. /// - @ref ClientContext4::rev_dns_update_ Indicates whether reverse DNS update
  921. /// will be performed for the client (true) or not (false).
  922. /// - @ref ClientContext4::hostname_ A string carrying hostname to be used for
  923. /// DNS updates.
  924. /// - @ref ClientContext4::callout_handle_ a callout handle (used in hooks).
  925. /// A lease callouts will be executed if this parameter is passed
  926. /// (and there are callouts registered)
  927. /// - @ref ClientContext4::fake_allocation_ Is this real i.e. REQUEST (false)
  928. /// or just picking an address for DISCOVER that is not really
  929. /// allocated (true)
  930. /// @return allocated lease (or NULL in the unlikely case of the lease just
  931. /// becomed unavailable)
  932. Lease4Ptr createLease4(const ClientContext4& ctx,
  933. const isc::asiolink::IOAddress& addr);
  934. /// @brief Renews a DHCPv4 lease.
  935. ///
  936. /// This method updates the lease with the information from the provided
  937. /// context and invokes the lease4_renew callout.
  938. ///
  939. /// The address of the lease being renewed is NOT updated.
  940. ///
  941. /// @param lease A lease to be renewed.
  942. /// @param ctx Message processing context. It holds various information
  943. /// extracted from the client's message and required to allocate a lease.
  944. ///
  945. /// @return Returns renewed lease. Note that the lease is only updated when
  946. /// it is an actual allocation (not processing a DHCPDISCOVER message).
  947. Lease4Ptr renewLease4(const Lease4Ptr& lease, ClientContext4& ctx);
  948. /// @brief Reuses expired DHCPv4 lease.
  949. ///
  950. /// Makes a new allocation using an expired lease. The lease is updated with
  951. /// the information from the provided context. Typically, an expired lease
  952. /// which belonged to one client may be assigned to another client
  953. /// which asked for the specific address.
  954. ///
  955. /// @param expired An old, expired lease.
  956. /// @param ctx Message processing context. It holds various information
  957. /// extracted from the client's message and required to allocate a lease.
  958. ///
  959. /// @return Updated lease instance.
  960. /// @throw BadValue if trying to reuse a lease which is still valid or
  961. /// when the provided parameters are invalid.
  962. Lease4Ptr reuseExpiredLease4(Lease4Ptr& expired, ClientContext4& ctx);
  963. /// @brief Allocates the lease by replacing an existing lease.
  964. ///
  965. /// This method checks if the lease database contains the lease for
  966. /// the specified address. If the lease exists and has expired, it
  967. /// reuses the expired lease. If the lease doesn't exist, it creates
  968. /// the new lease.
  969. ///
  970. /// @param address Requested address for which the lease should be
  971. /// allocted.
  972. /// @param ctx Client context holding the data extracted from the
  973. /// client's message.
  974. ///
  975. /// @return A pointer to the allocated lease or NULL if the allocation
  976. /// was not successful.
  977. Lease4Ptr allocateOrReuseLease4(const asiolink::IOAddress& address,
  978. ClientContext4& ctx);
  979. /// @brief Allocates the lease from the dynamic pool.
  980. ///
  981. /// This method allocates the lease from the dynamic pool. It uses
  982. /// one of the allocators to pick addresses from the pool and if the
  983. /// address appears to be available, it allocates the new lease
  984. /// using this address. The number of attempts depends on the size
  985. /// of the dynamic pool. If all of the addresses in the pool have
  986. /// been tried and all of them appeared to be in use, the allocation
  987. /// fails. This is the case when the pool is exhausted.
  988. ///
  989. /// The time required to find a suitable lease depends on the current
  990. /// pool utilization.
  991. ///
  992. /// @param ctx Client context holding the data extracted from the
  993. /// client's message.
  994. ///
  995. /// @return A pointer to the allocated lease or NULL if the allocation
  996. /// was not successful.
  997. Lease4Ptr allocateUnreservedLease4(ClientContext4& ctx);
  998. /// @brief Updates the specified lease with the information from a context.
  999. ///
  1000. /// The context, specified as an argument to this method, holds various
  1001. /// information gathered from the client's message and passed to the
  1002. /// allocation engine. The allocation engine uses this information to make
  1003. /// lease allocation decisions. Some public methods of the allocation engine
  1004. /// requires updating the lease information with the data gathered from the
  1005. /// context, e.g. @c AllocEngine::reuseExpiredLease requires updating the
  1006. /// expired lease with fresh information from the context to create a
  1007. /// lease to be held for the client.
  1008. ///
  1009. /// Note that this doesn't update the lease address.
  1010. ///
  1011. /// @warning This method doesn't check if the pointer to the lease is
  1012. /// valid nor if the subnet to the pointer in the @c ctx is valid.
  1013. /// The caller is responsible for making sure that they are valid.
  1014. ///
  1015. /// @param [out] lease A pointer to the lease to be updated.
  1016. /// @param ctx A context containing information from the server about the
  1017. /// client and its message.
  1018. void updateLease4Information(const Lease4Ptr& lease,
  1019. ClientContext4& ctx) const;
  1020. };
  1021. /// @brief A pointer to the @c AllocEngine object.
  1022. typedef boost::shared_ptr<AllocEngine> AllocEnginePtr;
  1023. }; // namespace isc::dhcp
  1024. }; // namespace isc
  1025. #endif // ALLOC_ENGINE_H