libdhcp++_unittest.cc 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. // Copyright (C) 2011-2013 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. #include <config.h>
  15. #include <dhcp/dhcp4.h>
  16. #include <dhcp/dhcp6.h>
  17. #include <dhcp/libdhcp++.h>
  18. #include <dhcp/option4_addrlst.h>
  19. #include <dhcp/option6_addrlst.h>
  20. #include <dhcp/option6_client_fqdn.h>
  21. #include <dhcp/option6_ia.h>
  22. #include <dhcp/option6_iaaddr.h>
  23. #include <dhcp/option_custom.h>
  24. #include <dhcp/option_int.h>
  25. #include <dhcp/option_int_array.h>
  26. #include <dhcp/option_string.h>
  27. #include <util/buffer.h>
  28. #include <gtest/gtest.h>
  29. #include <iostream>
  30. #include <sstream>
  31. #include <arpa/inet.h>
  32. using namespace std;
  33. using namespace isc;
  34. using namespace isc::dhcp;
  35. using namespace isc::util;
  36. namespace {
  37. class LibDhcpTest : public ::testing::Test {
  38. public:
  39. LibDhcpTest() { }
  40. /// @brief Generic factory function to create any option.
  41. ///
  42. /// Generic factory function to create any option.
  43. ///
  44. /// @param u universe (V4 or V6)
  45. /// @param type option-type
  46. /// @param buf option-buffer
  47. static OptionPtr genericOptionFactory(Option::Universe u, uint16_t type,
  48. const OptionBuffer& buf) {
  49. return (OptionPtr(new Option(u, type, buf)));
  50. }
  51. /// @brief Test DHCPv4 option definition.
  52. ///
  53. /// This function tests if option definition for standard
  54. /// option has been initialized correctly.
  55. ///
  56. /// @param code option code.
  57. /// @param begin iterator pointing at beginning of a buffer to
  58. /// be used to create option instance.
  59. /// @param end iterator pointing at end of a buffer to be
  60. /// used to create option instance.
  61. /// @param expected_type type of the option created by the
  62. /// factory function returned by the option definition.
  63. /// @param encapsulates name of the option space being encapsulated
  64. /// by the option.
  65. static void testStdOptionDefs4(const uint16_t code,
  66. const OptionBufferConstIter begin,
  67. const OptionBufferConstIter end,
  68. const std::type_info& expected_type,
  69. const std::string& encapsulates = "") {
  70. // Use V4 universe.
  71. testStdOptionDefs(Option::V4, code, begin, end, expected_type,
  72. encapsulates);
  73. }
  74. /// @brief Test DHCPv6 option definition.
  75. ///
  76. /// This function tests if option definition for standard
  77. /// option has been initialized correctly.
  78. ///
  79. /// @param code option code.
  80. /// @param begin iterator pointing at beginning of a buffer to
  81. /// be used to create option instance.
  82. /// @param end iterator pointing at end of a buffer to be
  83. /// used to create option instance.
  84. /// @param expected_type type of the option created by the
  85. /// factory function returned by the option definition.
  86. /// @param encapsulates name of the option space being encapsulated
  87. /// by the option.
  88. static void testStdOptionDefs6(const uint16_t code,
  89. const OptionBufferConstIter begin,
  90. const OptionBufferConstIter end,
  91. const std::type_info& expected_type,
  92. const std::string& encapsulates = "") {
  93. // Use V6 universe.
  94. testStdOptionDefs(Option::V6, code, begin, end, expected_type,
  95. encapsulates);
  96. }
  97. private:
  98. /// @brief Test DHCPv4 or DHCPv6 option definition.
  99. ///
  100. /// This function tests if option definition for standard
  101. /// option has been initialized correctly.
  102. ///
  103. /// @param code option code.
  104. /// @param begin iterator pointing at beginning of a buffer to
  105. /// be used to create option instance.
  106. /// @param end iterator pointing at end of a buffer to be
  107. /// used to create option instance.
  108. /// @param expected_type type of the option created by the
  109. /// factory function returned by the option definition.
  110. /// @param encapsulates name of the option space being encapsulated
  111. /// by the option.
  112. static void testStdOptionDefs(const Option::Universe u,
  113. const uint16_t code,
  114. const OptionBufferConstIter begin,
  115. const OptionBufferConstIter end,
  116. const std::type_info& expected_type,
  117. const std::string& encapsulates) {
  118. // Get all option definitions, we will use them to extract
  119. // the definition for a particular option code.
  120. // We don't have to initialize option definitions here because they
  121. // are initialized in the class's constructor.
  122. OptionDefContainer options = LibDHCP::getOptionDefs(u);
  123. // Get the container index #1. This one allows for searching
  124. // option definitions using option code.
  125. const OptionDefContainerTypeIndex& idx = options.get<1>();
  126. // Get 'all' option definitions for a particular option code.
  127. // For standard options we expect that the range returned
  128. // will contain single option as their codes are unique.
  129. OptionDefContainerTypeRange range = idx.equal_range(code);
  130. ASSERT_EQ(1, std::distance(range.first, range.second))
  131. << "Standard option definition for the code " << code
  132. << " has not been found.";
  133. // If we have single option definition returned, the
  134. // first iterator holds it.
  135. OptionDefinitionPtr def = *(range.first);
  136. // It should not happen that option definition is NULL but
  137. // let's make sure (test should take things like that into
  138. // account).
  139. ASSERT_TRUE(def) << "Option definition for the code "
  140. << code << " is NULL.";
  141. // Check that option definition is valid.
  142. ASSERT_NO_THROW(def->validate())
  143. << "Option definition for the option code " << code
  144. << " is invalid";
  145. // Check that the valid encapsulated option space name
  146. // has been specified.
  147. EXPECT_EQ(encapsulates, def->getEncapsulatedSpace());
  148. OptionPtr option;
  149. // Create the option.
  150. ASSERT_NO_THROW(option = def->optionFactory(u, code, begin, end))
  151. << "Option creation failed for option code " << code;
  152. // Make sure it is not NULL.
  153. ASSERT_TRUE(option);
  154. // And the actual object type is the one that we expect.
  155. // Note that for many options there are dedicated classes
  156. // derived from Option class to represent them.
  157. EXPECT_TRUE(typeid(*option) == expected_type)
  158. << "Invalid class returned for option code " << code;
  159. }
  160. };
  161. // The DHCPv6 options in the wire format, used by multiple tests.
  162. const uint8_t v6packed[] = {
  163. 0, 1, 0, 5, 100, 101, 102, 103, 104, // CLIENT_ID (9 bytes)
  164. 0, 2, 0, 3, 105, 106, 107, // SERVER_ID (7 bytes)
  165. 0, 14, 0, 0, // RAPID_COMMIT (0 bytes)
  166. 0, 6, 0, 4, 108, 109, 110, 111, // ORO (8 bytes)
  167. 0, 8, 0, 2, 112, 113 // ELAPSED_TIME (6 bytes)
  168. };
  169. TEST_F(LibDhcpTest, optionFactory) {
  170. OptionBuffer buf;
  171. // Factory functions for specific options must be registered before
  172. // they can be used to create options instances. Otherwise exception
  173. // is rised.
  174. EXPECT_THROW(LibDHCP::optionFactory(Option::V4, DHO_SUBNET_MASK, buf),
  175. isc::BadValue);
  176. // Let's register some factory functions (two v4 and one v6 function).
  177. // Registration may trigger exception if function for the specified
  178. // option has been registered already.
  179. ASSERT_NO_THROW(
  180. LibDHCP::OptionFactoryRegister(Option::V4, DHO_SUBNET_MASK,
  181. &LibDhcpTest::genericOptionFactory);
  182. );
  183. ASSERT_NO_THROW(
  184. LibDHCP::OptionFactoryRegister(Option::V4, DHO_TIME_OFFSET,
  185. &LibDhcpTest::genericOptionFactory);
  186. );
  187. ASSERT_NO_THROW(
  188. LibDHCP::OptionFactoryRegister(Option::V6, D6O_CLIENTID,
  189. &LibDhcpTest::genericOptionFactory);
  190. );
  191. // Invoke factory functions for all options (check if registration
  192. // was successful).
  193. OptionPtr opt_subnet_mask;
  194. opt_subnet_mask = LibDHCP::optionFactory(Option::V4,
  195. DHO_SUBNET_MASK,
  196. buf);
  197. // Check if non-NULL DHO_SUBNET_MASK option pointer has been returned.
  198. ASSERT_TRUE(opt_subnet_mask);
  199. // Validate if type and universe is correct.
  200. EXPECT_EQ(Option::V4, opt_subnet_mask->getUniverse());
  201. EXPECT_EQ(DHO_SUBNET_MASK, opt_subnet_mask->getType());
  202. // Expect that option does not have content..
  203. EXPECT_EQ(0, opt_subnet_mask->len() - opt_subnet_mask->getHeaderLen());
  204. // Fill the time offset buffer with 4 bytes of data. Each byte set to 1.
  205. OptionBuffer time_offset_buf(4, 1);
  206. OptionPtr opt_time_offset;
  207. opt_time_offset = LibDHCP::optionFactory(Option::V4,
  208. DHO_TIME_OFFSET,
  209. time_offset_buf);
  210. // Check if non-NULL DHO_TIME_OFFSET option pointer has been returned.
  211. ASSERT_TRUE(opt_time_offset);
  212. // Validate if option length, type and universe is correct.
  213. EXPECT_EQ(Option::V4, opt_time_offset->getUniverse());
  214. EXPECT_EQ(DHO_TIME_OFFSET, opt_time_offset->getType());
  215. EXPECT_EQ(time_offset_buf.size(),
  216. opt_time_offset->len() - opt_time_offset->getHeaderLen());
  217. // Validate data in the option.
  218. EXPECT_TRUE(std::equal(time_offset_buf.begin(), time_offset_buf.end(),
  219. opt_time_offset->getData().begin()));
  220. // Fill the client id buffer with 20 bytes of data. Each byte set to 2.
  221. OptionBuffer clientid_buf(20, 2);
  222. OptionPtr opt_clientid;
  223. opt_clientid = LibDHCP::optionFactory(Option::V6,
  224. D6O_CLIENTID,
  225. clientid_buf);
  226. // Check if non-NULL D6O_CLIENTID option pointer has been returned.
  227. ASSERT_TRUE(opt_clientid);
  228. // Validate if option length, type and universe is correct.
  229. EXPECT_EQ(Option::V6, opt_clientid->getUniverse());
  230. EXPECT_EQ(D6O_CLIENTID, opt_clientid->getType());
  231. EXPECT_EQ(clientid_buf.size(), opt_clientid->len() - opt_clientid->getHeaderLen());
  232. // Validate data in the option.
  233. EXPECT_TRUE(std::equal(clientid_buf.begin(), clientid_buf.end(),
  234. opt_clientid->getData().begin()));
  235. }
  236. TEST_F(LibDhcpTest, packOptions6) {
  237. OptionBuffer buf(512);
  238. isc::dhcp::Option::OptionCollection opts; // list of options
  239. // generate content for options
  240. for (int i = 0; i < 64; i++) {
  241. buf[i]=i+100;
  242. }
  243. OptionPtr opt1(new Option(Option::V6, 1, buf.begin() + 0, buf.begin() + 5));
  244. OptionPtr opt2(new Option(Option::V6, 2, buf.begin() + 5, buf.begin() + 8));
  245. OptionPtr opt3(new Option(Option::V6, 14, buf.begin() + 8, buf.begin() + 8));
  246. OptionPtr opt4(new Option(Option::V6, 6, buf.begin() + 8, buf.begin() + 12));
  247. OptionPtr opt5(new Option(Option::V6, 8, buf.begin() + 12, buf.begin() + 14));
  248. opts.insert(make_pair(opt1->getType(), opt1));
  249. opts.insert(make_pair(opt1->getType(), opt2));
  250. opts.insert(make_pair(opt1->getType(), opt3));
  251. opts.insert(make_pair(opt1->getType(), opt4));
  252. opts.insert(make_pair(opt1->getType(), opt5));
  253. OutputBuffer assembled(512);
  254. EXPECT_NO_THROW(LibDHCP::packOptions(assembled, opts));
  255. EXPECT_EQ(sizeof(v6packed), assembled.getLength());
  256. EXPECT_EQ(0, memcmp(assembled.getData(), v6packed, sizeof(v6packed)));
  257. }
  258. TEST_F(LibDhcpTest, unpackOptions6) {
  259. // just couple of random options
  260. // Option is used as a simple option implementation
  261. // More advanced uses are validated in tests dedicated for
  262. // specific derived classes.
  263. isc::dhcp::Option::OptionCollection options; // list of options
  264. OptionBuffer buf(512);
  265. memcpy(&buf[0], v6packed, sizeof(v6packed));
  266. EXPECT_NO_THROW ({
  267. LibDHCP::unpackOptions6(OptionBuffer(buf.begin(), buf.begin() + sizeof(v6packed)),
  268. options);
  269. });
  270. EXPECT_EQ(options.size(), 5); // there should be 5 options
  271. isc::dhcp::Option::OptionCollection::const_iterator x = options.find(1);
  272. ASSERT_FALSE(x == options.end()); // option 1 should exist
  273. EXPECT_EQ(1, x->second->getType()); // this should be option 1
  274. ASSERT_EQ(9, x->second->len()); // it should be of length 9
  275. ASSERT_EQ(5, x->second->getData().size());
  276. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v6packed + 4, 5)); // data len=5
  277. x = options.find(2);
  278. ASSERT_FALSE(x == options.end()); // option 2 should exist
  279. EXPECT_EQ(2, x->second->getType()); // this should be option 2
  280. ASSERT_EQ(7, x->second->len()); // it should be of length 7
  281. ASSERT_EQ(3, x->second->getData().size());
  282. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v6packed + 13, 3)); // data len=3
  283. x = options.find(14);
  284. ASSERT_FALSE(x == options.end()); // option 14 should exist
  285. EXPECT_EQ(14, x->second->getType()); // this should be option 14
  286. ASSERT_EQ(4, x->second->len()); // it should be of length 4
  287. EXPECT_EQ(0, x->second->getData().size()); // data len = 0
  288. x = options.find(6);
  289. ASSERT_FALSE(x == options.end()); // option 6 should exist
  290. EXPECT_EQ(6, x->second->getType()); // this should be option 6
  291. ASSERT_EQ(8, x->second->len()); // it should be of length 8
  292. // Option with code 6 is the OPTION_ORO. This option is
  293. // represented by the OptionIntArray<uint16_t> class which
  294. // comprises the set of uint16_t values. We need to cast the
  295. // returned pointer to this type to get values stored in it.
  296. boost::shared_ptr<OptionIntArray<uint16_t> > opt_oro =
  297. boost::dynamic_pointer_cast<OptionIntArray<uint16_t> >(x->second);
  298. // This value will be NULL if cast was unsuccessful. This is the case
  299. // when returned option has different type than expected.
  300. ASSERT_TRUE(opt_oro);
  301. // Get set of uint16_t values.
  302. std::vector<uint16_t> opts = opt_oro->getValues();
  303. // Prepare the refrence data.
  304. std::vector<uint16_t> expected_opts;
  305. expected_opts.push_back(0x6C6D); // equivalent to: 108, 109
  306. expected_opts.push_back(0x6E6F); // equivalent to 110, 111
  307. ASSERT_EQ(expected_opts.size(), opts.size());
  308. // Validated if option has been unpacked correctly.
  309. EXPECT_TRUE(std::equal(expected_opts.begin(), expected_opts.end(),
  310. opts.begin()));
  311. x = options.find(8);
  312. ASSERT_FALSE(x == options.end()); // option 8 should exist
  313. EXPECT_EQ(8, x->second->getType()); // this should be option 8
  314. ASSERT_EQ(6, x->second->len()); // it should be of length 9
  315. // Option with code 8 is OPTION_ELAPSED_TIME. This option is
  316. // represented by Option6Int<uint16_t> value that holds single
  317. // uint16_t value.
  318. boost::shared_ptr<OptionInt<uint16_t> > opt_elapsed_time =
  319. boost::dynamic_pointer_cast<OptionInt<uint16_t> >(x->second);
  320. // This value will be NULL if cast was unsuccessful. This is the case
  321. // when returned option has different type than expected.
  322. ASSERT_TRUE(opt_elapsed_time);
  323. // Returned value should be equivalent to two byte values: 112, 113
  324. EXPECT_EQ(0x7071, opt_elapsed_time->getValue());
  325. x = options.find(0);
  326. EXPECT_TRUE(x == options.end()); // option 0 not found
  327. x = options.find(256); // 256 is htons(1) on little endians. Worth checking
  328. EXPECT_TRUE(x == options.end()); // option 1 not found
  329. x = options.find(7);
  330. EXPECT_TRUE(x == options.end()); // option 2 not found
  331. x = options.find(32000);
  332. EXPECT_TRUE(x == options.end()); // option 32000 not found */
  333. }
  334. /// V4 Options being used to test pack/unpack operations.
  335. /// These are variable length options only so as there
  336. /// is no restriction on the data length being carried by them.
  337. /// For simplicity, we assign data of the length 3 for each
  338. /// of them.
  339. static uint8_t v4_opts[] = {
  340. 12, 3, 0, 1, 2, // Hostname
  341. 60, 3, 10, 11, 12, // Class Id
  342. 14, 3, 20, 21, 22, // Merit Dump File
  343. 254, 3, 30, 31, 32, // Reserved
  344. 128, 3, 40, 41, 42 // Vendor specific
  345. };
  346. TEST_F(LibDhcpTest, packOptions4) {
  347. vector<uint8_t> payload[5];
  348. for (int i = 0; i < 5; i++) {
  349. payload[i].resize(3);
  350. payload[i][0] = i*10;
  351. payload[i][1] = i*10+1;
  352. payload[i][2] = i*10+2;
  353. }
  354. OptionPtr opt1(new Option(Option::V4, 12, payload[0]));
  355. OptionPtr opt2(new Option(Option::V4, 60, payload[1]));
  356. OptionPtr opt3(new Option(Option::V4, 14, payload[2]));
  357. OptionPtr opt4(new Option(Option::V4,254, payload[3]));
  358. OptionPtr opt5(new Option(Option::V4,128, payload[4]));
  359. isc::dhcp::Option::OptionCollection opts; // list of options
  360. opts.insert(make_pair(opt1->getType(), opt1));
  361. opts.insert(make_pair(opt1->getType(), opt2));
  362. opts.insert(make_pair(opt1->getType(), opt3));
  363. opts.insert(make_pair(opt1->getType(), opt4));
  364. opts.insert(make_pair(opt1->getType(), opt5));
  365. vector<uint8_t> expVect(v4_opts, v4_opts + sizeof(v4_opts));
  366. OutputBuffer buf(100);
  367. EXPECT_NO_THROW(LibDHCP::packOptions(buf, opts));
  368. ASSERT_EQ(buf.getLength(), sizeof(v4_opts));
  369. EXPECT_EQ(0, memcmp(v4_opts, buf.getData(), sizeof(v4_opts)));
  370. }
  371. TEST_F(LibDhcpTest, unpackOptions4) {
  372. vector<uint8_t> v4packed(v4_opts, v4_opts + sizeof(v4_opts));
  373. isc::dhcp::Option::OptionCollection options; // list of options
  374. ASSERT_NO_THROW(
  375. LibDHCP::unpackOptions4(v4packed, options);
  376. );
  377. isc::dhcp::Option::OptionCollection::const_iterator x = options.find(12);
  378. ASSERT_FALSE(x == options.end()); // option 1 should exist
  379. // Option 12 holds a string so let's cast it to an appropriate type.
  380. OptionStringPtr option12 = boost::static_pointer_cast<OptionString>(x->second);
  381. ASSERT_TRUE(option12);
  382. EXPECT_EQ(12, option12->getType()); // this should be option 12
  383. ASSERT_EQ(3, option12->getValue().length()); // it should be of length 3
  384. EXPECT_EQ(5, option12->len()); // total option length 5
  385. EXPECT_EQ(0, memcmp(&option12->getValue()[0], v4_opts + 2, 3)); // data len=3
  386. x = options.find(60);
  387. ASSERT_FALSE(x == options.end()); // option 2 should exist
  388. EXPECT_EQ(60, x->second->getType()); // this should be option 60
  389. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  390. EXPECT_EQ(5, x->second->len()); // total option length 5
  391. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4_opts + 7, 3)); // data len=3
  392. x = options.find(14);
  393. ASSERT_FALSE(x == options.end()); // option 3 should exist
  394. OptionStringPtr option14 = boost::static_pointer_cast<OptionString>(x->second);
  395. ASSERT_TRUE(option14);
  396. EXPECT_EQ(14, option14->getType()); // this should be option 14
  397. ASSERT_EQ(3, option14->getValue().length()); // it should be of length 3
  398. EXPECT_EQ(5, option14->len()); // total option length 5
  399. EXPECT_EQ(0, memcmp(&option14->getValue()[0], v4_opts + 12, 3)); // data len=3
  400. x = options.find(254);
  401. ASSERT_FALSE(x == options.end()); // option 3 should exist
  402. EXPECT_EQ(254, x->second->getType()); // this should be option 254
  403. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  404. EXPECT_EQ(5, x->second->len()); // total option length 5
  405. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4_opts + 17, 3)); // data len=3
  406. x = options.find(128);
  407. ASSERT_FALSE(x == options.end()); // option 3 should exist
  408. EXPECT_EQ(128, x->second->getType()); // this should be option 254
  409. ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
  410. EXPECT_EQ(5, x->second->len()); // total option length 5
  411. EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4_opts + 22, 3)); // data len=3
  412. x = options.find(0);
  413. EXPECT_TRUE(x == options.end()); // option 0 not found
  414. x = options.find(1);
  415. EXPECT_TRUE(x == options.end()); // option 1 not found
  416. x = options.find(2);
  417. EXPECT_TRUE(x == options.end()); // option 2 not found
  418. }
  419. TEST_F(LibDhcpTest, isStandardOption4) {
  420. // Get all option codes that are not occupied by standard options.
  421. const uint16_t unassigned_codes[] = { 84, 96, 102, 103, 104, 105, 106, 107, 108,
  422. 109, 110, 111, 115, 126, 127, 147, 148, 149,
  423. 178, 179, 180, 181, 182, 183, 184, 185, 186,
  424. 187, 188, 189, 190, 191, 192, 193, 194, 195,
  425. 196, 197, 198, 199, 200, 201, 202, 203, 204,
  426. 205, 206, 207, 214, 215, 216, 217, 218, 219,
  427. 222, 223 };
  428. const size_t unassigned_num = sizeof(unassigned_codes) / sizeof(unassigned_codes[0]);
  429. // Try all possible option codes.
  430. for (size_t i = 0; i < 256; ++i) {
  431. // Some ranges of option codes are unassigned and thus the isStandardOption
  432. // should return false for them.
  433. bool check_unassigned = false;
  434. // Check the array of unassigned options to find out whether option code
  435. // is assigned to standard option or unassigned.
  436. for (size_t j = 0; j < unassigned_num; ++j) {
  437. // If option code is found within the array of unassigned options
  438. // we the isStandardOption function should return false.
  439. if (unassigned_codes[j] == i) {
  440. check_unassigned = true;
  441. EXPECT_FALSE(LibDHCP::isStandardOption(Option::V4,
  442. unassigned_codes[j]))
  443. << "Test failed for option code " << unassigned_codes[j];
  444. break;
  445. }
  446. }
  447. // If the option code belongs to the standard option then the
  448. // isStandardOption should return true.
  449. if (!check_unassigned) {
  450. EXPECT_TRUE(LibDHCP::isStandardOption(Option::V4, i))
  451. << "Test failed for the option code " << i;
  452. }
  453. }
  454. }
  455. TEST_F(LibDhcpTest, isStandardOption6) {
  456. // All option codes in the range from 0 to 78 (except 10 and 35)
  457. // identify the standard options.
  458. for (uint16_t code = 0; code < 79; ++code) {
  459. if (code != 10 && code != 35) {
  460. EXPECT_TRUE(LibDHCP::isStandardOption(Option::V6, code))
  461. << "Test failed for option code " << code;
  462. }
  463. }
  464. // Check the option codes 10 and 35. They are unassigned.
  465. EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, 10));
  466. EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, 35));
  467. // Check a range of option codes above 78. Those are option codes
  468. // identifying non-standard options.
  469. for (uint16_t code = 79; code < 512; ++code) {
  470. EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, code))
  471. << "Test failed for option code " << code;
  472. }
  473. }
  474. TEST_F(LibDhcpTest, stdOptionDefs4) {
  475. // Create a buffer that holds dummy option data.
  476. // It will be used to create most of the options.
  477. std::vector<uint8_t> buf(48, 1);
  478. OptionBufferConstIter begin = buf.begin();
  479. OptionBufferConstIter end = buf.end();
  480. LibDhcpTest::testStdOptionDefs4(DHO_SUBNET_MASK, begin, end,
  481. typeid(OptionCustom));
  482. LibDhcpTest::testStdOptionDefs4(DHO_TIME_OFFSET, begin, begin + 4,
  483. typeid(OptionInt<uint32_t>));
  484. LibDhcpTest::testStdOptionDefs4(DHO_ROUTERS, begin, end,
  485. typeid(Option4AddrLst));
  486. LibDhcpTest::testStdOptionDefs4(DHO_TIME_SERVERS, begin, end,
  487. typeid(Option4AddrLst));
  488. LibDhcpTest::testStdOptionDefs4(DHO_NAME_SERVERS, begin, end,
  489. typeid(OptionCustom));
  490. LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_NAME_SERVERS, begin, end,
  491. typeid(Option4AddrLst));
  492. LibDhcpTest::testStdOptionDefs4(DHO_LOG_SERVERS, begin, end,
  493. typeid(Option4AddrLst));
  494. LibDhcpTest::testStdOptionDefs4(DHO_COOKIE_SERVERS, begin, end,
  495. typeid(Option4AddrLst));
  496. LibDhcpTest::testStdOptionDefs4(DHO_LPR_SERVERS, begin, end,
  497. typeid(Option4AddrLst));
  498. LibDhcpTest::testStdOptionDefs4(DHO_IMPRESS_SERVERS, begin, end,
  499. typeid(Option4AddrLst));
  500. LibDhcpTest::testStdOptionDefs4(DHO_RESOURCE_LOCATION_SERVERS, begin, end,
  501. typeid(Option4AddrLst));
  502. LibDhcpTest::testStdOptionDefs4(DHO_HOST_NAME, begin, end,
  503. typeid(OptionString));
  504. LibDhcpTest::testStdOptionDefs4(DHO_BOOT_SIZE, begin, begin + 2,
  505. typeid(OptionInt<uint16_t>));
  506. LibDhcpTest::testStdOptionDefs4(DHO_MERIT_DUMP, begin, end,
  507. typeid(OptionString));
  508. LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_NAME, begin, end,
  509. typeid(OptionString));
  510. LibDhcpTest::testStdOptionDefs4(DHO_SWAP_SERVER, begin, end,
  511. typeid(OptionCustom));
  512. LibDhcpTest::testStdOptionDefs4(DHO_ROOT_PATH, begin, end,
  513. typeid(OptionString));
  514. LibDhcpTest::testStdOptionDefs4(DHO_EXTENSIONS_PATH, begin, end,
  515. typeid(OptionString));
  516. LibDhcpTest::testStdOptionDefs4(DHO_IP_FORWARDING, begin, end,
  517. typeid(OptionCustom));
  518. LibDhcpTest::testStdOptionDefs4(DHO_NON_LOCAL_SOURCE_ROUTING, begin, end,
  519. typeid(OptionCustom));
  520. LibDhcpTest::testStdOptionDefs4(DHO_POLICY_FILTER, begin, end,
  521. typeid(Option4AddrLst));
  522. LibDhcpTest::testStdOptionDefs4(DHO_MAX_DGRAM_REASSEMBLY, begin, begin + 2,
  523. typeid(OptionInt<uint16_t>));
  524. LibDhcpTest::testStdOptionDefs4(DHO_DEFAULT_IP_TTL, begin, begin + 1,
  525. typeid(OptionInt<uint8_t>));
  526. LibDhcpTest::testStdOptionDefs4(DHO_PATH_MTU_AGING_TIMEOUT, begin, begin + 4,
  527. typeid(OptionInt<uint32_t>));
  528. LibDhcpTest::testStdOptionDefs4(DHO_PATH_MTU_PLATEAU_TABLE, begin, begin + 10,
  529. typeid(OptionIntArray<uint16_t>));
  530. LibDhcpTest::testStdOptionDefs4(DHO_INTERFACE_MTU, begin, begin + 2,
  531. typeid(OptionInt<uint16_t>));
  532. LibDhcpTest::testStdOptionDefs4(DHO_ALL_SUBNETS_LOCAL, begin, end,
  533. typeid(OptionCustom));
  534. LibDhcpTest::testStdOptionDefs4(DHO_BROADCAST_ADDRESS, begin, end,
  535. typeid(OptionCustom));
  536. LibDhcpTest::testStdOptionDefs4(DHO_PERFORM_MASK_DISCOVERY, begin, end,
  537. typeid(OptionCustom));
  538. LibDhcpTest::testStdOptionDefs4(DHO_MASK_SUPPLIER, begin, end,
  539. typeid(OptionCustom));
  540. LibDhcpTest::testStdOptionDefs4(DHO_ROUTER_DISCOVERY, begin, end,
  541. typeid(OptionCustom));
  542. LibDhcpTest::testStdOptionDefs4(DHO_ROUTER_SOLICITATION_ADDRESS, begin, end,
  543. typeid(OptionCustom));
  544. LibDhcpTest::testStdOptionDefs4(DHO_STATIC_ROUTES, begin, end,
  545. typeid(Option4AddrLst));
  546. LibDhcpTest::testStdOptionDefs4(DHO_TRAILER_ENCAPSULATION, begin, end,
  547. typeid(OptionCustom));
  548. LibDhcpTest::testStdOptionDefs4(DHO_ARP_CACHE_TIMEOUT, begin, begin + 4,
  549. typeid(OptionInt<uint32_t>));
  550. LibDhcpTest::testStdOptionDefs4(DHO_IEEE802_3_ENCAPSULATION, begin, end,
  551. typeid(OptionCustom));
  552. LibDhcpTest::testStdOptionDefs4(DHO_DEFAULT_TCP_TTL, begin, begin + 1,
  553. typeid(OptionInt<uint8_t>));
  554. LibDhcpTest::testStdOptionDefs4(DHO_TCP_KEEPALIVE_INTERVAL, begin, begin + 4,
  555. typeid(OptionInt<uint32_t>));
  556. LibDhcpTest::testStdOptionDefs4(DHO_TCP_KEEPALIVE_GARBAGE, begin, begin + 1,
  557. typeid(OptionCustom));
  558. LibDhcpTest::testStdOptionDefs4(DHO_NIS_DOMAIN, begin, end,
  559. typeid(OptionString));
  560. LibDhcpTest::testStdOptionDefs4(DHO_NIS_SERVERS, begin, end,
  561. typeid(Option4AddrLst));
  562. LibDhcpTest::testStdOptionDefs4(DHO_NTP_SERVERS, begin, end,
  563. typeid(Option4AddrLst));
  564. LibDhcpTest::testStdOptionDefs4(DHO_VENDOR_ENCAPSULATED_OPTIONS, begin, end,
  565. typeid(Option),
  566. "vendor-encapsulated-options-space");
  567. LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_NAME_SERVERS, begin, end,
  568. typeid(Option4AddrLst));
  569. LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_DD_SERVER, begin, end,
  570. typeid(Option4AddrLst));
  571. LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_NODE_TYPE, begin, begin + 1,
  572. typeid(OptionInt<uint8_t>));
  573. LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_SCOPE, begin, end,
  574. typeid(OptionString));
  575. LibDhcpTest::testStdOptionDefs4(DHO_FONT_SERVERS, begin, end,
  576. typeid(Option4AddrLst));
  577. LibDhcpTest::testStdOptionDefs4(DHO_X_DISPLAY_MANAGER, begin, end,
  578. typeid(Option4AddrLst));
  579. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_REQUESTED_ADDRESS, begin, end,
  580. typeid(OptionCustom));
  581. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_LEASE_TIME, begin, begin + 4,
  582. typeid(OptionInt<uint32_t>));
  583. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_OPTION_OVERLOAD, begin, begin + 1,
  584. typeid(OptionInt<uint8_t>));
  585. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_MESSAGE_TYPE, begin, begin + 1,
  586. typeid(OptionInt<uint8_t>));
  587. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_SERVER_IDENTIFIER, begin, end,
  588. typeid(OptionCustom));
  589. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_PARAMETER_REQUEST_LIST, begin, end,
  590. typeid(Option));
  591. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_MESSAGE, begin, end,
  592. typeid(OptionString));
  593. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_MAX_MESSAGE_SIZE, begin, begin + 2,
  594. typeid(OptionInt<uint16_t>));
  595. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_RENEWAL_TIME, begin, begin + 4,
  596. typeid(OptionInt<uint32_t>));
  597. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_REBINDING_TIME, begin, begin + 4,
  598. typeid(OptionInt<uint32_t>));
  599. LibDhcpTest::testStdOptionDefs4(DHO_VENDOR_CLASS_IDENTIFIER, begin, end,
  600. typeid(Option));
  601. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_CLIENT_IDENTIFIER, begin, end,
  602. typeid(Option));
  603. LibDhcpTest::testStdOptionDefs4(DHO_NWIP_DOMAIN_NAME, begin, end,
  604. typeid(OptionString));
  605. LibDhcpTest::testStdOptionDefs4(DHO_NWIP_SUBOPTIONS, begin, end,
  606. typeid(Option));
  607. LibDhcpTest::testStdOptionDefs4(DHO_USER_CLASS, begin, end,
  608. typeid(Option));
  609. LibDhcpTest::testStdOptionDefs4(DHO_FQDN, begin, end,
  610. typeid(OptionCustom));
  611. LibDhcpTest::testStdOptionDefs4(DHO_DHCP_AGENT_OPTIONS, begin, end,
  612. typeid(Option), "dhcp-agent-options-space");
  613. LibDhcpTest::testStdOptionDefs4(DHO_AUTHENTICATE, begin, end,
  614. typeid(Option));
  615. LibDhcpTest::testStdOptionDefs4(DHO_CLIENT_LAST_TRANSACTION_TIME,
  616. begin, begin + 4,
  617. typeid(OptionInt<uint32_t>));
  618. LibDhcpTest::testStdOptionDefs4(DHO_ASSOCIATED_IP, begin, end,
  619. typeid(Option4AddrLst));
  620. LibDhcpTest::testStdOptionDefs4(DHO_SUBNET_SELECTION, begin, end,
  621. typeid(OptionCustom));
  622. LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_SEARCH, begin, end,
  623. typeid(Option));
  624. LibDhcpTest::testStdOptionDefs4(DHO_VIVCO_SUBOPTIONS, begin, end,
  625. typeid(Option));
  626. LibDhcpTest::testStdOptionDefs4(DHO_VIVSO_SUBOPTIONS, begin, end,
  627. typeid(Option));
  628. }
  629. // Test that definitions of standard options have been initialized
  630. // correctly.
  631. // @todo Only limited number of option definitions are now created
  632. // This test have to be extended once all option definitions are
  633. // created.
  634. TEST_F(LibDhcpTest, stdOptionDefs6) {
  635. // Create a buffer that holds dummy option data.
  636. // It will be used to create most of the options.
  637. std::vector<uint8_t> buf(48, 1);
  638. OptionBufferConstIter begin = buf.begin();
  639. OptionBufferConstIter end = buf.end();
  640. // Prepare buffer holding an array of FQDNs.
  641. const char data[] = {
  642. 8, 109, 121, 100, 111, 109, 97, 105, 110, // "mydomain"
  643. 7, 101, 120, 97, 109, 112, 108, 101, // "example"
  644. 3, 99, 111, 109, // "com"
  645. 0,
  646. 7, 101, 120, 97, 109, 112, 108, 101, // "example"
  647. 3, 99, 111, 109, // "com"
  648. 0
  649. };
  650. // Initialize a vector with the FQDN data.
  651. std::vector<uint8_t> fqdn_buf(data, data + sizeof(data));
  652. // The CLIENT_FQDN holds a uint8_t value and FQDN. We have
  653. // to add the uint8_t value to it and then append the buffer
  654. // holding some valid FQDN.
  655. std::vector<uint8_t> client_fqdn_buf(1);
  656. client_fqdn_buf.insert(client_fqdn_buf.end(), fqdn_buf.begin(),
  657. fqdn_buf.end());
  658. // The actual test starts here for all supported option codes.
  659. LibDhcpTest::testStdOptionDefs6(D6O_CLIENTID, begin, end,
  660. typeid(Option));
  661. LibDhcpTest::testStdOptionDefs6(D6O_SERVERID, begin, end,
  662. typeid(Option));
  663. LibDhcpTest::testStdOptionDefs6(D6O_IA_NA, begin, end,
  664. typeid(Option6IA));
  665. LibDhcpTest::testStdOptionDefs6(D6O_IA_TA, begin, begin + 4,
  666. typeid(OptionInt<uint32_t>));
  667. LibDhcpTest::testStdOptionDefs6(D6O_IAADDR, begin, end,
  668. typeid(Option6IAAddr));
  669. LibDhcpTest::testStdOptionDefs6(D6O_ORO, begin, end,
  670. typeid(OptionIntArray<uint16_t>));
  671. LibDhcpTest::testStdOptionDefs6(D6O_PREFERENCE, begin, begin + 1,
  672. typeid(OptionInt<uint8_t>));
  673. LibDhcpTest::testStdOptionDefs6(D6O_ELAPSED_TIME, begin, begin + 2,
  674. typeid(OptionInt<uint16_t>));
  675. LibDhcpTest::testStdOptionDefs6(D6O_RELAY_MSG, begin, end,
  676. typeid(Option));
  677. LibDhcpTest::testStdOptionDefs6(D6O_STATUS_CODE, begin, end,
  678. typeid(OptionCustom));
  679. LibDhcpTest::testStdOptionDefs6(D6O_RAPID_COMMIT, begin, end,
  680. typeid(Option));
  681. LibDhcpTest::testStdOptionDefs6(D6O_USER_CLASS, begin, end,
  682. typeid(Option));
  683. LibDhcpTest::testStdOptionDefs6(D6O_VENDOR_CLASS, begin, end,
  684. typeid(OptionCustom));
  685. LibDhcpTest::testStdOptionDefs6(D6O_VENDOR_OPTS, begin, end,
  686. typeid(OptionInt<uint32_t>),
  687. "vendor-opts-space");
  688. LibDhcpTest::testStdOptionDefs6(D6O_INTERFACE_ID, begin, end,
  689. typeid(Option));
  690. LibDhcpTest::testStdOptionDefs6(D6O_RECONF_MSG, begin, begin + 1,
  691. typeid(OptionInt<uint8_t>));
  692. LibDhcpTest::testStdOptionDefs6(D6O_RECONF_ACCEPT, begin, end,
  693. typeid(Option));
  694. LibDhcpTest::testStdOptionDefs6(D6O_SIP_SERVERS_DNS, fqdn_buf.begin(),
  695. fqdn_buf.end(),
  696. typeid(OptionCustom));
  697. LibDhcpTest::testStdOptionDefs6(D6O_SIP_SERVERS_ADDR, begin, end,
  698. typeid(Option6AddrLst));
  699. LibDhcpTest::testStdOptionDefs6(D6O_NAME_SERVERS, begin, end,
  700. typeid(Option6AddrLst));
  701. LibDhcpTest::testStdOptionDefs6(D6O_DOMAIN_SEARCH, fqdn_buf.begin(),
  702. fqdn_buf.end(), typeid(OptionCustom));
  703. LibDhcpTest::testStdOptionDefs6(D6O_IA_PD, begin, end,
  704. typeid(Option6IA));
  705. LibDhcpTest::testStdOptionDefs6(D6O_IAPREFIX, begin, end,
  706. typeid(OptionCustom));
  707. LibDhcpTest::testStdOptionDefs6(D6O_NIS_SERVERS, begin, end,
  708. typeid(Option6AddrLst));
  709. LibDhcpTest::testStdOptionDefs6(D6O_NISP_SERVERS, begin, end,
  710. typeid(Option6AddrLst));
  711. LibDhcpTest::testStdOptionDefs6(D6O_NIS_DOMAIN_NAME, fqdn_buf.begin(),
  712. fqdn_buf.end(),
  713. typeid(OptionCustom));
  714. LibDhcpTest::testStdOptionDefs6(D6O_NISP_DOMAIN_NAME, fqdn_buf.begin(),
  715. fqdn_buf.end(),
  716. typeid(OptionCustom));
  717. LibDhcpTest::testStdOptionDefs6(D6O_SNTP_SERVERS, begin, end,
  718. typeid(Option6AddrLst));
  719. LibDhcpTest::testStdOptionDefs6(D6O_INFORMATION_REFRESH_TIME,
  720. begin, begin + 4,
  721. typeid(OptionInt<uint32_t>));
  722. LibDhcpTest::testStdOptionDefs6(D6O_BCMCS_SERVER_D, fqdn_buf.begin(),
  723. fqdn_buf.end(),
  724. typeid(OptionCustom));
  725. LibDhcpTest::testStdOptionDefs6(D6O_BCMCS_SERVER_A, begin, end,
  726. typeid(Option6AddrLst));
  727. LibDhcpTest::testStdOptionDefs6(D6O_GEOCONF_CIVIC, begin, end,
  728. typeid(OptionCustom));
  729. LibDhcpTest::testStdOptionDefs6(D6O_REMOTE_ID, begin, end,
  730. typeid(OptionCustom));
  731. LibDhcpTest::testStdOptionDefs6(D6O_SUBSCRIBER_ID, begin, end,
  732. typeid(Option));
  733. LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_FQDN, client_fqdn_buf.begin(),
  734. client_fqdn_buf.end(),
  735. typeid(Option6ClientFqdn));
  736. LibDhcpTest::testStdOptionDefs6(D6O_PANA_AGENT, begin, end,
  737. typeid(Option6AddrLst));
  738. LibDhcpTest::testStdOptionDefs6(D6O_PANA_AGENT, begin, end,
  739. typeid(Option6AddrLst));
  740. LibDhcpTest::testStdOptionDefs6(D6O_NEW_POSIX_TIMEZONE, begin, end,
  741. typeid(OptionString));
  742. LibDhcpTest::testStdOptionDefs6(D6O_NEW_TZDB_TIMEZONE, begin, end,
  743. typeid(OptionString));
  744. LibDhcpTest::testStdOptionDefs6(D6O_ERO, begin, end,
  745. typeid(OptionIntArray<uint16_t>));
  746. LibDhcpTest::testStdOptionDefs6(D6O_LQ_QUERY, begin, end,
  747. typeid(OptionCustom));
  748. LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_DATA, begin, end,
  749. typeid(Option));
  750. LibDhcpTest::testStdOptionDefs6(D6O_CLT_TIME, begin, begin + 4,
  751. typeid(OptionInt<uint32_t>));
  752. LibDhcpTest::testStdOptionDefs6(D6O_LQ_RELAY_DATA, begin, end,
  753. typeid(OptionCustom));
  754. LibDhcpTest::testStdOptionDefs6(D6O_LQ_CLIENT_LINK, begin, end,
  755. typeid(Option6AddrLst));
  756. }
  757. }