option6_addrlst_unittest.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 <asiolink/io_address.h>
  16. #include <dhcp/dhcp6.h>
  17. #include <dhcp/option.h>
  18. #include <dhcp/option6_addrlst.h>
  19. #include <util/buffer.h>
  20. #include <gtest/gtest.h>
  21. #include <boost/scoped_ptr.hpp>
  22. #include <iostream>
  23. #include <sstream>
  24. #include <arpa/inet.h>
  25. using namespace std;
  26. using namespace isc;
  27. using namespace isc::dhcp;
  28. using namespace isc::asiolink;
  29. using namespace isc::util;
  30. using boost::scoped_ptr;
  31. namespace {
  32. class Option6AddrLstTest : public ::testing::Test {
  33. public:
  34. Option6AddrLstTest(): buf_(255), outBuf_(255) {
  35. for (unsigned i = 0; i < 255; i++) {
  36. buf_[i] = 255 - i;
  37. }
  38. }
  39. OptionBuffer buf_;
  40. OutputBuffer outBuf_;
  41. };
  42. TEST_F(Option6AddrLstTest, basic) {
  43. // Limiting tests to just a 2001:db8::/32 is *wrong*.
  44. // Good tests check corner cases as well.
  45. // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff checks
  46. // for integer overflow.
  47. // ff02::face:b00c checks if multicast addresses
  48. // can be represented properly.
  49. uint8_t sampledata[] = {
  50. // 2001:db8:1::dead:beef
  51. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
  52. 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
  53. // ff02::face:b00c
  54. 0xff, 02, 0, 0, 0, 0, 0 , 0,
  55. 0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
  56. // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
  57. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  58. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  59. };
  60. uint8_t expected1[] = {
  61. D6O_NAME_SERVERS/256, D6O_NAME_SERVERS%256,//type
  62. 0, 16, // len = 16 (1 address)
  63. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
  64. 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
  65. };
  66. uint8_t expected2[] = {
  67. D6O_SIP_SERVERS_ADDR/256, D6O_SIP_SERVERS_ADDR%256,
  68. 0, 32, // len = 32 (2 addresses)
  69. // 2001:db8:1::dead:beef
  70. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
  71. 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
  72. // ff02::face:b00c
  73. 0xff, 02, 0, 0, 0, 0, 0 , 0,
  74. 0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
  75. // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
  76. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  77. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  78. };
  79. uint8_t expected3[] = {
  80. D6O_NIS_SERVERS/256, D6O_NIS_SERVERS%256,
  81. 0, 48,
  82. // 2001:db8:1::dead:beef
  83. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
  84. 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
  85. // ff02::face:b00c
  86. 0xff, 02, 0, 0, 0, 0, 0 , 0,
  87. 0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
  88. // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
  89. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  90. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  91. };
  92. memcpy(&buf_[0], sampledata, 48);
  93. // Just a single address
  94. scoped_ptr<Option6AddrLst> opt1;
  95. EXPECT_NO_THROW(
  96. opt1.reset(new Option6AddrLst(D6O_NAME_SERVERS,
  97. buf_.begin(), buf_.begin() + 16));
  98. );
  99. EXPECT_EQ(Option::V6, opt1->getUniverse());
  100. EXPECT_EQ(D6O_NAME_SERVERS, opt1->getType());
  101. EXPECT_EQ(20, opt1->len());
  102. Option6AddrLst::AddressContainer addrs = opt1->getAddresses();
  103. ASSERT_EQ(1, addrs.size());
  104. IOAddress addr = addrs[0];
  105. EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
  106. // Pack this option
  107. opt1->pack(outBuf_);
  108. EXPECT_EQ(20, outBuf_.getLength());
  109. EXPECT_EQ(0, memcmp(expected1, outBuf_.getData(), 20));
  110. // Two addresses
  111. scoped_ptr<Option6AddrLst> opt2;
  112. EXPECT_NO_THROW(
  113. opt2.reset(new Option6AddrLst(D6O_SIP_SERVERS_ADDR,
  114. buf_.begin(), buf_.begin() + 32));
  115. );
  116. EXPECT_EQ(D6O_SIP_SERVERS_ADDR, opt2->getType());
  117. EXPECT_EQ(36, opt2->len());
  118. addrs = opt2->getAddresses();
  119. ASSERT_EQ(2, addrs.size());
  120. EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
  121. EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
  122. // Pack this option
  123. outBuf_.clear();
  124. opt2->pack(outBuf_);
  125. EXPECT_EQ(36, outBuf_.getLength() );
  126. EXPECT_EQ(0, memcmp(expected2, outBuf_.getData(), 36));
  127. // Three addresses
  128. scoped_ptr<Option6AddrLst> opt3;
  129. EXPECT_NO_THROW(
  130. opt3.reset(new Option6AddrLst(D6O_NIS_SERVERS,
  131. buf_.begin(), buf_.begin() + 48));
  132. );
  133. EXPECT_EQ(D6O_NIS_SERVERS, opt3->getType());
  134. EXPECT_EQ(52, opt3->len());
  135. addrs = opt3->getAddresses();
  136. ASSERT_EQ(3, addrs.size());
  137. EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
  138. EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
  139. EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", addrs[2].toText());
  140. // Pack this option
  141. outBuf_.clear();
  142. opt3->pack(outBuf_);
  143. EXPECT_EQ(52, outBuf_.getLength());
  144. EXPECT_EQ(0, memcmp(expected3, outBuf_.getData(), 52));
  145. EXPECT_NO_THROW(opt1.reset());
  146. EXPECT_NO_THROW(opt2.reset());
  147. EXPECT_NO_THROW(opt3.reset());
  148. }
  149. TEST_F(Option6AddrLstTest, constructors) {
  150. scoped_ptr<Option6AddrLst> opt1;
  151. EXPECT_NO_THROW(
  152. opt1.reset(new Option6AddrLst(1234, IOAddress("::1")));
  153. );
  154. EXPECT_EQ(Option::V6, opt1->getUniverse());
  155. EXPECT_EQ(1234, opt1->getType());
  156. Option6AddrLst::AddressContainer addrs = opt1->getAddresses();
  157. ASSERT_EQ(1, addrs.size() );
  158. EXPECT_EQ("::1", addrs[0].toText());
  159. addrs.clear();
  160. addrs.push_back(IOAddress(string("fe80::1234")));
  161. addrs.push_back(IOAddress(string("2001:db8:1::baca")));
  162. scoped_ptr<Option6AddrLst> opt2;
  163. EXPECT_NO_THROW(
  164. opt2.reset(new Option6AddrLst(5678, addrs));
  165. );
  166. Option6AddrLst::AddressContainer check = opt2->getAddresses();
  167. ASSERT_EQ(2, check.size() );
  168. EXPECT_EQ("fe80::1234", check[0].toText());
  169. EXPECT_EQ("2001:db8:1::baca", check[1].toText());
  170. EXPECT_NO_THROW(opt1.reset());
  171. EXPECT_NO_THROW(opt2.reset());
  172. }
  173. TEST_F(Option6AddrLstTest, setAddress) {
  174. scoped_ptr<Option6AddrLst> opt1;
  175. EXPECT_NO_THROW(
  176. opt1.reset(new Option6AddrLst(1234, IOAddress("::1")));
  177. );
  178. opt1->setAddress(IOAddress("2001:db8:1::2"));
  179. /// TODO It used to be ::2 address, but io_address represents
  180. /// it as ::0.0.0.2. Purpose of this test is to verify
  181. /// that setAddress() works, not deal with subtleties of
  182. /// io_address handling of IPv4-mapped IPv6 addresses, we
  183. /// switched to a more common address. User interested
  184. /// in pursuing this matter further is encouraged to look
  185. /// at section 2.5.5 of RFC4291 (and possibly implement
  186. /// a test for IOAddress)
  187. Option6AddrLst::AddressContainer addrs = opt1->getAddresses();
  188. ASSERT_EQ(1, addrs.size());
  189. EXPECT_EQ("2001:db8:1::2", addrs[0].toText());
  190. EXPECT_NO_THROW(opt1.reset());
  191. }
  192. // This test checks that the option holding IPv6 address list can
  193. // be converted to textual format.
  194. TEST_F(Option6AddrLstTest, toText) {
  195. Option6AddrLst opt(1234, IOAddress("2001:db8:1::1"));
  196. // Generate a few IPv6 addresses.
  197. Option6AddrLst::AddressContainer addresses;
  198. for (int i = 2; i < 6; ++i) {
  199. std::stringstream s;
  200. s << "2001:db8:1::" << i;
  201. addresses.push_back(IOAddress(s.str()));
  202. }
  203. opt.setAddresses(addresses);
  204. EXPECT_EQ("type=01234, len=00064: 2001:db8:1::2 2001:db8:1::3 "
  205. "2001:db8:1::4 2001:db8:1::5", opt.toText());
  206. }
  207. } // namespace