pkt6_unittest.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Copyright (C) 2011-2012 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/pkt6.h>
  19. #include <boost/date_time/posix_time/posix_time.hpp>
  20. #include <gtest/gtest.h>
  21. #include <iostream>
  22. #include <sstream>
  23. #include <arpa/inet.h>
  24. using namespace std;
  25. using namespace isc;
  26. using namespace isc::asiolink;
  27. using namespace isc::dhcp;
  28. namespace {
  29. // empty class for now, but may be extended once Addr6 becomes bigger
  30. class Pkt6Test : public ::testing::Test {
  31. public:
  32. Pkt6Test() {
  33. }
  34. };
  35. TEST_F(Pkt6Test, constructor) {
  36. uint8_t data[] = { 0, 1, 2, 3, 4, 5 };
  37. Pkt6 * pkt1 = new Pkt6(data, sizeof(data) );
  38. EXPECT_EQ(6, pkt1->getData().size());
  39. EXPECT_EQ(0, memcmp( &pkt1->getData()[0], data, sizeof(data)));
  40. delete pkt1;
  41. }
  42. /// @brief returns captured actual SOLICIT packet
  43. ///
  44. /// Captured SOLICIT packet with transid=0x3d79fb and options: client-id,
  45. /// in_na, dns-server, elapsed-time, option-request
  46. /// This code was autogenerated (see src/bin/dhcp6/tests/iface_mgr_unittest.c),
  47. /// but we spent some time to make is less ugly than it used to be.
  48. ///
  49. /// @return pointer to Pkt6 that represents received SOLICIT
  50. Pkt6* capture1() {
  51. Pkt6* pkt;
  52. uint8_t data[98];
  53. data[0] = 1;
  54. data[1] = 1; data[2] = 2; data[3] = 3; data[4] = 0;
  55. data[5] = 1; data[6] = 0; data[7] = 14; data[8] = 0;
  56. data[9] = 1; data[10] = 0; data[11] = 1; data[12] = 21;
  57. data[13] = 158; data[14] = 60; data[15] = 22; data[16] = 0;
  58. data[17] = 30; data[18] = 140; data[19] = 155; data[20] = 115;
  59. data[21] = 73; data[22] = 0; data[23] = 3; data[24] = 0;
  60. data[25] = 40; data[26] = 0; data[27] = 0; data[28] = 0;
  61. data[29] = 1; data[30] = 255; data[31] = 255; data[32] = 255;
  62. data[33] = 255; data[34] = 255; data[35] = 255; data[36] = 255;
  63. data[37] = 255; data[38] = 0; data[39] = 5; data[40] = 0;
  64. data[41] = 24; data[42] = 32; data[43] = 1; data[44] = 13;
  65. data[45] = 184; data[46] = 0; data[47] = 1; data[48] = 0;
  66. data[49] = 0; data[50] = 0; data[51] = 0; data[52] = 0;
  67. data[53] = 0; data[54] = 0; data[55] = 0; data[56] = 18;
  68. data[57] = 52; data[58] = 255; data[59] = 255; data[60] = 255;
  69. data[61] = 255; data[62] = 255; data[63] = 255; data[64] = 255;
  70. data[65] = 255; data[66] = 0; data[67] = 23; data[68] = 0;
  71. data[69] = 16; data[70] = 32; data[71] = 1; data[72] = 13;
  72. data[73] = 184; data[74] = 0; data[75] = 1; data[76] = 0;
  73. data[77] = 0; data[78] = 0; data[79] = 0; data[80] = 0;
  74. data[81] = 0; data[82] = 0; data[83] = 0; data[84] = 221;
  75. data[85] = 221; data[86] = 0; data[87] = 8; data[88] = 0;
  76. data[89] = 2; data[90] = 0; data[91] = 100; data[92] = 0;
  77. data[93] = 6; data[94] = 0; data[95] = 2; data[96] = 0;
  78. data[97] = 23;
  79. pkt = new Pkt6(data, sizeof(data));
  80. pkt->setRemotePort(546);
  81. pkt->setRemoteAddr(IOAddress("fe80::21e:8cff:fe9b:7349"));
  82. pkt->setLocalPort(0);
  83. pkt->setLocalAddr(IOAddress("ff02::1:2"));
  84. pkt->setIndex(2);
  85. pkt->setIface("eth0");
  86. return (pkt);
  87. }
  88. TEST_F(Pkt6Test, unpack_solicit1) {
  89. Pkt6* sol = capture1();
  90. ASSERT_EQ(true, sol->unpack());
  91. // check for length
  92. EXPECT_EQ(98, sol->len() );
  93. // check for type
  94. EXPECT_EQ(DHCPV6_SOLICIT, sol->getType() );
  95. // check that all present options are returned
  96. EXPECT_TRUE(sol->getOption(D6O_CLIENTID)); // client-id is present
  97. EXPECT_TRUE(sol->getOption(D6O_IA_NA)); // IA_NA is present
  98. EXPECT_TRUE(sol->getOption(D6O_ELAPSED_TIME)); // elapsed is present
  99. EXPECT_TRUE(sol->getOption(D6O_NAME_SERVERS));
  100. EXPECT_TRUE(sol->getOption(D6O_ORO));
  101. // let's check that non-present options are not returned
  102. EXPECT_FALSE(sol->getOption(D6O_SERVERID)); // server-id is missing
  103. EXPECT_FALSE(sol->getOption(D6O_IA_TA));
  104. EXPECT_FALSE(sol->getOption(D6O_IAADDR));
  105. delete sol;
  106. }
  107. TEST_F(Pkt6Test, packUnpack) {
  108. Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, 0x020304);
  109. OptionPtr opt1(new Option(Option::V6, 1));
  110. OptionPtr opt2(new Option(Option::V6, 2));
  111. OptionPtr opt3(new Option(Option::V6, 100));
  112. // let's not use zero-length option type 3 as it is IA_NA
  113. parent->addOption(opt1);
  114. parent->addOption(opt2);
  115. parent->addOption(opt3);
  116. EXPECT_EQ(DHCPV6_SOLICIT, parent->getType());
  117. // calculated length should be 16
  118. EXPECT_EQ(Pkt6::DHCPV6_PKT_HDR_LEN + 3 * Option::OPTION6_HDR_LEN,
  119. parent->len());
  120. EXPECT_TRUE(parent->pack());
  121. EXPECT_EQ(Pkt6::DHCPV6_PKT_HDR_LEN + 3 * Option::OPTION6_HDR_LEN,
  122. parent->len());
  123. // create second packet,based on assembled data from the first one
  124. Pkt6* clone = new Pkt6(static_cast<const uint8_t*>(parent->getBuffer().getData()),
  125. parent->getBuffer().getLength());
  126. // now recreate options list
  127. EXPECT_TRUE( clone->unpack() );
  128. // transid, message-type should be the same as before
  129. EXPECT_EQ(parent->getTransid(), parent->getTransid());
  130. EXPECT_EQ(DHCPV6_SOLICIT, clone->getType());
  131. EXPECT_TRUE( clone->getOption(1));
  132. EXPECT_TRUE( clone->getOption(2));
  133. EXPECT_TRUE( clone->getOption(100));
  134. EXPECT_FALSE( clone->getOption(4));
  135. delete parent;
  136. delete clone;
  137. }
  138. TEST_F(Pkt6Test, addGetDelOptions) {
  139. Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, random() );
  140. OptionPtr opt1(new Option(Option::V6, 1));
  141. OptionPtr opt2(new Option(Option::V6, 2));
  142. OptionPtr opt3(new Option(Option::V6, 2));
  143. parent->addOption(opt1);
  144. parent->addOption(opt2);
  145. // getOption() test
  146. EXPECT_EQ(opt1, parent->getOption(1));
  147. EXPECT_EQ(opt2, parent->getOption(2));
  148. // expect NULL
  149. EXPECT_EQ(OptionPtr(), parent->getOption(4));
  150. // now there are 2 options of type 2
  151. parent->addOption(opt3);
  152. // let's delete one of them
  153. EXPECT_EQ(true, parent->delOption(2));
  154. // there still should be the other option 2
  155. EXPECT_NE(OptionPtr(), parent->getOption(2));
  156. // let's delete the other option 2
  157. EXPECT_EQ(true, parent->delOption(2));
  158. // no more options with type=2
  159. EXPECT_EQ(OptionPtr(), parent->getOption(2));
  160. // let's try to delete - should fail
  161. EXPECT_TRUE(false == parent->delOption(2));
  162. delete parent;
  163. }
  164. TEST_F(Pkt6Test, Timestamp) {
  165. boost::scoped_ptr<Pkt6> pkt(new Pkt6(DHCPV6_SOLICIT, 0x020304));
  166. // Just after construction timestamp is invalid
  167. ASSERT_TRUE(pkt->getTimestamp().is_not_a_date_time());
  168. // Update packet time.
  169. pkt->updateTimestamp();
  170. // Get updated packet time.
  171. boost::posix_time::ptime ts_packet = pkt->getTimestamp();
  172. // After timestamp is updated it should be date-time.
  173. ASSERT_FALSE(ts_packet.is_not_a_date_time());
  174. // Check current time.
  175. boost::posix_time::ptime ts_now =
  176. boost::posix_time::microsec_clock::universal_time();
  177. // Calculate period between packet time and now.
  178. boost::posix_time::time_period ts_period(ts_packet, ts_now);
  179. // Duration should be positive or zero.
  180. EXPECT_TRUE(ts_period.length().total_microseconds() >= 0);
  181. }
  182. }