dhcp6_client.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. // Copyright (C) 2014 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 DHCP6_CLIENT_H
  15. #define DHCP6_CLIENT_H
  16. #include <asiolink/io_address.h>
  17. #include <dhcp/duid.h>
  18. #include <dhcp/option.h>
  19. #include <dhcp6/tests/dhcp6_test_utils.h>
  20. #include <boost/noncopyable.hpp>
  21. #include <boost/shared_ptr.hpp>
  22. namespace isc {
  23. namespace dhcp {
  24. namespace test {
  25. /// @brief DHCPv6 client used for unit testing.
  26. ///
  27. /// This class implements a DHCPv6 "client" which interoperates with the
  28. /// @c NakedDhcpv6Srv class. It calls @c NakedDhcpv6Srv::fakeRecive to
  29. /// deliver client messages to the server for processing. The server places
  30. /// the response in the @c NakedDhcpv6Srv::fake_sent_ container. The client
  31. /// pops messages from this container which simulates reception of the
  32. /// response from the server.
  33. ///
  34. /// The client maintains the leases it acquired from the server. If it has
  35. /// acquired the lease as a result of SARR exchange, it will use this lease
  36. /// when the Rebind process is triggered by the unit test.
  37. ///
  38. /// The client exposes a set of functions which simulate different exchange
  39. /// types between the client and the server. It also provides the access to
  40. /// the objects encapsulating responses from the server so as it is possible
  41. /// to verify from the unit test that the server's response is correct.
  42. ///
  43. /// @todo This class has been implemented to simplify the structure of the
  44. /// unit test and to make unit tests code self-explanatory. Currently,
  45. /// this class is mostly used by the unit tests which test Rebind processing
  46. /// logic. At some point we may want to use this class to test some other
  47. /// message types, e.g. Renew, in which case it may need to be extended.
  48. /// Also, once we implement the support for multiple IAAddr and IAPrefix
  49. /// options within single IA, the logic which maintains leases will have
  50. /// to be extended to support it.
  51. class Dhcp6Client : public boost::noncopyable {
  52. public:
  53. /// @brief Holds an information about single lease.
  54. struct LeaseInfo {
  55. /// @brief A structure describing the lease.
  56. Lease6 lease_;
  57. /// @brief Holds the last status code that server has sent for
  58. /// the particular lease.
  59. uint16_t status_code_;
  60. /// @brief Default constructor for the structure.
  61. LeaseInfo() :
  62. lease_(), status_code_(0) { }
  63. };
  64. /// @brief Holds the current client configuration obtained from the
  65. /// server over DHCP.
  66. ///
  67. /// Currently it simply contains the collection of leases acquired.
  68. struct Configuration {
  69. std::vector<LeaseInfo> leases_;
  70. };
  71. /// @brief Holds the DHCPv6 messages taking part in transaction between
  72. /// the client and the server.
  73. struct Context {
  74. /// @brief Holds the last sent message from the client to the server.
  75. Pkt6Ptr query_;
  76. /// @brief Holds the last sent message by the server to the client.
  77. Pkt6Ptr response_;
  78. };
  79. /// @brief Creates a new client.
  80. ///
  81. /// This constructor initializes the class members to default values:
  82. /// - relay link-addr = 3000:1::1
  83. /// - first transaction id = 0
  84. /// - dest-addr = All_DHCP_Relay_Agents_and_Servers
  85. /// - duid (LLT) = <random 4 bytes>00010203040506
  86. /// - link-local-addr = fe80::3a60:77ff:fed5:cdef
  87. /// - IA_NA not requested
  88. /// - IA_PD not requested
  89. /// - not relayed
  90. Dhcp6Client();
  91. /// @brief Creates a new client that communicates with a specified server.
  92. ///
  93. /// This constructor allows passing a pointer to the server object which
  94. /// should be used in a test. The server may be preconfigured before passed
  95. /// to the constructor. The default configuration used by the client is:
  96. /// - relay link-addr = 3000:1::1
  97. /// - first transaction id = 0
  98. /// - dest-addr = All_DHCP_Relay_Agents_and_Servers
  99. /// - duid (LLT) = <random 4 bytes>00010203040506
  100. /// - link-local-addr = fe80::3a60:77ff:fed5:cdef
  101. /// - IA_NA not requested
  102. /// - IA_PD not requested
  103. /// - not relayed
  104. ///
  105. /// @param srv Object representing server under test.
  106. Dhcp6Client(boost::shared_ptr<isc::test::NakedDhcpv6Srv>& srv);
  107. /// @brief Performs a 4-way echange between the client and the server.
  108. ///
  109. /// If the 4-way exchange is successful, the client should acquire leases
  110. /// according to the server's current configuration and the type of leases
  111. /// that have been requested (IA_NA, IA_PD).
  112. ///
  113. /// The leases acquired are accessible through the @c config_ member.
  114. ///
  115. /// @throw This function doesn't throw exceptions on its own, but it calls
  116. /// functions that are not exception safe, so it may throw exceptions if
  117. /// error occurs.
  118. ///
  119. /// @todo Perform sanity checks on returned messages.
  120. void doSARR();
  121. /// @brief Send Solicit and receive Advertise.
  122. ///
  123. /// This function simulates the first transaction of the 4-way exchange,
  124. /// i.e. sends a Solicit to the server and receives Advertise. It doesn't
  125. /// set the lease configuration in the @c config_.
  126. ///
  127. /// @throw This function doesn't throw exceptions on its own, but it calls
  128. /// functions that are not exception safe, so it may throw exceptions if
  129. /// error occurs.
  130. ///
  131. /// @todo Perform sanity checks on returned messages.
  132. void doSolicit();
  133. /// @brief Sends a Rebind to the server and receives the Reply.
  134. ///
  135. /// This function simulates sending the Rebind message to the server and
  136. /// receiving server's response (if any). The client uses existing leases
  137. /// (either address or prefixes) and places them in the Rebind message.
  138. /// If the server responds to the Rebind (and extends the lease lifetimes)
  139. /// the current lease configuration is updated.
  140. ///
  141. /// @throw This function doesn't throw exceptions on its own, but it calls
  142. /// functions that are not exception safe, so it may throw exceptions if
  143. /// error occurs.
  144. ///
  145. /// @todo Perform sanity checks on returned messages.
  146. void doRebind();
  147. /// @brief Sends Request to the server and receives Reply.
  148. ///
  149. /// This function simulates sending the Request message to the server and
  150. /// receiving server's response (if any). The client copies IA options
  151. /// from the current context (server's Advertise) to request acquisition
  152. /// of offered IAs. If the server responds to the Request (leases are
  153. /// acquired) the client's lease configuration is updated.
  154. ///
  155. /// @throw This function doesn't throw exceptions on its own, but it calls
  156. /// functions that are not exception safe, so it may throw exceptions if
  157. /// error occurs.
  158. ///
  159. /// @todo Perform sanity checks on returned messages.
  160. void doRequest();
  161. /// @brief Simulates aging of leases by the specified number of seconds.
  162. ///
  163. /// This function moves back the time of acquired leases by the specified
  164. /// number of seconds. It is useful for checking whether the particular
  165. /// lease has been later updated (e.g. as a result of Rebind) as it is
  166. /// expected that the fresh lease has cltt set to "now" (not to the time
  167. /// in the past).
  168. void fastFwdTime(const uint32_t secs);
  169. /// @brief Returns DUID option used by the client.
  170. OptionPtr getClientId() const;
  171. /// @brief Returns current context.
  172. const Context& getContext() const {
  173. return (context_);
  174. }
  175. /// @brief Returns lease at specified index.
  176. ///
  177. /// @warning This method doesn't check if the specified index is out of
  178. /// range. The caller is responsible for using a correct offset by
  179. /// invoking the @c getLeaseNum function.
  180. ///
  181. /// @param at Index of the lease held by the client.
  182. /// @return A lease at the specified index.
  183. Lease6 getLease(const size_t at) const {
  184. return (config_.leases_[at].lease_);
  185. }
  186. /// @brief Returns status code set by the server for the lease.
  187. ///
  188. /// @warning This method doesn't check if the specified index is out of
  189. /// range. The caller is responsible for using a correct offset by
  190. /// invoking the @c getLeaseNum function.
  191. ///
  192. /// @param at Index of the lease held by the client.
  193. /// @return A status code for the lease at the specified index.
  194. uint16_t getStatusCode(const size_t at) const {
  195. return (config_.leases_[at].status_code_);
  196. }
  197. /// @brief Returns number of acquired leases.
  198. size_t getLeaseNum() const {
  199. return (config_.leases_.size());
  200. }
  201. /// @brief Returns the server that the client is communicating with.
  202. boost::shared_ptr<isc::test::NakedDhcpv6Srv> getServer() const {
  203. return (srv_);
  204. }
  205. /// @brief Modifies the client's DUID (adds one to it).
  206. ///
  207. /// The DUID should be modified to test negative scenarios when the client
  208. /// acquires a lease and tries to renew it with a different DUID. The server
  209. /// should detect the DUID mismatch and react accordingly.
  210. ///
  211. /// The DUID modification affects the value returned by the
  212. /// @c Dhcp6Client::getClientId
  213. void modifyDUID();
  214. /// @brief Sets destination address for the messages being sent by the
  215. /// client.
  216. ///
  217. /// By default, the client uses All_DHCP_Relay_Agents_and_Servers
  218. /// multicast address to communicate with the server. In certain cases
  219. /// it ay be desired that different address is used (e.g. unicast in Renew).
  220. /// This function sets the new address for all future exchanges with the
  221. /// server.
  222. ///
  223. /// @param dest_addr New destination address.
  224. void setDestAddress(const asiolink::IOAddress& dest_addr) {
  225. dest_addr_ = dest_addr;
  226. }
  227. /// @brief Place IA_NA options to request address assignment.
  228. ///
  229. /// This function configures the client to place IA_NA options in its
  230. /// Solicit messages to request the IPv6 address assignment.
  231. ///
  232. /// @param use Parameter which 'true' value indicates that client should
  233. /// request address assignment.
  234. void useNA(const bool use = true) {
  235. use_na_ = use;
  236. }
  237. /// @brief Place IA_PD options to request prefix assignment.
  238. ///
  239. /// This function configures the client to place IA_PD options in its
  240. /// Solicit messages to request the IPv6 address assignment.
  241. ///
  242. /// @param use Parameter which 'true' value indicates that client should
  243. /// request prefix assignment.
  244. void usePD(const bool use = true) {
  245. use_pd_ = use;
  246. }
  247. /// @brief Simulate sending messages through a relay.
  248. ///
  249. /// @param use Parameter which 'true' value indicates that client should
  250. /// simulate sending messages via relay.
  251. /// @param link_addr Relay link-addr.
  252. void useRelay(const bool use = true,
  253. const asiolink::IOAddress& link_addr = asiolink::IOAddress("3000:1::1")) {
  254. use_relay_ = use;
  255. relay_link_addr_ = link_addr;
  256. }
  257. /// @brief Lease configuration obtained by the client.
  258. Configuration config_;
  259. /// @brief Link address of the relay to be used for relayed messages.
  260. asiolink::IOAddress relay_link_addr_;
  261. private:
  262. /// @brief Applies the new leases for the client.
  263. ///
  264. /// This method is called when the client obtains a new configuration
  265. /// from the server in the Reply message. This function adds new leases
  266. /// or replaces existing ones, on the client's side. Client uses these
  267. /// leases in any later communication with the server when doing Renew
  268. /// or Rebind.
  269. ///
  270. /// @param reply Server response.
  271. ///
  272. /// @todo Currently this function supports one IAAddr or IAPrefix option
  273. /// within IA. We will need to extend it to support multiple options
  274. /// within a single IA once server supports that.
  275. void applyRcvdConfiguration(const Pkt6Ptr& reply);
  276. /// @brief Applies configuration for the single lease.
  277. ///
  278. /// This method is called by the @c Dhcp6Client::applyRcvdConfiguration for
  279. /// each individual lease.
  280. ///
  281. /// @param lease_info Structure holding new lease information.
  282. void applyLease(const LeaseInfo& lease_info);
  283. /// @brief Copy IA options from one message to another.
  284. ///
  285. /// This method copies IA_NA and IA_PD options from one message to another.
  286. /// It is useful when the client needs to construct the Request message
  287. /// using addresses and prefixes returned by the client in Advertise.
  288. ///
  289. /// @param source Message from which IA options will be copied.
  290. /// @param dest Message to which IA options will be copied.
  291. ///
  292. /// @todo Add support for IA_TA.
  293. void copyIAs(const Pkt6Ptr& source, const Pkt6Ptr& dest);
  294. /// @brief Creates IA options from existing configuration.
  295. ///
  296. /// This method iterates over existing leases that client acquired and
  297. /// places corresponding IA_NA or IA_PD options into a specified message.
  298. /// This is useful to construct Renew or Rebind message from the existing
  299. /// configuration that client has obtained using 4-way exchange.
  300. ///
  301. /// @param dest Message to which the IA options will be added.
  302. void copyIAsFromLeases(const Pkt6Ptr& dest) const;
  303. /// @brief Creates client's side DHCP message.
  304. ///
  305. /// @param msg_type Type of the message to be created.
  306. /// @return An instance of the message created.
  307. Pkt6Ptr createMsg(const uint8_t msg_type);
  308. /// @brief Generates DUID for the client.
  309. ///
  310. /// @param duid_type Type of the DUID. Currently, only LLT is accepted.
  311. /// @return Object encapsulating a DUID.
  312. DuidPtr generateDUID(DUID::DUIDType duid_type) const;
  313. /// @brief Simulates reception of the message from the server.
  314. ///
  315. /// @return Received message.
  316. Pkt6Ptr receiveOneMsg();
  317. /// @brief Simulates sending a message to the server.
  318. ///
  319. /// This function instantly triggers processing of the message by the
  320. /// server. The server's response can be gathered by invoking the
  321. /// @c receiveOneMsg function.
  322. ///
  323. /// @param msg Message to be sent.
  324. void sendMsg(const Pkt6Ptr& msg);
  325. /// @brief Current context (sent and received message).
  326. Context context_;
  327. /// @biref Current transaction id (altered on each send).
  328. uint32_t curr_transid_;
  329. /// @brief Currently use destination address.
  330. asiolink::IOAddress dest_addr_;
  331. /// @brief Currently used DUID.
  332. DuidPtr duid_;
  333. /// @brief Currently used link local address.
  334. asiolink::IOAddress link_local_;
  335. /// @brief Pointer to the server that the client is communicating with.
  336. boost::shared_ptr<isc::test::NakedDhcpv6Srv> srv_;
  337. bool use_na_; ///< Enable address assignment.
  338. bool use_pd_; ///< Enable prefix delegation.
  339. bool use_relay_; ///< Enable relaying messages to the server.
  340. };
  341. } // end of namespace isc::dhcp::test
  342. } // end of namespace isc::dhcp
  343. } // end of namespace isc
  344. #endif // DHCP6_CLIENT