option6_ia_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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/dhcp6.h>
  16. #include <dhcp/option.h>
  17. #include <dhcp/option6_ia.h>
  18. #include <dhcp/option6_iaaddr.h>
  19. #include <dhcp/option6_iaprefix.h>
  20. #include <util/buffer.h>
  21. #include <boost/scoped_ptr.hpp>
  22. #include <gtest/gtest.h>
  23. #include <iostream>
  24. #include <sstream>
  25. #include <arpa/inet.h>
  26. using namespace std;
  27. using namespace isc;
  28. using namespace isc::dhcp;
  29. using namespace isc::asiolink;
  30. using namespace isc::util;
  31. using boost::scoped_ptr;
  32. namespace {
  33. class Option6IATest : public ::testing::Test {
  34. public:
  35. Option6IATest(): buf_(255), outBuf_(255) {
  36. for (unsigned i = 0; i < 255; i++) {
  37. buf_[i] = 255 - i;
  38. }
  39. }
  40. /// @brief performs basic checks on IA option
  41. ///
  42. /// Check that an option can be built based on incoming buffer and that
  43. /// the option contains expected values.
  44. /// @param type specifies option type (IA_NA or IA_PD)
  45. void checkIA(uint16_t type) {
  46. buf_[0] = 0xa1; // iaid
  47. buf_[1] = 0xa2;
  48. buf_[2] = 0xa3;
  49. buf_[3] = 0xa4;
  50. buf_[4] = 0x81; // T1
  51. buf_[5] = 0x02;
  52. buf_[6] = 0x03;
  53. buf_[7] = 0x04;
  54. buf_[8] = 0x84; // T2
  55. buf_[9] = 0x03;
  56. buf_[10] = 0x02;
  57. buf_[11] = 0x01;
  58. // Create an option
  59. // unpack() is called from constructor
  60. scoped_ptr<Option6IA> opt;
  61. ASSERT_NO_THROW(opt.reset(new Option6IA(type, buf_.begin(),
  62. buf_.begin() + 12)));
  63. EXPECT_EQ(Option::V6, opt->getUniverse());
  64. EXPECT_EQ(type, opt->getType());
  65. EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
  66. EXPECT_EQ(0x81020304, opt->getT1());
  67. EXPECT_EQ(0x84030201, opt->getT2());
  68. // Pack this option again in the same buffer, but in
  69. // different place
  70. // Test for pack()
  71. ASSERT_NO_THROW(opt->pack(outBuf_));
  72. // 12 bytes header + 4 bytes content
  73. EXPECT_EQ(12, opt->len() - opt->getHeaderLen());
  74. EXPECT_EQ(type, opt->getType());
  75. EXPECT_EQ(16, outBuf_.getLength()); // lenght(IA_NA) = 16
  76. // Check if pack worked properly:
  77. InputBuffer out(outBuf_.getData(), outBuf_.getLength());
  78. // - if option type is correct
  79. EXPECT_EQ(type, out.readUint16());
  80. // - if option length is correct
  81. EXPECT_EQ(12, out.readUint16());
  82. // - if iaid is correct
  83. EXPECT_EQ(0xa1a2a3a4, out.readUint32() );
  84. // - if T1 is correct
  85. EXPECT_EQ(0x81020304, out.readUint32() );
  86. // - if T1 is correct
  87. EXPECT_EQ(0x84030201, out.readUint32() );
  88. EXPECT_NO_THROW(opt.reset());
  89. }
  90. OptionBuffer buf_;
  91. OutputBuffer outBuf_;
  92. };
  93. TEST_F(Option6IATest, basic) {
  94. checkIA(D6O_IA_NA);
  95. }
  96. TEST_F(Option6IATest, pdBasic) {
  97. checkIA(D6O_IA_PD);
  98. }
  99. // Check that this class cannot be used for IA_TA (IA_TA has no T1, T2 fields
  100. // and people tend to think that if it's good for IA_NA and IA_PD, it can
  101. // be used for IA_TA as well and that is not true)
  102. TEST_F(Option6IATest, taForbidden) {
  103. EXPECT_THROW(Option6IA(D6O_IA_TA, buf_.begin(), buf_.begin() + 50),
  104. BadValue);
  105. EXPECT_THROW(Option6IA(D6O_IA_TA, 123), BadValue);
  106. }
  107. // Check that getters/setters are working as expected.
  108. TEST_F(Option6IATest, simple) {
  109. scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_NA, 1234));
  110. // Check that the values are really different than what we are about
  111. // to set them to.
  112. EXPECT_NE(2345, ia->getT1());
  113. EXPECT_NE(3456, ia->getT2());
  114. ia->setT1(2345);
  115. ia->setT2(3456);
  116. EXPECT_EQ(Option::V6, ia->getUniverse());
  117. EXPECT_EQ(D6O_IA_NA, ia->getType());
  118. EXPECT_EQ(1234, ia->getIAID());
  119. EXPECT_EQ(2345, ia->getT1());
  120. EXPECT_EQ(3456, ia->getT2());
  121. ia->setIAID(890);
  122. EXPECT_EQ(890, ia->getIAID());
  123. EXPECT_NO_THROW(ia.reset());
  124. }
  125. // test if the option can build suboptions
  126. TEST_F(Option6IATest, suboptionsPack) {
  127. scoped_ptr<Option6IA> ia(new Option6IA(D6O_IA_NA, 0x13579ace));
  128. ia->setT1(0x2345);
  129. ia->setT2(0x3456);
  130. OptionPtr sub1(new Option(Option::V6, 0xcafe));
  131. boost::shared_ptr<Option6IAAddr> addr1(
  132. new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1234:5678::abcd"), 0x5000, 0x7000));
  133. ia->addOption(sub1);
  134. ia->addOption(addr1);
  135. ASSERT_EQ(28, addr1->len());
  136. ASSERT_EQ(4, sub1->len());
  137. ASSERT_EQ(48, ia->len());
  138. // This contains expected on-wire format
  139. uint8_t expected[] = {
  140. D6O_IA_NA/256, D6O_IA_NA%256, // type
  141. 0, 44, // length
  142. 0x13, 0x57, 0x9a, 0xce, // iaid
  143. 0, 0, 0x23, 0x45, // T1
  144. 0, 0, 0x34, 0x56, // T2
  145. // iaaddr suboption
  146. D6O_IAADDR/256, D6O_IAADDR%256, // type
  147. 0, 24, // len
  148. 0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
  149. 0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
  150. 0, 0, 0x50, 0, // preferred-lifetime
  151. 0, 0, 0x70, 0, // valid-lifetime
  152. // suboption
  153. 0xca, 0xfe, // type
  154. 0, 0 // len
  155. };
  156. ia->pack(outBuf_);
  157. ASSERT_EQ(48, outBuf_.getLength());
  158. EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 48));
  159. EXPECT_NO_THROW(ia.reset());
  160. }
  161. // test if IA_PD option can build IAPREFIX suboptions
  162. TEST_F(Option6IATest, pdSuboptionsPack) {
  163. // Let's build IA_PD
  164. scoped_ptr<Option6IA> ia;
  165. ASSERT_NO_THROW(ia.reset(new Option6IA(D6O_IA_PD, 0x13579ace)));
  166. ia->setT1(0x2345);
  167. ia->setT2(0x3456);
  168. // Put some dummy option in it
  169. OptionPtr sub1(new Option(Option::V6, 0xcafe));
  170. // Put a valid IAPREFIX option in it
  171. boost::shared_ptr<Option6IAPrefix> addr1(
  172. new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1234:5678::abcd"),
  173. 91, 0x5000, 0x7000));
  174. ia->addOption(sub1);
  175. ia->addOption(addr1);
  176. ASSERT_EQ(29, addr1->len());
  177. ASSERT_EQ(4, sub1->len());
  178. ASSERT_EQ(49, ia->len());
  179. uint8_t expected[] = {
  180. D6O_IA_PD/256, D6O_IA_PD%256, // type
  181. 0, 45, // length
  182. 0x13, 0x57, 0x9a, 0xce, // iaid
  183. 0, 0, 0x23, 0x45, // T1
  184. 0, 0, 0x34, 0x56, // T2
  185. // iaprefix suboption
  186. D6O_IAPREFIX/256, D6O_IAPREFIX%256, // type
  187. 0, 25, // len
  188. 0, 0, 0x50, 0, // preferred-lifetime
  189. 0, 0, 0x70, 0, // valid-lifetime
  190. 91, // prefix length
  191. 0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
  192. 0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
  193. // suboption
  194. 0xca, 0xfe, // type
  195. 0, 0 // len
  196. };
  197. ia->pack(outBuf_);
  198. ASSERT_EQ(49, outBuf_.getLength());
  199. EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 49));
  200. EXPECT_NO_THROW(ia.reset());
  201. }
  202. // test if option can parse suboptions
  203. TEST_F(Option6IATest, suboptionsUnpack) {
  204. // sizeof (expected) = 48 bytes
  205. const uint8_t expected[] = {
  206. D6O_IA_NA / 256, D6O_IA_NA % 256, // type
  207. 0, 28, // length
  208. 0x13, 0x57, 0x9a, 0xce, // iaid
  209. 0, 0, 0x23, 0x45, // T1
  210. 0, 0, 0x34, 0x56, // T2
  211. // iaaddr suboption
  212. D6O_IAADDR / 256, D6O_IAADDR % 256, // type
  213. 0, 24, // len
  214. 0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
  215. 0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
  216. 0, 0, 0x50, 0, // preferred-lifetime
  217. 0, 0, 0x70, 0, // valid-lifetime
  218. // suboption
  219. 0xca, 0xfe, // type
  220. 0, 0 // len
  221. };
  222. ASSERT_EQ(48, sizeof(expected));
  223. memcpy(&buf_[0], expected, sizeof(expected));
  224. scoped_ptr<Option6IA> ia;
  225. EXPECT_NO_THROW(
  226. ia.reset(new Option6IA(D6O_IA_NA, buf_.begin() + 4,
  227. buf_.begin() + sizeof(expected)));
  228. );
  229. ASSERT_TRUE(ia);
  230. EXPECT_EQ(D6O_IA_NA, ia->getType());
  231. EXPECT_EQ(0x13579ace, ia->getIAID());
  232. EXPECT_EQ(0x2345, ia->getT1());
  233. EXPECT_EQ(0x3456, ia->getT2());
  234. OptionPtr subopt = ia->getOption(D6O_IAADDR);
  235. ASSERT_NE(OptionPtr(), subopt); // non-NULL
  236. // Checks for address option
  237. Option6IAAddr * addr = dynamic_cast<Option6IAAddr*>(subopt.get());
  238. ASSERT_TRUE(NULL != addr);
  239. EXPECT_EQ(D6O_IAADDR, addr->getType());
  240. EXPECT_EQ(28, addr->len());
  241. EXPECT_EQ(0x5000, addr->getPreferred());
  242. EXPECT_EQ(0x7000, addr->getValid());
  243. EXPECT_EQ("2001:db8:1234:5678::abcd", addr->getAddress().toText());
  244. // Checks for dummy option
  245. subopt = ia->getOption(0xcafe);
  246. ASSERT_TRUE(subopt); // should be non-NULL
  247. EXPECT_EQ(0xcafe, subopt->getType());
  248. EXPECT_EQ(4, subopt->len());
  249. // There should be no data at all
  250. EXPECT_EQ(0, subopt->getData().size());
  251. subopt = ia->getOption(1); // get option 1
  252. ASSERT_FALSE(subopt); // should be NULL
  253. EXPECT_NO_THROW(ia.reset());
  254. }
  255. // This test checks that the IA_NA option is correctly converted to the
  256. // textual format.
  257. TEST_F(Option6IATest, toTextNA) {
  258. Option6IA ia(D6O_IA_NA, 1234);
  259. ia.setT1(200);
  260. ia.setT2(300);
  261. ia.addOption(OptionPtr(new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1::1"),
  262. 500, 600)));
  263. ia.addOption(OptionPtr(new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1::2"),
  264. 450, 550)));
  265. EXPECT_EQ("type=00003(IA_NA), len=00068: iaid=1234, t1=200, t2=300,\n"
  266. "options:\n"
  267. " type=00005(IAADDR), len=00024: address=2001:db8:1::1, "
  268. "preferred-lft=500, valid-lft=600\n"
  269. " type=00005(IAADDR), len=00024: address=2001:db8:1::2, "
  270. "preferred-lft=450, valid-lft=550", ia.toText());
  271. }
  272. // This test checks that the IA_PD option is correctly converted to the
  273. // textual format.
  274. TEST_F(Option6IATest, toTextPD) {
  275. Option6IA ia(D6O_IA_PD, 2345);
  276. ia.setT1(200);
  277. ia.setT2(300);
  278. ia.addOption(OptionPtr(new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1::"),
  279. 72, 500, 600)));
  280. ia.addOption(OptionPtr(new Option6IAPrefix(D6O_IAPREFIX, IOAddress("2001:db8:1::"),
  281. 64, 450, 550)));
  282. EXPECT_EQ("type=00025(IA_PD), len=00070: iaid=2345, t1=200, t2=300,\n"
  283. "options:\n"
  284. " type=00026(IAPREFIX), len=00025: prefix=2001:db8:1::/72, "
  285. "preferred-lft=500, valid-lft=600\n"
  286. " type=00026(IAPREFIX), len=00025: prefix=2001:db8:1::/64, "
  287. "preferred-lft=450, valid-lft=550",
  288. ia.toText());
  289. }
  290. }