dhcp6_client.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. // Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #ifndef DHCP6_CLIENT_H
  7. #define DHCP6_CLIENT_H
  8. #include <asiolink/io_address.h>
  9. #include <dhcp/duid.h>
  10. #include <dhcp/option.h>
  11. #include <dhcp/option6_client_fqdn.h>
  12. #include <dhcpsrv/lease.h>
  13. #include <dhcp6/tests/dhcp6_test_utils.h>
  14. #include <util/staged_value.h>
  15. #include <boost/noncopyable.hpp>
  16. #include <boost/shared_ptr.hpp>
  17. #include <list>
  18. #include <set>
  19. #include <vector>
  20. namespace isc {
  21. namespace dhcp {
  22. namespace test {
  23. /// @brief DHCPv6 client used for unit testing.
  24. ///
  25. /// This class implements a DHCPv6 "client" which interoperates with the
  26. /// @c NakedDhcpv6Srv class. It calls @c NakedDhcpv6Srv::fakeReceive to
  27. /// deliver client messages to the server for processing. The server places
  28. /// the response in the @c NakedDhcpv6Srv::fake_sent_ container. The client
  29. /// pops messages from this container which simulates reception of the
  30. /// response from the server.
  31. ///
  32. /// The client maintains the leases it acquired from the server. If it has
  33. /// acquired the lease as a result of SARR exchange, it will use this lease
  34. /// when the Rebind process is triggered by the unit test.
  35. ///
  36. /// The client exposes a set of functions which simulate different exchange
  37. /// types between the client and the server. It also provides the access to
  38. /// the objects encapsulating responses from the server so as it is possible
  39. /// to verify from the unit test that the server's response is correct.
  40. ///
  41. /// @todo This class has been implemented to simplify the structure of the
  42. /// unit test and to make unit tests code self-explanatory. Currently,
  43. /// this class is mostly used by the unit tests which test Rebind processing
  44. /// logic. At some point we may want to use this class to test some other
  45. /// message types, e.g. Renew, in which case it may need to be extended.
  46. /// Also, once we implement the support for multiple IAAddr and IAPrefix
  47. /// options within single IA, the logic which maintains leases will have
  48. /// to be extended to support it.
  49. class Dhcp6Client : public boost::noncopyable {
  50. public:
  51. /// @brief Holds an information about single lease.
  52. struct LeaseInfo {
  53. /// @brief A structure describing the lease.
  54. Lease6 lease_;
  55. /// @brief Holds the last status code that server has sent for
  56. /// the particular lease.
  57. uint16_t status_code_;
  58. /// @brief Default constructor for the structure.
  59. LeaseInfo() :
  60. lease_(), status_code_(0) { }
  61. /// @brief Constructor which sets the lease type.
  62. ///
  63. /// @param lease_type One of the D6O_IA_NA or D6O_IA_PD.
  64. LeaseInfo(const uint16_t lease_type) :
  65. lease_(), status_code_(0) {
  66. lease_.type_ = lease_type == D6O_IA_NA ? Lease::TYPE_NA :
  67. Lease::TYPE_PD;
  68. }
  69. };
  70. /// @brief Holds the current client configuration obtained from the
  71. /// server over DHCP.
  72. ///
  73. /// Currently it simply contains the collection of leases acquired
  74. /// and a list of options. Note: this is a simple copy of all
  75. /// non-IA options and often includes "protocol" options, like
  76. /// server-id and client-id.
  77. struct Configuration {
  78. /// @brief List of received leases
  79. std::vector<Lease6> leases_;
  80. /// @brief A map of IAID, status code tuples.
  81. std::map<uint32_t, uint16_t> status_codes_;
  82. /// @brief List of received options
  83. OptionCollection options_;
  84. /// @brief Status code received in the global option scope.
  85. uint16_t status_code_;
  86. /// @brief Indicates if the status code has been received in the
  87. /// last transaction.
  88. bool received_status_code_;
  89. /// @brief Constructor.
  90. Configuration() {
  91. clear();
  92. }
  93. /// @brief Clears configuration.
  94. void clear() {
  95. leases_.clear();
  96. status_codes_.clear();
  97. resetGlobalStatusCode();
  98. options_.clear();
  99. }
  100. /// @brief Clears global status code.
  101. ///
  102. /// This function should be called before the new message is received.
  103. void resetGlobalStatusCode() {
  104. status_code_ = 0;
  105. received_status_code_ = false;
  106. }
  107. /// @brief Finds an option with the specific code in the received
  108. /// configuration.
  109. ///
  110. /// @param code Option code.
  111. ///
  112. /// @return Pointer to the option if the option exists, or NULL if
  113. /// the option doesn't exist.
  114. OptionPtr findOption(const uint16_t code) const {
  115. std::multimap<unsigned int, OptionPtr>::const_iterator it = options_.find(code);
  116. if (it != options_.end()) {
  117. return (it->second);
  118. }
  119. return (OptionPtr());
  120. }
  121. };
  122. /// @brief Holds the DHCPv6 messages taking part in transaction between
  123. /// the client and the server.
  124. struct Context {
  125. /// @brief Holds the last sent message from the client to the server.
  126. Pkt6Ptr query_;
  127. /// @brief Holds the last sent message by the server to the client.
  128. Pkt6Ptr response_;
  129. };
  130. /// @brief Structure holding information to be placed in client's IA.
  131. struct ClientIA {
  132. Lease::Type type_; ///< IA type
  133. uint32_t iaid_; ///< IAID
  134. asiolink::IOAddress prefix_; ///< prefix or address
  135. uint8_t prefix_len_; ///< prefix length
  136. /// @brief Constructor.
  137. ///
  138. /// @param type IA type.
  139. /// @param iaid IAID.
  140. /// @param prefix Address or prefix.
  141. /// @param prefix_len Prefix length.
  142. ClientIA(const Lease::Type& type, const uint32_t iaid,
  143. const asiolink::IOAddress& prefix,
  144. const uint8_t prefix_len)
  145. : type_(type), iaid_(iaid), prefix_(prefix),
  146. prefix_len_(prefix_len) {
  147. }
  148. };
  149. /// @brief Creates a new client.
  150. ///
  151. /// This constructor initializes the class members to default values:
  152. /// - relay link-addr = 3000:1::1
  153. /// - first transaction id = 0
  154. /// - dest-addr = All_DHCP_Relay_Agents_and_Servers
  155. /// - duid (LLT) = <random 4 bytes>00010203040506
  156. /// - link-local-addr = fe80::3a60:77ff:fed5:cdef
  157. /// - IA_NA not requested
  158. /// - IA_PD not requested
  159. /// - not relayed
  160. Dhcp6Client();
  161. /// @brief Creates a new client that communicates with a specified server.
  162. ///
  163. /// This constructor allows passing a pointer to the server object which
  164. /// should be used in a test. The server may be preconfigured before passed
  165. /// to the constructor. The default configuration used by the client is:
  166. /// - relay link-addr = 3000:1::1
  167. /// - first transaction id = 0
  168. /// - dest-addr = All_DHCP_Relay_Agents_and_Servers
  169. /// - duid (LLT) = <random 4 bytes>00010203040506
  170. /// - link-local-addr = fe80::3a60:77ff:fed5:cdef
  171. /// - IA_NA not requested
  172. /// - IA_PD not requested
  173. /// - not relayed
  174. ///
  175. /// @param srv Object representing server under test.
  176. Dhcp6Client(boost::shared_ptr<isc::dhcp::test::NakedDhcpv6Srv>& srv);
  177. /// @brief Create lease for the client.
  178. ///
  179. /// This function creates new lease on the client side without contacting
  180. /// the server. This may be useful for the negative tests in which the
  181. /// client is supposed to send invalid addresses/prefixes to the server
  182. /// and expect certain responses.
  183. ///
  184. /// @param lease A lease to be applied for the client.
  185. void createLease(const Lease6& lease);
  186. /// @brief Performs a 4-way exchange between the client and the server.
  187. ///
  188. /// If the 4-way exchange is successful, the client should acquire leases
  189. /// according to the server's current configuration and the type of leases
  190. /// that have been requested (IA_NA, IA_PD).
  191. ///
  192. /// The leases acquired are accessible through the @c config_ member.
  193. ///
  194. /// @throw This function doesn't throw exceptions on its own, but it calls
  195. /// functions that are not exception safe, so it may throw exceptions if
  196. /// error occurs.
  197. ///
  198. /// @todo Perform sanity checks on returned messages.
  199. void doSARR();
  200. /// @brief Send Solicit and receive Advertise.
  201. ///
  202. /// This function simulates the first transaction of the 4-way exchange,
  203. /// i.e. sends a Solicit to the server and receives Advertise. It doesn't
  204. /// set the lease configuration in the @c config_.
  205. ///
  206. /// @param always_apply_config Apply received configuration even if the
  207. /// Advertise message is received. Default value is false.
  208. ///
  209. /// @throw This function doesn't throw exceptions on its own, but it calls
  210. /// functions that are not exception safe, so it may throw exceptions if
  211. /// error occurs.
  212. ///
  213. /// @todo Perform sanity checks on returned messages.
  214. void doSolicit(const bool always_apply_config = false);
  215. /// @brief Sends a Renew to the server and receives the Reply.
  216. ///
  217. /// This function simulates sending the Renew message to the server and
  218. /// receiving server's response (if any). The client uses existing leases
  219. /// (either address or prefixes) and places them in the Renew message.
  220. /// If the server responds to the Renew (and extends the lease lifetimes)
  221. /// the current lease configuration is updated.
  222. ///
  223. /// @throw This function doesn't throw exceptions on its own, but it calls
  224. /// functions that are not exception safe, so it may throw exceptions if
  225. /// error occurs.
  226. ///
  227. /// @todo Perform sanity checks on returned messages.
  228. void doRenew();
  229. /// @brief Sends a Rebind to the server and receives the Reply.
  230. ///
  231. /// This function simulates sending the Rebind message to the server and
  232. /// receiving server's response (if any). The client uses existing leases
  233. /// (either address or prefixes) and places them in the Rebind message.
  234. /// If the server responds to the Rebind (and extends the lease lifetimes)
  235. /// the current lease configuration is updated.
  236. ///
  237. /// @throw This function doesn't throw exceptions on its own, but it calls
  238. /// functions that are not exception safe, so it may throw exceptions if
  239. /// error occurs.
  240. ///
  241. /// @todo Perform sanity checks on returned messages.
  242. void doRebind();
  243. /// @brief Sends Request to the server and receives Reply.
  244. ///
  245. /// This function simulates sending the Request message to the server and
  246. /// receiving server's response (if any). The client copies IA options
  247. /// from the current context (server's Advertise) to request acquisition
  248. /// of offered IAs. If the server responds to the Request (leases are
  249. /// acquired) the client's lease configuration is updated.
  250. ///
  251. /// @throw This function doesn't throw exceptions on its own, but it calls
  252. /// functions that are not exception safe, so it may throw exceptions if
  253. /// error occurs.
  254. ///
  255. /// @todo Perform sanity checks on returned messages.
  256. void doRequest();
  257. /// @brief Sends Confirm to the server and receives Reply.
  258. ///
  259. /// This function simulates sending the Confirm message to the server and
  260. /// receiving server's response (if any).
  261. void doConfirm();
  262. /// @brief Sends Decline to the server and receives Reply.
  263. ///
  264. /// This function simulates sending the Decline message to the server and
  265. /// receiving the server's response.
  266. /// @param include_address should the address be included?
  267. void doDecline(const bool include_address = true);
  268. /// @brief Performs stateless (inf-request / reply) exchange.
  269. ///
  270. /// This function generates Information-request message, sends it
  271. /// to the server and then receives the reply. Contents of the Inf-Request
  272. /// are controlled by client_ias_, use_client_id_ and use_oro_
  273. /// fields. This method does not process the response in any specific
  274. /// way, just stores it.
  275. void doInfRequest();
  276. /// @brief Sends Release to the server.
  277. ///
  278. /// This function simulates sending the Release message to the server
  279. /// and receiving server's response.
  280. void doRelease();
  281. /// @brief Removes the stateful configuration obtained from the server.
  282. ///
  283. /// It removes all leases held by the client.
  284. void clearConfig() {
  285. config_.clear();
  286. }
  287. /// @brief Simulates aging of leases by the specified number of seconds.
  288. ///
  289. /// This function moves back the time of acquired leases by the specified
  290. /// number of seconds. It is useful for checking whether the particular
  291. /// lease has been later updated (e.g. as a result of Rebind) as it is
  292. /// expected that the fresh lease has cltt set to "now" (not to the time
  293. /// in the past).
  294. ///
  295. /// @param secs Number of seconds by which the time should be moved.
  296. /// @param update_server Indicates if the leases should be updated on the
  297. /// server.
  298. void fastFwdTime(const uint32_t secs, const bool update_server = false);
  299. /// @brief Returns DUID option used by the client.
  300. OptionPtr getClientId() const;
  301. /// @brief Returns current context.
  302. const Context& getContext() const {
  303. return (context_);
  304. }
  305. /// @brief Returns the collection of IAIDs held by the client.
  306. std::set<uint32_t> getIAIDs() const;
  307. /// @brief Returns lease at specified index.
  308. ///
  309. /// @warning This method doesn't check if the specified index is out of
  310. /// range. The caller is responsible for using a correct offset by
  311. /// invoking the @c getLeaseNum function.
  312. ///
  313. /// @param at Index of the lease held by the client.
  314. /// @return A lease at the specified index.
  315. Lease6 getLease(const size_t at) const {
  316. return (config_.leases_[at]);
  317. }
  318. /// @brief Returns collection of leases for specified IAID.
  319. ///
  320. /// @param iaid IAID for which the leases should be returned.
  321. ///
  322. /// @return Vector containing leases for the IAID.
  323. std::vector<Lease6> getLeasesByIAID(const uint32_t iaid) const;
  324. /// @brief Returns collection of leases by type.
  325. ///
  326. /// @param type Lease type: D6O_IA_NA or D6O_IA_PD.
  327. ///
  328. /// @return Vector containing leases of the specified type.
  329. std::vector<Lease6> getLeasesByType(const Lease::Type& lease_type) const;
  330. /// @brief Returns leases with non-zero lifetimes.
  331. std::vector<Lease6> getLeasesWithNonZeroLifetime() const;
  332. /// @brief Returns leases with zero lifetimes.
  333. std::vector<Lease6> getLeasesWithZeroLifetime() const;
  334. /// @brief Returns leases by lease address/prefix.
  335. ///
  336. /// @param address Leased address.
  337. ///
  338. /// @return Vector containing leases for the specified address.
  339. std::vector<Lease6>
  340. getLeasesByAddress(const asiolink::IOAddress& address) const;
  341. /// @brief Returns leases belonging to specified address range.
  342. ///
  343. /// @param first Lower bound of the address range.
  344. /// @param second Upper bound of the address range.
  345. ///
  346. /// @return Vector containing leases belonging to specified address range.
  347. std::vector<Lease6>
  348. getLeasesByAddressRange(const asiolink::IOAddress& first,
  349. const asiolink::IOAddress& second) const;
  350. /// @brief Returns leases belonging to prefix pool.
  351. ///
  352. /// @param prefix Prefix of the pool.
  353. /// @param prefix_len Prefix length.
  354. /// @param delegated_len Delegated prefix length.
  355. ///
  356. /// @return Vector containing leases belonging to specified prefix pool.
  357. std::vector<Lease6>
  358. getLeasesByPrefixPool(const asiolink::IOAddress& prefix,
  359. const uint8_t prefix_len,
  360. const uint8_t delegated_len) const;
  361. /// @brief Checks if client has lease for the specified address.
  362. ///
  363. /// @param address Address for which lease should be found.
  364. ///
  365. /// @return true if client has lease for the address, false otherwise.
  366. bool hasLeaseForAddress(const asiolink::IOAddress& address) const;
  367. /// @brief Checks if client has lease for the specified address in the
  368. /// IA_NA identified by IAID.
  369. ///
  370. /// @param address Address for which lease should be found.
  371. /// @param iaid IAID of the IA_NA in which the lease is expected.
  372. bool hasLeaseForAddress(const asiolink::IOAddress& address,
  373. const IAID& iaid) const;
  374. /// @brief Checks if client has a lease for an address within range.
  375. ///
  376. /// @param first Lower bound of the address range.
  377. /// @param last Upper bound of the address range.
  378. ///
  379. /// @return true if client has lease for the address within the range,
  380. /// false otherwise.
  381. bool hasLeaseForAddressRange(const asiolink::IOAddress& first,
  382. const asiolink::IOAddress& last) const;
  383. /// @brief Checks if client has a lease with zero lifetimes for the
  384. /// specified address.
  385. ///
  386. /// @param address Address for which lease should be found.
  387. ///
  388. /// @return true if client has a lease, false otherwise.
  389. bool hasLeaseWithZeroLifetimeForAddress(const asiolink::IOAddress& address) const;
  390. /// @brief Checks if client has a lease for a prefix.
  391. ///
  392. /// @param prefix Prefix.
  393. /// @param prefix_len Prefix length.
  394. ///
  395. /// @return true if client has a lease for the specified prefix, false
  396. /// otherwise.
  397. bool hasLeaseForPrefix(const asiolink::IOAddress& prefix,
  398. const uint8_t prefix_len) const;
  399. /// @brief Checks if client as a lease for prefix in the IA_PD identified
  400. /// by specified IAID.
  401. ///
  402. /// @param prefix Prefix.
  403. /// @param prefix_len Prefix length.
  404. /// @param iaid IAID of the IA_PD in which the lease is expected.
  405. bool hasLeaseForPrefix(const asiolink::IOAddress& prefix,
  406. const uint8_t prefix_len,
  407. const IAID& iaid) const;
  408. /// @brief Checks if client has a lease belonging to a prefix pool.
  409. ///
  410. /// @param prefix Pool prefix.
  411. /// @param prefix_len Prefix length.
  412. /// @param delegated_len Delegated prefix length.
  413. ///
  414. /// @return true if client has a lease belonging to specified pool,
  415. /// false otherwise.
  416. bool hasLeaseForPrefixPool(const asiolink::IOAddress& prefix,
  417. const uint8_t prefix_len,
  418. const uint8_t delegated_len) const;
  419. /// @brief Checks if client has a lease with zero lifetimes for a prefix.
  420. ///
  421. /// @param prefix Prefix.
  422. /// @param prefix_len Prefix length.
  423. ///
  424. /// @return true if client has a lease with zero lifetimes for a prefix.
  425. bool hasLeaseWithZeroLifetimeForPrefix(const asiolink::IOAddress& prefix,
  426. const uint8_t prefix_len) const;
  427. /// @brief Checks that specified option exists and contains a desired
  428. /// address.
  429. ///
  430. /// The option must cast to the @ref Option6AddrLst type. The function
  431. /// expects that this option contains at least one address and checks
  432. /// first address for equality with @ref expected_address.
  433. ///
  434. /// @param option_type Option type.
  435. /// @param expected_address Desired address.
  436. /// @param config Configuration obtained from the server.
  437. bool hasOptionWithAddress(const uint16_t option_type,
  438. const std::string& expected_address) const;
  439. /// @brief Returns the value of the global status code for the last
  440. /// transaction.
  441. uint16_t getStatusCode() const {
  442. return (config_.status_code_);
  443. }
  444. /// @brief Returns status code set by the server for the IAID.
  445. ///
  446. /// @warning This method doesn't check if the specified index is out of
  447. /// range. The caller is responsible for using a correct offset by
  448. /// invoking the @c getLeaseNum function.
  449. ///
  450. /// @param at Index of the lease held by the client.
  451. /// @return A status code for the lease at the specified index.
  452. uint16_t getStatusCode(const uint32_t iaid) const;
  453. /// @brief Returns number of acquired leases.
  454. size_t getLeaseNum() const {
  455. return (config_.leases_.size());
  456. }
  457. /// @brief Returns the server that the client is communicating with.
  458. boost::shared_ptr<isc::dhcp::test::NakedDhcpv6Srv>& getServer() {
  459. return (srv_);
  460. }
  461. /// @brief Sets the client's DUID from a string value
  462. ///
  463. /// Replaces the client's DUID with one constructed from the given
  464. /// string. The string is expected to contain hexadecimal digits with or
  465. /// without ":" separators.
  466. ///
  467. /// @param str The string of digits from which to create the DUID
  468. ///
  469. /// The DUID modification affects the value returned by the
  470. /// @c Dhcp6Client::getClientId
  471. void setDUID(const std::string& duid_str);
  472. /// @brief Modifies the client's DUID (adds one to it).
  473. ///
  474. /// The DUID should be modified to test negative scenarios when the client
  475. /// acquires a lease and tries to renew it with a different DUID. The server
  476. /// should detect the DUID mismatch and react accordingly.
  477. ///
  478. /// The DUID modification affects the value returned by the
  479. /// @c Dhcp6Client::getClientId
  480. void modifyDUID();
  481. /// @brief Checks if the global status code was received in the response
  482. /// from the server.
  483. ///
  484. /// @return true if the global status code option was received.
  485. bool receivedStatusCode() const {
  486. return (config_.received_status_code_);
  487. }
  488. /// @brief Sets destination address for the messages being sent by the
  489. /// client.
  490. ///
  491. /// By default, the client uses All_DHCP_Relay_Agents_and_Servers
  492. /// multicast address to communicate with the server. In certain cases
  493. /// it may be desired that different address is used (e.g. unicast in Renew).
  494. /// This function sets the new address for all future exchanges with the
  495. /// server.
  496. ///
  497. /// @param dest_addr New destination address.
  498. void setDestAddress(const asiolink::IOAddress& dest_addr) {
  499. dest_addr_ = dest_addr;
  500. }
  501. /// @brief Sets the interface to be used by the client.
  502. ///
  503. /// @param iface_name Interface name.
  504. void setInterface(const std::string& iface_name) {
  505. iface_name_ = iface_name;
  506. }
  507. /// @brief Sets link local address used by the client.
  508. ///
  509. /// @param link_local New link local address.
  510. void setLinkLocal(const asiolink::IOAddress& link_local) {
  511. link_local_ = link_local;
  512. }
  513. /// @brief Specifies address to be included in client's message.
  514. ///
  515. /// This method specifies IPv6 address to be included within IA_NA
  516. /// option sent by the client. In order to specify multiple addresses
  517. /// to be included in a particular IA_NA, this method must be called
  518. /// multiple times to specify each address separately. In such case,
  519. /// the value of the IAID should remain the same across all calls to
  520. /// this method.
  521. ///
  522. /// This method is typically called to specify IA_NA options to be
  523. /// sent to the server during 4-way handshakes and during lease
  524. /// renewal to request allocation of new leases (as per RFC7550).
  525. ///
  526. /// @param iaid IAID.
  527. /// @param address IPv6 address to be included in the IA_NA. It defaults
  528. /// to IPv6 zero address, which indicates that no address should be
  529. /// included in the IA_NA (empty IA_NA will be sent).
  530. void requestAddress(const uint32_t iaid = 1234,
  531. const asiolink::IOAddress& address =
  532. asiolink::IOAddress::IPV6_ZERO_ADDRESS());
  533. /// @brief Specifies IPv6 prefix to be included in client's message.
  534. ///
  535. /// This method specifies IPv6 prefix to be included within IA_PD
  536. /// option sent by the client. In order to specify multiple prefixes
  537. /// to be included in a particular IA_PD, this method must be called
  538. /// multiple times to specify each prefix separately. In such case,
  539. /// the value of the IAID should remain the same across all calls to
  540. /// this method.
  541. ///
  542. /// This method is typically called to specify IA_PD options to be
  543. /// sent to the server during 4-way handshakes and during lease
  544. /// renewal to request allocation of new leases (as per RFC7550).
  545. ///
  546. /// @param iaid IAID.
  547. /// @param prefix_len Prefix length.
  548. /// @param prefix Prefix to be included. This value defaults to the
  549. /// IPv6 zero address. If zero address is specified and prefix_len is
  550. /// set to 0, the IA Prefix option will not be included in the IA_PD.
  551. /// If the prefix_len is non-zero and the prefix is IPv6 zero address
  552. /// the prefix length hint will be included in the IA Prefix option.
  553. void requestPrefix(const uint32_t iaid = 5678,
  554. const uint8_t prefix_len = 0,
  555. const asiolink::IOAddress& prefix =
  556. asiolink::IOAddress::IPV6_ZERO_ADDRESS());
  557. /// @brief Removes IAs specified by @ref requestAddress and
  558. /// @ref requestPrefix methods.
  559. ///
  560. /// If this method is called and the client initiates an exchange with
  561. /// a server the client will only include IAs for which it has leases.
  562. /// If the client has no leases (e.g. a Solicit case), no IAs will be
  563. /// included in the client's message.
  564. void clearRequestedIAs() {
  565. client_ias_.clear();
  566. }
  567. /// @brief Simulate sending messages through a relay.
  568. ///
  569. /// @param use Parameter which 'true' value indicates that client should
  570. /// simulate sending messages via relay.
  571. /// @param link_addr Relay link-addr.
  572. void useRelay(const bool use = true,
  573. const asiolink::IOAddress& link_addr = asiolink::IOAddress("3000:1::1")) {
  574. use_relay_ = use;
  575. relay_link_addr_ = link_addr;
  576. }
  577. /// @brief Sets interface id value to be inserted into relay agent option.
  578. ///
  579. /// @param interface_id Value of the interface id as string.
  580. void useInterfaceId(const std::string& interface_id);
  581. /// @brief Controls whether the client should send a client-id or not
  582. /// @param send should the client-id be sent?
  583. void useClientId(const bool send) {
  584. use_client_id_ = send;
  585. }
  586. /// @brief Specifies if the Rapid Commit option should be included in
  587. /// the Solicit message.
  588. ///
  589. /// @param rapid_commit Boolean parameter controlling if the Rapid Commit
  590. /// option must be included in the Solicit (if true), or not (if false).
  591. void useRapidCommit(const bool rapid_commit) {
  592. use_rapid_commit_ = rapid_commit;
  593. }
  594. /// @brief Specifies server-id to be used in send messages
  595. ///
  596. /// Overrides the server-id to be sent when server-id is expected to be
  597. /// sent. May be NULL, which means use proper server-id sent in Advertise
  598. /// (which is a normal client behavior).
  599. ///
  600. /// @param server_id server-id to be sent
  601. void useServerId(const OptionPtr& server_id) {
  602. forced_server_id_ = server_id;
  603. }
  604. /// @brief Creates an instance of the Client FQDN option to be included
  605. /// in the client's message.
  606. ///
  607. /// @param flags Flags.
  608. /// @param fqdn_name Name in the textual format.
  609. /// @param fqdn_type Type of the name (fully qualified or partial).
  610. void useFQDN(const uint8_t flags, const std::string& fqdn_name,
  611. Option6ClientFqdn::DomainNameType fqdn_type);
  612. /// @brief Lease configuration obtained by the client.
  613. Configuration config_;
  614. /// @brief Link address of the relay to be used for relayed messages.
  615. asiolink::IOAddress relay_link_addr_;
  616. /// @brief RelayInfo (information about relays)
  617. ///
  618. /// Dhcp6Client will typically construct this info itself, but if
  619. /// it is provided here by the test, this data will be used as is.
  620. std::vector<Pkt6::RelayInfo> relay_info_;
  621. /// @brief Controls whether the client will send ORO
  622. ///
  623. /// The actual content of the ORO is specified in oro_.
  624. /// It is useful to split the actual content and the ORO sending
  625. /// decision, so we could test cases of sending empty ORO.
  626. /// @param send controls whether ORO will be sent or not.
  627. void useORO(bool send) {
  628. use_oro_ = send;
  629. }
  630. /// @brief Instructs client to request specified option in ORO
  631. ///
  632. /// @param option_code client will request this option code
  633. void requestOption(uint16_t option_code) {
  634. use_oro_ = true;
  635. oro_.push_back(option_code);
  636. }
  637. /// @brief Controls whether the client will send DOCSIS vendor ORO
  638. ///
  639. /// The actual content of the ORO is specified in docsis_oro_.
  640. /// It is useful to split the actual content and the ORO sending
  641. /// decision, so we could test cases of sending empty ORO.
  642. /// @param send controls whether ORO will be sent or not.
  643. void useDocsisORO(bool send) {
  644. use_docsis_oro_ = send;
  645. }
  646. /// @brief Instructs client to request specified option in DOCSIS
  647. /// vendor ORO
  648. ///
  649. /// @param option_code client will request this option code
  650. void requestDocsisOption(uint16_t option_code) {
  651. use_docsis_oro_ = true;
  652. docsis_oro_.push_back(option_code);
  653. }
  654. /// @brief returns client-id
  655. /// @return client-id
  656. DuidPtr getDuid() const {
  657. return (duid_);
  658. }
  659. /// @brief Generates IA_NA based on lease information
  660. ///
  661. /// @param query generated IA_NA options will be added here
  662. /// @param include_address should the address be included?
  663. void generateIAFromLeases(const Pkt6Ptr& query,
  664. const bool include_address = true);
  665. /// @brief Adds extra option (an option the client will always send)
  666. ///
  667. /// @param opt additional option to be sent
  668. void addExtraOption(const OptionPtr& opt);
  669. /// @brief Configures the client to not send any extra options.
  670. void clearExtraOptions();
  671. /// @brief Debugging method the prints currently held configuration
  672. ///
  673. /// @todo: This is mostly useful when debugging tests. This method
  674. /// is incomplete. Please extend it when needed.
  675. void printConfiguration() const;
  676. private:
  677. /// @brief Applies the new leases for the client.
  678. ///
  679. /// This method is called when the client obtains a new configuration
  680. /// from the server in the Reply message. This function adds new leases
  681. /// or replaces existing ones, on the client's side. Client uses these
  682. /// leases in any later communication with the server when doing Renew
  683. /// or Rebind.
  684. ///
  685. /// @param reply Server response.
  686. /// @param state specifies lease state (see Lease::STATE_* for details).
  687. ///
  688. /// The default for state is 0. We could have included dhcpsrv/lease.h
  689. /// and used Lease::STATE_DEFAULT, but that would complicate the header
  690. /// inclusion dependencies. It's easier to simply use 0 as the default.
  691. ///
  692. /// @todo Currently this function supports one IAAddr or IAPrefix option
  693. /// within IA. We will need to extend it to support multiple options
  694. /// within a single IA once server supports that.
  695. void applyRcvdConfiguration(const Pkt6Ptr& reply, uint32_t state = 0);
  696. /// @brief Applies configuration for the single lease.
  697. ///
  698. /// This method is called by the @c Dhcp6Client::applyRcvdConfiguration for
  699. /// each individual lease.
  700. ///
  701. /// @param lease_info Structure holding new lease information.
  702. void applyLease(const Lease6& lease);
  703. /// @brief Includes Client FQDN in the client's message.
  704. ///
  705. /// This method checks if @c fqdn_ is specified and includes it in
  706. /// the client's message.
  707. void appendFQDN();
  708. /// @brief Includes IAs to be requested.
  709. ///
  710. /// This method includes IAs explicitly requested using client_ias_
  711. ///
  712. /// @param query Pointer to the client's message to which IAs should be
  713. /// added.
  714. void appendRequestedIAs(const Pkt6Ptr& query) const;
  715. /// @brief Copy IA options from one message to another.
  716. ///
  717. /// This method copies IA_NA and IA_PD options from one message to another.
  718. /// It is useful when the client needs to construct the Request message
  719. /// using addresses and prefixes returned by the client in Advertise.
  720. ///
  721. /// @param source Message from which IA options will be copied.
  722. /// @param dest Message to which IA options will be copied.
  723. ///
  724. /// @todo Add support for IA_TA.
  725. void copyIAs(const Pkt6Ptr& source, const Pkt6Ptr& dest);
  726. /// @brief Creates IA options from existing configuration.
  727. ///
  728. /// This method iterates over existing leases that client acquired and
  729. /// places corresponding IA_NA or IA_PD options into a specified message.
  730. /// This is useful to construct Renew, Rebind or Confirm message from the
  731. /// existing configuration that client has obtained using 4-way exchange.
  732. ///
  733. /// If there are no leases no IA options will be added. If the lease exists
  734. /// but any of the lifetime values is set to 0, the IA option will be added
  735. /// but the IAAddr (or IAPrefix) option will not be added.
  736. ///
  737. /// @param dest Message to which the IA options will be added.
  738. void copyIAsFromLeases(const Pkt6Ptr& dest) const;
  739. /// @brief Creates client's side DHCP message.
  740. ///
  741. /// @param msg_type Type of the message to be created.
  742. /// @return An instance of the message created.
  743. Pkt6Ptr createMsg(const uint8_t msg_type);
  744. /// @brief Generates DUID for the client.
  745. ///
  746. /// @param duid_type Type of the DUID. Currently, only LLT is accepted.
  747. /// @return Object encapsulating a DUID.
  748. DuidPtr generateDUID(DUID::DUIDType duid_type) const;
  749. /// @brief Returns client's leases which match the specified condition.
  750. ///
  751. /// @param property A value of the lease property used to search the lease.
  752. /// @param equals A flag which indicates if the operator should search
  753. /// for the leases which property is equal to the value of @c property
  754. /// parameter (if true), or unequal (if false).
  755. /// @param [out] leases A vector in which the operator will store leases
  756. /// found.
  757. ///
  758. /// @tparam BaseType Base type to which the property belongs: @c Lease or
  759. /// @c Lease6.
  760. /// @tparam PropertyType A type of the property, e.g. @c uint32_t for IAID.
  761. /// @tparam MemberPointer A pointer to the member, e.g. @c &Lease6::iaid_.
  762. template<typename BaseType, typename PropertyType,
  763. PropertyType BaseType::*MemberPointer>
  764. void getLeasesByProperty(const PropertyType& property, const bool equals,
  765. std::vector<Lease6>& leases) const;
  766. /// @brief Simulates reception of the message from the server.
  767. ///
  768. /// @return Received message.
  769. Pkt6Ptr receiveOneMsg();
  770. /// @brief Simulates sending a message to the server.
  771. ///
  772. /// This function instantly triggers processing of the message by the
  773. /// server. The server's response can be gathered by invoking the
  774. /// @c receiveOneMsg function.
  775. ///
  776. /// @param msg Message to be sent.
  777. void sendMsg(const Pkt6Ptr& msg);
  778. /// @brief Current context (sent and received message).
  779. Context context_;
  780. /// @brief Current transaction id (altered on each send).
  781. uint32_t curr_transid_;
  782. /// @brief Currently used destination address.
  783. asiolink::IOAddress dest_addr_;
  784. /// @brief Currently used DUID.
  785. DuidPtr duid_;
  786. /// @brief Currently used link local address.
  787. asiolink::IOAddress link_local_;
  788. /// @brief Currently used interface.
  789. std::string iface_name_;
  790. /// @brief Pointer to the server that the client is communicating with.
  791. boost::shared_ptr<isc::dhcp::test::NakedDhcpv6Srv> srv_;
  792. bool use_relay_; ///< Enable relaying messages to the server.
  793. bool use_oro_; ///< Conth
  794. bool use_docsis_oro_;
  795. bool use_client_id_;
  796. bool use_rapid_commit_;
  797. /// @brief List holding information to be sent in client's IAs.
  798. std::list<ClientIA> client_ias_;
  799. /// @brief List of options to be requested
  800. ///
  801. /// Content of this vector will be sent as ORO if use_oro_ is set
  802. /// to true. See @ref sendORO for details.
  803. std::vector<uint16_t> oro_;
  804. /// @brief List of DOCSIS vendor options to be requested
  805. ///
  806. /// Content of this vector will be sent as DOCSIS vendor ORO if
  807. /// use_docsis_oro_ is set to true. See @ref sendDocsisORO for details.
  808. std::vector<uint16_t> docsis_oro_;
  809. /// @brief forced (Overridden) value of the server-id option (may be NULL)
  810. OptionPtr forced_server_id_;
  811. /// @brief Extra options the client will send.
  812. OptionCollection extra_options_;
  813. /// @brief FQDN requested by the client.
  814. Option6ClientFqdnPtr fqdn_;
  815. /// @brief Interface id.
  816. OptionPtr interface_id_;
  817. };
  818. } // end of namespace isc::dhcp::test
  819. } // end of namespace isc::dhcp
  820. } // end of namespace isc
  821. #endif // DHCP6_CLIENT