libdhcp++_unittest.cc 57 KB

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