dhcp4_srv.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. // Copyright (C) 2011-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 DHCPV4_SRV_H
  15. #define DHCPV4_SRV_H
  16. #include <dhcp/dhcp4.h>
  17. #include <dhcp/pkt4.h>
  18. #include <dhcp/option.h>
  19. #include <dhcp/option_string.h>
  20. #include <dhcp/option4_client_fqdn.h>
  21. #include <dhcp/option_custom.h>
  22. #include <dhcp_ddns/ncr_msg.h>
  23. #include <dhcpsrv/d2_client_mgr.h>
  24. #include <dhcpsrv/subnet.h>
  25. #include <dhcpsrv/alloc_engine.h>
  26. #include <hooks/callout_handle.h>
  27. #include <dhcpsrv/daemon.h>
  28. #include <boost/noncopyable.hpp>
  29. #include <iostream>
  30. #include <queue>
  31. namespace isc {
  32. namespace dhcp {
  33. /// @brief Exception thrown when DHCID computation failed.
  34. class DhcidComputeError : public isc::Exception {
  35. public:
  36. DhcidComputeError(const char* file, size_t line, const char* what) :
  37. isc::Exception(file, line, what) { };
  38. };
  39. /// @brief DHCPv4 message exchange.
  40. ///
  41. /// This class represents the DHCPv4 message exchange. The message exchange
  42. /// consists of the single client message, server response to this message
  43. /// and the mechanisms to generate the server's response. The server creates
  44. /// the instance of the @c Dhcpv4Exchange for each inbound message that it
  45. /// accepts for processing.
  46. ///
  47. /// The use of the @c Dhcpv4Exchange object as a central repository of
  48. /// information about the message exchange simplifies the API of the
  49. /// @c Dhcpv4Srv class.
  50. ///
  51. /// Another benefit of using this class is that different methods of the
  52. /// @c Dhcpv4Srv may share information. For example, the constructor of this
  53. /// class selects the subnet and multiple methods of @c Dhcpv4Srv use this
  54. /// subnet, without the need to select it again.
  55. ///
  56. /// @todo This is the initial version of this class. In the future a lot of
  57. /// code from the @c Dhcpv4Srv class will be migrated here.
  58. class Dhcpv4Exchange {
  59. public:
  60. /// @brief Constructor.
  61. ///
  62. /// The constructor selects the subnet for the query and checks for the
  63. /// static host reservations for the client which has sent the message.
  64. /// The information about the reservations is stored in the
  65. /// @c AllocEngine::ClientContext4 object, which can be obtained by
  66. /// calling the @c getContext.
  67. ///
  68. /// @param alloc_engine Pointer to the instance of the Allocation Engine
  69. /// used by the server.
  70. /// @param query Pointer to the client message.
  71. /// @param subnet Pointer to the subnet to which the client belongs.
  72. Dhcpv4Exchange(const AllocEnginePtr& alloc_engine, const Pkt4Ptr& query,
  73. const Subnet4Ptr& subnet);
  74. /// @brief Initializes the instance of the response message.
  75. ///
  76. /// The type of the response depends on the type of the query message.
  77. /// For the DHCPDISCOVER the DHCPOFFER is created. For the DHCPREQUEST
  78. /// and DHCPINFORM the DHCPACK is created. For the DHCPRELEASE the
  79. /// response is not initialized.
  80. void initResponse();
  81. /// @brief Returns the pointer to the query from the client.
  82. Pkt4Ptr getQuery() const {
  83. return (query_);
  84. }
  85. /// @brief Returns the pointer to the server's response.
  86. ///
  87. /// The returned pointer is NULL if the query type is DHCPRELEASE or DHCPDECLINE.
  88. Pkt4Ptr getResponse() const {
  89. return (resp_);
  90. }
  91. /// @brief Removes the response message by resetting the pointer to NULL.
  92. void deleteResponse() {
  93. resp_.reset();
  94. }
  95. /// @brief Returns the copy of the context for the Allocation engine.
  96. AllocEngine::ClientContext4Ptr getContext() const {
  97. return (context_);
  98. }
  99. private:
  100. /// @brief Copies default parameters from client's to server's message
  101. ///
  102. /// Some fields are copied from client's message into server's response,
  103. /// e.g. client HW address, number of hops, transaction-id etc.
  104. ///
  105. /// @warning This message is called internally by @c initResponse and
  106. /// thus it doesn't check if the resp_ value has been initialized. The
  107. /// calling method is responsible for making sure that @c resp_ is
  108. /// not NULL.
  109. void copyDefaultFields();
  110. /// @brief Pointer to the allocation engine used by the server.
  111. AllocEnginePtr alloc_engine_;
  112. /// @brief Pointer to the DHCPv4 message sent by the client.
  113. Pkt4Ptr query_;
  114. /// @brief Pointer to the DHCPv4 message to be sent to the client.
  115. Pkt4Ptr resp_;
  116. /// @brief Context for use with allocation engine.
  117. AllocEngine::ClientContext4Ptr context_;
  118. };
  119. /// @brief Type representing the pointer to the @c Dhcpv4Exchange.
  120. typedef boost::shared_ptr<Dhcpv4Exchange> Dhcpv4ExchangePtr;
  121. /// @brief DHCPv4 server service.
  122. ///
  123. /// This singleton class represents DHCPv4 server. It contains all
  124. /// top-level methods and routines necessary for server operation.
  125. /// In particular, it instantiates IfaceMgr, loads or generates DUID
  126. /// that is going to be used as server-identifier, receives incoming
  127. /// packets, processes them, manages leases assignment and generates
  128. /// appropriate responses.
  129. ///
  130. /// This class does not support any controlling mechanisms directly.
  131. /// See the derived \ref ControlledDhcpv4Srv class for support for
  132. /// command and configuration updates over msgq.
  133. ///
  134. /// For detailed explanation or relations between main(), ControlledDhcpv4Srv,
  135. /// Dhcpv4Srv and other classes, see \ref dhcpv4Session.
  136. class Dhcpv4Srv : public Daemon {
  137. public:
  138. /// @brief defines if certain option may, must or must not appear
  139. typedef enum {
  140. FORBIDDEN,
  141. MANDATORY,
  142. OPTIONAL
  143. } RequirementLevel;
  144. /// @brief Default constructor.
  145. ///
  146. /// Instantiates necessary services, required to run DHCPv4 server.
  147. /// In particular, creates IfaceMgr that will be responsible for
  148. /// network interaction. Will instantiate lease manager, and load
  149. /// old or create new DUID. It is possible to specify alternate
  150. /// port on which DHCPv4 server will listen on. That is mostly useful
  151. /// for testing purposes. The Last two arguments of the constructor
  152. /// should be left at default values for normal server operation.
  153. /// They should be set to 'false' when creating an instance of this
  154. /// class for unit testing because features they enable require
  155. /// root privileges.
  156. ///
  157. /// @param port specifies port number to listen on
  158. /// @param use_bcast configure sockets to support broadcast messages.
  159. /// @param direct_response_desired specifies if it is desired to
  160. /// use direct V4 traffic.
  161. Dhcpv4Srv(uint16_t port = DHCP4_SERVER_PORT,
  162. const bool use_bcast = true,
  163. const bool direct_response_desired = true);
  164. /// @brief Destructor. Used during DHCPv4 service shutdown.
  165. virtual ~Dhcpv4Srv();
  166. /// @brief Main server processing loop.
  167. ///
  168. /// Main server processing loop. Receives incoming packets, verifies
  169. /// their correctness, generates appropriate answer (if needed) and
  170. /// transmits responses.
  171. ///
  172. /// @return true, if being shut down gracefully, fail if experienced
  173. /// critical error.
  174. bool run();
  175. /// @brief Instructs the server to shut down.
  176. void shutdown();
  177. /// @brief Return textual type of packet received by server
  178. ///
  179. /// Returns the name of valid packet received by the server (e.g. DISCOVER).
  180. /// If the packet is unknown - or if it is a valid DHCP packet but not one
  181. /// expected to be received by the server (such as an OFFER), the string
  182. /// "UNKNOWN" is returned. This method is used in debug messages.
  183. ///
  184. /// As the operation of the method does not depend on any server state, it
  185. /// is declared static.
  186. ///
  187. /// @todo: This should be named static Pkt4::getName()
  188. ///
  189. /// @param type DHCPv4 packet type
  190. ///
  191. /// @return Pointer to "const" string containing the packet name.
  192. /// Note that this string is statically allocated and MUST NOT
  193. /// be freed by the caller.
  194. static const char* serverReceivedPacketName(uint8_t type);
  195. ///
  196. /// @name Public accessors returning values required to (re)open sockets.
  197. ///
  198. //@{
  199. ///
  200. /// @brief Get UDP port on which server should listen.
  201. ///
  202. /// Typically, server listens on UDP port number 67. Other ports are used
  203. /// for testing purposes only.
  204. ///
  205. /// @return UDP port on which server should listen.
  206. uint16_t getPort() const {
  207. return (port_);
  208. }
  209. /// @brief Return bool value indicating that broadcast flags should be set
  210. /// on sockets.
  211. ///
  212. /// @return A bool value indicating that broadcast should be used (if true).
  213. bool useBroadcast() const {
  214. return (use_bcast_);
  215. }
  216. //@}
  217. /// @brief Starts DHCP_DDNS client IO if DDNS updates are enabled.
  218. ///
  219. /// If updates are enabled, it Instructs the D2ClientMgr singleton to
  220. /// enter send mode. If D2ClientMgr encounters errors it may throw
  221. /// D2ClientErrors. This method does not catch exceptions.
  222. void startD2();
  223. /// @brief Implements the error handler for DHCP_DDNS IO errors
  224. ///
  225. /// Invoked when a NameChangeRequest send to kea-dhcp-ddns completes with
  226. /// a failed status. These are communications errors, not data related
  227. /// failures.
  228. ///
  229. /// This method logs the failure and then suspends all further updates.
  230. /// Updating can only be restored by reconfiguration or restarting the
  231. /// server. There is currently no retry logic so the first IO error that
  232. /// occurs will suspend updates.
  233. /// @todo We may wish to make this more robust or sophisticated.
  234. ///
  235. /// @param result Result code of the send operation.
  236. /// @param ncr NameChangeRequest which failed to send.
  237. virtual void d2ClientErrorHandler(const dhcp_ddns::
  238. NameChangeSender::Result result,
  239. dhcp_ddns::NameChangeRequestPtr& ncr);
  240. protected:
  241. /// @name Functions filtering and sanity-checking received messages.
  242. ///
  243. /// @todo These functions are supposed to be moved to a new class which
  244. /// will manage different rules for accepting and rejecting messages.
  245. /// Perhaps ticket #3116 is a good opportunity to do it.
  246. ///
  247. //@{
  248. /// @brief Checks whether received message should be processed or discarded.
  249. ///
  250. /// This function checks whether received message should be processed or
  251. /// discarded. It should be called on the beginning of message processing
  252. /// (just after the message has been decoded). This message calls a number
  253. /// of other functions which check whether message should be processed,
  254. /// using different criteria.
  255. ///
  256. /// This function should be extended when new criteria for accepting
  257. /// received message have to be implemented. This function is meant to
  258. /// aggregate all early filtering checks on the received message. By having
  259. /// a single function like this, we are avoiding bloat of the server's main
  260. /// loop.
  261. ///
  262. /// @warning This function should remain exception safe.
  263. ///
  264. /// @param query Received message.
  265. ///
  266. /// @return true if the message should be further processed, or false if
  267. /// the message should be discarded.
  268. bool accept(const Pkt4Ptr& query) const;
  269. /// @brief Check if a message sent by directly connected client should be
  270. /// accepted or discarded.
  271. ///
  272. /// This function checks if the received message is from directly connected
  273. /// client. If it is, it checks that it should be processed or discarded.
  274. ///
  275. /// Note that this function doesn't validate all addresses being carried in
  276. /// the message. The primary purpose of this function is to filter out
  277. /// direct messages in the local network for which there is no suitable
  278. /// subnet configured. For example, this function accepts unicast messages
  279. /// because unicasts may be used by clients located in remote networks to
  280. /// to renew existing leases. If their notion of address is wrong, the
  281. /// server will have to sent a NAK, instead of dropping the message.
  282. /// Detailed validation of such messages is performed at later stage of
  283. /// processing.
  284. ///
  285. /// This function accepts the following messages:
  286. /// - all valid relayed messages,
  287. /// - all unicast messages,
  288. /// - all broadcast messages except DHCPINFORM received on the interface
  289. /// for which the suitable subnet exists (is configured).
  290. /// - all DHCPINFORM messages with source address or ciaddr set.
  291. ///
  292. /// @param query Message sent by a client.
  293. ///
  294. /// @return true if message is accepted for further processing, false
  295. /// otherwise.
  296. bool acceptDirectRequest(const Pkt4Ptr& query) const;
  297. /// @brief Check if received message type is valid for the server to
  298. /// process.
  299. ///
  300. /// This function checks that the received message type belongs to
  301. /// the range of types recognized by the server and that the
  302. /// message of this type should be processed by the server.
  303. ///
  304. /// The messages types accepted for processing are:
  305. /// - Discover
  306. /// - Request
  307. /// - Release
  308. /// - Decline
  309. /// - Inform
  310. ///
  311. /// @param query Message sent by a client.
  312. ///
  313. /// @return true if message is accepted for further processing, false
  314. /// otherwise.
  315. bool acceptMessageType(const Pkt4Ptr& query) const;
  316. /// @brief Verifies if the server id belongs to our server.
  317. ///
  318. /// This function checks if the server identifier carried in the specified
  319. /// DHCPv4 message belongs to this server. If the server identifier option
  320. /// is absent or the value carried by this option is equal to one of the
  321. /// server identifiers used by the server, the true is returned. If the
  322. /// server identifier option is present, but it doesn't match any server
  323. /// identifier used by this server, the false value is returned.
  324. ///
  325. /// @param pkt DHCPv4 message which server identifier is to be checked.
  326. ///
  327. /// @return true, if the server identifier is absent or matches one of the
  328. /// server identifiers that the server is using; false otherwise.
  329. bool acceptServerId(const Pkt4Ptr& pkt) const;
  330. //@}
  331. /// @brief Verifies if specified packet meets RFC requirements
  332. ///
  333. /// Checks if mandatory option is really there, that forbidden option
  334. /// is not there, and that client-id or server-id appears only once.
  335. ///
  336. /// @param query Pointer to the client's message.
  337. /// @param serverid expectation regarding server-id option
  338. /// @throw RFCViolation if any issues are detected
  339. static void sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid);
  340. /// @brief Processes incoming DISCOVER and returns response.
  341. ///
  342. /// Processes received DISCOVER message and verifies that its sender
  343. /// should be served. In particular, a lease is selected and sent
  344. /// as an offer to a client if it should be served.
  345. ///
  346. /// @param discover DISCOVER message received from client
  347. ///
  348. /// @return OFFER message or NULL
  349. Pkt4Ptr processDiscover(Pkt4Ptr& discover);
  350. /// @brief Processes incoming REQUEST and returns REPLY response.
  351. ///
  352. /// Processes incoming REQUEST message and verifies that its sender
  353. /// should be served. In particular, verifies that requested lease
  354. /// is valid, not expired, not reserved, not used by other client and
  355. /// that requesting client is allowed to use it.
  356. ///
  357. /// Returns ACK message, NAK message, or NULL
  358. ///
  359. /// @param request a message received from client
  360. ///
  361. /// @return ACK or NAK message
  362. Pkt4Ptr processRequest(Pkt4Ptr& request);
  363. /// @brief Stub function that will handle incoming RELEASE messages.
  364. ///
  365. /// In DHCPv4, server does not respond to RELEASE messages, therefore
  366. /// this function does not return anything.
  367. ///
  368. /// @param release message received from client
  369. void processRelease(Pkt4Ptr& release);
  370. /// @brief Stub function that will handle incoming DHCPDECLINE messages.
  371. ///
  372. /// @param decline message received from client
  373. void processDecline(Pkt4Ptr& decline);
  374. /// @brief Stub function that will handle incoming INFORM messages.
  375. ///
  376. /// @param inform message received from client
  377. Pkt4Ptr processInform(Pkt4Ptr& inform);
  378. /// @brief Appends options requested by client.
  379. ///
  380. /// This method assigns options that were requested by client
  381. /// (sent in PRL) or are enforced by server.
  382. ///
  383. /// @param ex The exchange holding both the client's message and the
  384. /// server's response.
  385. void appendRequestedOptions(Dhcpv4Exchange& ex);
  386. /// @brief Appends requested vendor options as requested by client.
  387. ///
  388. /// This method is similar to \ref appendRequestedOptions(), but uses
  389. /// vendor options. The major difference is that vendor-options use
  390. /// its own option spaces (there may be more than one distinct set of vendor
  391. /// options, each with unique vendor-id). Vendor options are requested
  392. /// using separate options within their respective vendor-option spaces.
  393. ///
  394. /// @param ex The exchange holding both the client's message and the
  395. /// server's response.
  396. void appendRequestedVendorOptions(Dhcpv4Exchange& ex);
  397. /// @brief Assigns a lease and appends corresponding options
  398. ///
  399. /// This method chooses the most appropriate lease for requesting
  400. /// client and assigning it. Options corresponding to the lease
  401. /// are added to specific message.
  402. ///
  403. /// This method may reset the pointer to the response in the @c ex object
  404. /// to indicate that the response should not be sent to the client.
  405. /// The caller must check if the response is is null after calling
  406. /// this method.
  407. ///
  408. /// The response type in the @c ex object may be set to DHCPACK or DHCPNAK.
  409. ///
  410. /// @param ex DHCPv4 exchange holding the client's message to be checked.
  411. void assignLease(Dhcpv4Exchange& ex);
  412. /// @brief Append basic options if they are not present.
  413. ///
  414. /// This function adds the following basic options if they
  415. /// are not yet added to the response message:
  416. /// - Subnet Mask,
  417. /// - Router,
  418. /// - Name Server,
  419. /// - Domain Name.
  420. ///
  421. /// @param ex DHCPv4 exchange holding the client's message to be checked.
  422. void appendBasicOptions(Dhcpv4Exchange& ex);
  423. /// @brief Processes Client FQDN and Hostname Options sent by a client.
  424. ///
  425. /// Client may send Client FQDN or Hostname option to communicate its name
  426. /// to the server. Server may use this name to perform DNS update for the
  427. /// lease being assigned to a client. If server takes responsibility for
  428. /// updating DNS for a client it may communicate it by sending the Client
  429. /// FQDN or Hostname %Option back to the client. Server select a different
  430. /// name than requested by a client to update DNS. In such case, the server
  431. /// stores this different name in its response.
  432. ///
  433. /// Client should not send both Client FQDN and Hostname options. However,
  434. /// if client sends both options, server should prefer Client FQDN option
  435. /// and ignore the Hostname option. If Client FQDN option is not present,
  436. /// the Hostname option is processed.
  437. ///
  438. /// The Client FQDN %Option is processed by this function as described in
  439. /// RFC4702.
  440. ///
  441. /// In response to a Hostname %Option sent by a client, the server may send
  442. /// Hostname option with the same or different hostname. If different
  443. /// hostname is sent, it is an indication to the client that server has
  444. /// overridden the client's preferred name and will rather use this
  445. /// different name to update DNS. However, since Hostname option doesn't
  446. /// carry an information whether DNS update will be carried by the server
  447. /// or not, the client is responsible for checking whether DNS update
  448. /// has been performed.
  449. ///
  450. /// After successful processing options stored in the first parameter,
  451. /// this function may add Client FQDN or Hostname option to the response
  452. /// message. In some cases, server may cease to add any options to the
  453. /// response, i.e. when server doesn't support DNS updates.
  454. ///
  455. /// This function does not throw. It simply logs the debug message if the
  456. /// processing of the FQDN or Hostname failed.
  457. ///
  458. /// @param ex The exchange holding both the client's message and the
  459. /// server's response.
  460. void processClientName(Dhcpv4Exchange& ex);
  461. /// @brief this is a prefix added to the contend of vendor-class option
  462. ///
  463. /// If incoming packet has a vendor class option, its content is
  464. /// prepended with this prefix and then interpreted as a class.
  465. /// For example, a packet that sends vendor class with value of "FOO"
  466. /// will cause the packet to be assigned to class VENDOR_CLASS_FOO.
  467. static const std::string VENDOR_CLASS_PREFIX;
  468. private:
  469. /// @brief Process Client FQDN %Option sent by a client.
  470. ///
  471. /// This function is called by the @c Dhcpv4Srv::processClientName when
  472. /// the client has sent the FQDN option in its message to the server.
  473. /// It comprises the actual logic to parse the FQDN option and prepare
  474. /// the FQDN option to be sent back to the client in the server's
  475. /// response.
  476. ///
  477. /// @param ex The exchange holding both the client's message and the
  478. /// server's response.
  479. void processClientFqdnOption(Dhcpv4Exchange& ex);
  480. /// @brief Process Hostname %Option sent by a client.
  481. ///
  482. /// This function is called by the @c Dhcpv4Srv::processClientName when
  483. /// the client has sent the Hostname option in its message to the server.
  484. /// It comprises the actual logic to parse the Hostname option and
  485. /// prepare the Hostname option to be sent back to the client in the
  486. /// server's response.
  487. ///
  488. /// @param ex The exchange holding both the client's message and the
  489. /// server's response.
  490. void processHostnameOption(Dhcpv4Exchange& ex);
  491. protected:
  492. /// @brief Creates NameChangeRequests which correspond to the lease
  493. /// which has been acquired.
  494. ///
  495. /// If this function is called when an existing lease is renewed, it
  496. /// may generate NameChangeRequest to remove existing DNS entries which
  497. /// correspond to the old lease instance. This function may cease to
  498. /// generate NameChangeRequests if the notion of the client's FQDN hasn't
  499. /// changed between an old and new lease.
  500. ///
  501. /// @param lease A pointer to the new lease which has been acquired.
  502. /// @param old_lease A pointer to the instance of the old lease which has
  503. /// been replaced by the new lease passed in the first argument. The NULL
  504. /// value indicates that the new lease has been allocated, rather than
  505. /// lease being renewed.
  506. void createNameChangeRequests(const Lease4Ptr& lease,
  507. const Lease4Ptr& old_lease);
  508. /// @brief Creates the NameChangeRequest and adds to the queue for
  509. /// processing.
  510. ///
  511. /// This creates the @c isc::dhcp_ddns::NameChangeRequest; emits a
  512. /// the debug message which indicates whether the request being added is
  513. /// to remove DNS entry or add a new entry; and then sends the request
  514. /// to the D2ClientMgr for transmission to kea-dhcp-ddns.
  515. ///
  516. /// @param chg_type A type of the NameChangeRequest (ADD or REMOVE).
  517. /// @param lease A lease for which the NameChangeRequest is created and
  518. /// queued.
  519. void queueNameChangeRequest(const isc::dhcp_ddns::NameChangeType chg_type,
  520. const Lease4Ptr& lease);
  521. /// @brief Attempts to renew received addresses
  522. ///
  523. /// Attempts to renew existing lease. This typically includes finding a lease that
  524. /// corresponds to the received address. If no such lease is found, a status code
  525. /// response is generated.
  526. ///
  527. /// @param renew client's message asking for renew
  528. /// @param reply server's response (ACK or NAK)
  529. void renewLease(const Pkt4Ptr& renew, Pkt4Ptr& reply);
  530. /// @brief Adds server identifier option to the server's response.
  531. ///
  532. /// This method adds a server identifier to the DHCPv4 message. It expects
  533. /// that the local (source) address is set for this message. If address is
  534. /// not set, it will throw an exception. This method also expects that the
  535. /// server identifier option is not present in the specified message.
  536. /// Otherwise, it will throw an exception on attempt to add a duplicate
  537. /// server identifier option.
  538. ///
  539. /// @note This method doesn't throw exceptions by itself but the underlying
  540. /// classes being used my throw. The reason for this method to not sanity
  541. /// check the specified message is that it is meant to be called internally
  542. /// by the @c Dhcpv4Srv class.
  543. ///
  544. /// @note This method is static because it is not dependent on the class
  545. /// state.
  546. ///
  547. /// @param ex The exchange holding both the client's message and the
  548. /// server's response.
  549. static void appendServerID(Dhcpv4Exchange& ex);
  550. /// @brief Set IP/UDP and interface parameters for the DHCPv4 response.
  551. ///
  552. /// This method sets the following parameters for the DHCPv4 message being
  553. /// sent to a client:
  554. /// - client unicast or a broadcast address,
  555. /// - client or relay port,
  556. /// - server address,
  557. /// - server port,
  558. /// - name and index of the interface which is to be used to send the
  559. /// message.
  560. ///
  561. /// Internally it calls the @c Dhcpv4Srv::adjustRemoteAddr to figure
  562. /// out the destination address (client unicast address or broadcast
  563. /// address).
  564. ///
  565. /// The destination port is always DHCPv4 client (68) or relay (67) port,
  566. /// depending if the response will be sent directly to a client.
  567. ///
  568. /// The source port is always set to DHCPv4 server port (67).
  569. ///
  570. /// The interface selected for the response is always the same as the
  571. /// one through which the query has been received.
  572. ///
  573. /// The source address for the response is the IPv4 address assigned to
  574. /// the interface being used to send the response. This function uses
  575. /// @c IfaceMgr to get the socket bound to the IPv4 address on the
  576. /// particular interface.
  577. ///
  578. /// @note This method is static because it is not dependent on the class
  579. /// state.
  580. ///
  581. /// @param ex The exchange holding both the client's message and the
  582. /// server's response.
  583. static void adjustIfaceData(Dhcpv4Exchange& ex);
  584. /// @brief Sets remote addresses for outgoing packet.
  585. ///
  586. /// This method sets the local and remote addresses on outgoing packet.
  587. /// The addresses being set depend on the following conditions:
  588. /// - has incoming packet been relayed,
  589. /// - is direct response to a client without address supported,
  590. /// - type of the outgoing packet,
  591. /// - broadcast flag set in the incoming packet.
  592. ///
  593. /// @warning This method does not check whether provided packet pointers
  594. /// are valid. Make sure that pointers are correct before calling this
  595. /// function.
  596. ///
  597. /// @note This method is static because it is not dependent on the class
  598. /// state.
  599. ///
  600. /// @param ex The exchange holding both the client's message and the
  601. /// server's response.
  602. static void adjustRemoteAddr(Dhcpv4Exchange& ex);
  603. /// @brief converts server-id to text
  604. /// Converts content of server-id option to a text representation, e.g.
  605. /// "192.0.2.1"
  606. ///
  607. /// @param opt option that contains server-id
  608. /// @return string representation
  609. static std::string srvidToString(const OptionPtr& opt);
  610. /// @brief Computes DHCID from a lease.
  611. ///
  612. /// This method creates an object which represents DHCID. The DHCID value
  613. /// is computed as described in RFC4701. The section 3.3. of RFC4701
  614. /// specifies the DHCID RR Identifier Type codes:
  615. /// - 0x0000 The 1 octet htype followed by glen octets of chaddr
  616. /// - 0x0001 The data octets from the DHCPv4 client's Client Identifier
  617. /// option.
  618. /// - 0x0002 The client's DUID.
  619. ///
  620. /// Currently this function supports first two of these identifiers.
  621. /// The 0x0001 is preferred over the 0x0000 - if the client identifier
  622. /// option is present, the former is used. If the client identifier
  623. /// is absent, the latter is used.
  624. ///
  625. /// @todo Implement support for 0x0002 DHCID identifier type.
  626. ///
  627. /// @param lease A pointer to the structure describing a lease.
  628. /// @return An object encapsulating DHCID to be used for DNS updates.
  629. /// @throw DhcidComputeError If the computation of the DHCID failed.
  630. static isc::dhcp_ddns::D2Dhcid computeDhcid(const Lease4Ptr& lease);
  631. /// @brief Selects a subnet for a given client's packet.
  632. ///
  633. /// @param query client's message
  634. /// @return selected subnet (or NULL if no suitable subnet was found)
  635. isc::dhcp::Subnet4Ptr selectSubnet(const Pkt4Ptr& query) const;
  636. /// indicates if shutdown is in progress. Setting it to true will
  637. /// initiate server shutdown procedure.
  638. volatile bool shutdown_;
  639. /// @brief dummy wrapper around IfaceMgr::receive4
  640. ///
  641. /// This method is useful for testing purposes, where its replacement
  642. /// simulates reception of a packet. For that purpose it is protected.
  643. virtual Pkt4Ptr receivePacket(int timeout);
  644. /// @brief dummy wrapper around IfaceMgr::send()
  645. ///
  646. /// This method is useful for testing purposes, where its replacement
  647. /// simulates transmission of a packet. For that purpose it is protected.
  648. virtual void sendPacket(const Pkt4Ptr& pkt);
  649. /// @brief Implements a callback function to parse options in the message.
  650. ///
  651. /// @param buf a A buffer holding options in on-wire format.
  652. /// @param option_space A name of the option space which holds definitions
  653. /// of to be used to parse options in the packets.
  654. /// @param [out] options A reference to the collection where parsed options
  655. /// will be stored.
  656. /// @return An offset to the first byte after last parsed option.
  657. size_t unpackOptions(const OptionBuffer& buf,
  658. const std::string& option_space,
  659. isc::dhcp::OptionCollection& options);
  660. /// @brief Assigns incoming packet to zero or more classes.
  661. ///
  662. /// @note For now, the client classification is very simple. It just uses
  663. /// content of the vendor-class-identifier option as a class. The resulting
  664. /// class will be stored in packet (see @ref isc::dhcp::Pkt4::classes_ and
  665. /// @ref isc::dhcp::Pkt4::inClass).
  666. ///
  667. /// @param pkt packet to be classified
  668. void classifyPacket(const Pkt4Ptr& pkt);
  669. /// @brief Performs packet processing specific to a class
  670. ///
  671. /// If the selected subnet, query or response in the @c ex object is NULL
  672. /// this method returns immediately and returns true.
  673. ///
  674. /// @note This processing is a likely candidate to be pushed into hooks.
  675. ///
  676. /// @param ex The exchange holding both the client's message and the
  677. /// server's response.
  678. /// @return true if successful, false otherwise (will prevent sending response)
  679. bool classSpecificProcessing(const Dhcpv4Exchange& ex);
  680. /// @brief Allocation Engine.
  681. /// Pointer to the allocation engine that we are currently using
  682. /// It must be a pointer, because we will support changing engines
  683. /// during normal operation (e.g. to use different allocators)
  684. boost::shared_ptr<AllocEngine> alloc_engine_;
  685. private:
  686. /// @brief Constructs netmask option based on subnet4
  687. /// @param subnet subnet for which the netmask will be calculated
  688. ///
  689. /// @return Option that contains netmask information
  690. static OptionPtr getNetmaskOption(const Subnet4Ptr& subnet);
  691. /// @brief Implements the error handler for socket open failure.
  692. ///
  693. /// This callback function is installed on the @c isc::dhcp::IfaceMgr
  694. /// when IPv4 sockets are being open. When socket fails to open for
  695. /// any reason, this function is called. It simply logs the error message.
  696. ///
  697. /// @param errmsg An error message containing a cause of the failure.
  698. static void ifaceMgrSocket4ErrorHandler(const std::string& errmsg);
  699. uint16_t port_; ///< UDP port number on which server listens.
  700. bool use_bcast_; ///< Should broadcast be enabled on sockets (if true).
  701. /// Indexes for registered hook points
  702. int hook_index_pkt4_receive_;
  703. int hook_index_subnet4_select_;
  704. int hook_index_pkt4_send_;
  705. };
  706. }; // namespace isc::dhcp
  707. }; // namespace isc
  708. #endif // DHCP4_SRV_H