libdhcp++_unittest.cc 48 KB

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