dhcp4o6_ipc_unittest.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <asiolink/io_address.h>
  8. #include <dhcp/pkt4o6.h>
  9. #include <dhcp/pkt6.h>
  10. #include <dhcp/tests/iface_mgr_test_config.h>
  11. #include <dhcp4/dhcp4_dhcp4o6_ipc.h>
  12. #include <dhcpsrv/cfgmgr.h>
  13. #include <dhcpsrv/testutils/dhcp4o6_test_ipc.h>
  14. #include <gtest/gtest.h>
  15. #include <stdint.h>
  16. using namespace isc;
  17. using namespace isc::asiolink;
  18. using namespace isc::dhcp;
  19. using namespace isc::dhcp::test;
  20. using namespace isc::util;
  21. namespace {
  22. /// @brief Port number used in tests.
  23. const uint16_t TEST_PORT = 32000;
  24. /// @brief Define short name for the test IPC.
  25. typedef Dhcp4o6TestIpc TestIpc;
  26. /// @brief Test fixture class for DHCPv4 endpoint of DHCPv4o6 IPC.
  27. class Dhcp4to6IpcTest : public ::testing::Test {
  28. public:
  29. /// @brief Constructor
  30. ///
  31. /// Configures IPC to use a test port. It also provides a fake
  32. /// configuration of interfaces.
  33. Dhcp4to6IpcTest()
  34. : iface_mgr_test_config_(true) {
  35. configurePort(TEST_PORT);
  36. }
  37. /// @brief Configure DHCP4o6 port.
  38. ///
  39. /// @param port New port.
  40. void configurePort(uint16_t port);
  41. /// @brief Creates an instance of the DHCPv4o6 Message option.
  42. ///
  43. /// The option will contain an empty DHCPREQUEST message, with
  44. /// just the Message Type option inside and nothing else.
  45. ///
  46. /// @return Pointer to the instance of the DHCPv4-query Message option.
  47. OptionPtr createDHCPv4MsgOption() const;
  48. private:
  49. /// @brief Provides fake configuration of interfaces.
  50. IfaceMgrTestConfig iface_mgr_test_config_;
  51. };
  52. void
  53. Dhcp4to6IpcTest::configurePort(uint16_t port) {
  54. CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(port);
  55. }
  56. OptionPtr
  57. Dhcp4to6IpcTest::createDHCPv4MsgOption() const {
  58. // Create the DHCPv4 message.
  59. Pkt4Ptr pkt(new Pkt4(DHCPREQUEST, 1234));
  60. // Make a wire representation of the DHCPv4 message.
  61. pkt->pack();
  62. OutputBuffer& output_buffer = pkt->getBuffer();
  63. const uint8_t* data = static_cast<const uint8_t*>(output_buffer.getData());
  64. OptionBuffer option_buffer(data, data + output_buffer.getLength());
  65. // Create the DHCPv4 Message option holding the created message.
  66. OptionPtr opt_msg(new Option(Option::V6, D6O_DHCPV4_MSG, option_buffer));
  67. return (opt_msg);
  68. }
  69. // This test verifies that the IPC returns an error when trying to bind
  70. // to the out of range port.
  71. TEST_F(Dhcp4to6IpcTest, invalidPortError) {
  72. // Create instance of the IPC endpoint under test with out-of-range port.
  73. configurePort(65535);
  74. Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance();
  75. EXPECT_THROW(ipc.open(), isc::OutOfRange);
  76. }
  77. // This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can
  78. // receive messages.
  79. TEST_F(Dhcp4to6IpcTest, receive) {
  80. // Create instance of the IPC endpoint under test.
  81. Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance();
  82. // Create instance of the IPC endpoint being used as a source of messages.
  83. TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6);
  84. // Open both endpoints.
  85. ASSERT_NO_THROW(ipc.open());
  86. ASSERT_NO_THROW(src_ipc.open());
  87. // Create message to be sent over IPC.
  88. Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
  89. pkt->addOption(createDHCPv4MsgOption());
  90. pkt->setIface("eth0");
  91. pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
  92. ASSERT_NO_THROW(pkt->pack());
  93. // Send and wait up to 1 second to receive it.
  94. ASSERT_NO_THROW(src_ipc.send(pkt));
  95. ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0));
  96. // Make sure that the message has been received.
  97. Pkt4o6Ptr pkt_received = ipc.getReceived();
  98. ASSERT_TRUE(pkt_received);
  99. Pkt6Ptr pkt6_received = pkt_received->getPkt6();
  100. ASSERT_TRUE(pkt6_received);
  101. EXPECT_EQ("eth0", pkt6_received->getIface());
  102. EXPECT_EQ("2001:db8:1::123", pkt6_received->getRemoteAddr().toText());
  103. }
  104. // This test verifies that message with multiple DHCPv4 query options
  105. // is rejected.
  106. TEST_F(Dhcp4to6IpcTest, receiveMultipleQueries) {
  107. // Create instance of the IPC endpoint under test.
  108. Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance();
  109. // Create instance of the IPC endpoint being used as a source of messages.
  110. TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6);
  111. // Open both endpoints.
  112. ASSERT_NO_THROW(ipc.open());
  113. ASSERT_NO_THROW(src_ipc.open());
  114. // Create message to be sent over IPC.
  115. Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
  116. // Add two DHCPv4 query options.
  117. pkt->addOption(createDHCPv4MsgOption());
  118. pkt->addOption(createDHCPv4MsgOption());
  119. pkt->setIface("eth0");
  120. pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
  121. ASSERT_NO_THROW(pkt->pack());
  122. // Send message.
  123. ASSERT_NO_THROW(src_ipc.send(pkt));
  124. // Reception handler should throw exception.
  125. EXPECT_THROW(IfaceMgr::instance().receive6(1, 0), Dhcp4o6IpcError);
  126. }
  127. // This test verifies that message with no DHCPv4 query options is rejected.
  128. TEST_F(Dhcp4to6IpcTest, receiveNoQueries) {
  129. // Create instance of the IPC endpoint under test.
  130. Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance();
  131. // Create instance of the IPC endpoint being used as a source of messages.
  132. TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6);
  133. // Open both endpoints.
  134. ASSERT_NO_THROW(ipc.open());
  135. ASSERT_NO_THROW(src_ipc.open());
  136. // Create message to be sent over IPC without DHCPv4 query option.
  137. Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234));
  138. pkt->setIface("eth0");
  139. pkt->setRemoteAddr(IOAddress("2001:db8:1::123"));
  140. ASSERT_NO_THROW(pkt->pack());
  141. // Send message.
  142. ASSERT_NO_THROW(src_ipc.send(pkt));
  143. // Reception handler should throw exception.
  144. EXPECT_THROW(IfaceMgr::instance().receive6(1, 0), Dhcp4o6IpcError);
  145. }
  146. } // end of anonymous namespace