diff --git a/src/bin/dhcp4/Makefile.am b/src/bin/dhcp4/Makefile.am index 2b23bfa447..043ed26d38 100644 --- a/src/bin/dhcp4/Makefile.am +++ b/src/bin/dhcp4/Makefile.am @@ -62,7 +62,6 @@ libdhcp4_la_SOURCES += ctrl_dhcp4_srv.cc ctrl_dhcp4_srv.h libdhcp4_la_SOURCES += json_config_parser.cc json_config_parser.h libdhcp4_la_SOURCES += dhcp4_log.cc dhcp4_log.h libdhcp4_la_SOURCES += dhcp4_srv.cc dhcp4_srv.h -libdhcp4_la_SOURCES += dhcp4_dhcp4o6_ipc.cc dhcp4_dhcp4o6_ipc.h libdhcp4_la_SOURCES += kea_controller.cc diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc index a0ea0bde22..7d19451dc3 100644 --- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc +++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -186,16 +185,6 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) { return (isc::config::createAnswer(1, err.str())); } - // Setup DHCPv4-over-DHCPv6 IPC - try { - Dhcp4to6Ipc::instance().open(); - } catch (const std::exception& ex) { - std::ostringstream err; - err << "error starting DHCPv4-over-DHCPv6 IPC " - " after server reconfiguration: " << ex.what(); - return (isc::config::createAnswer(1, err.str())); - } - // Configuration may change active interfaces. Therefore, we have to reopen // sockets according to new configuration. It is possible that this // operation will fail for some interfaces but the openSockets function diff --git a/src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc b/src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc deleted file mode 100644 index 94f8102118..0000000000 --- a/src/bin/dhcp4/dhcp4_dhcp4o6_ipc.cc +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include -#include -#include -#include - -using namespace std; - -namespace isc { -namespace dhcp { - -Dhcp4to6Ipc::Dhcp4to6Ipc() : Dhcp4o6IpcBase() { -} - -Dhcp4to6Ipc& Dhcp4to6Ipc::instance() { - static Dhcp4to6Ipc dhcp4to6_ipc; - return (dhcp4to6_ipc); -} - -void Dhcp4to6Ipc::open() { - uint32_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port(); - if (port == 0) { - Dhcp4o6IpcBase::close(); - return; - } - - int old_fd = socket_fd_; - socket_fd_ = Dhcp4o6IpcBase::open(static_cast(port), ENDPOINT_TYPE_V4); - if ((old_fd == -1) && (socket_fd_ != old_fd)) { - IfaceMgr::instance().addExternalSocket(socket_fd_, Dhcp4to6Ipc::handler); - } -} - -void Dhcp4to6Ipc::handler() { - Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance(); - - // Reset received message in case we return from this method before the - // received message pointer is updated. - ipc.received_.reset(); - - // Receive message from the IPC socket. - Pkt6Ptr pkt = ipc.receive(); - if (!pkt) { - return; - } - - // Each message must contain option holding DHCPv4 message. - OptionCollection msgs = pkt->getOptions(D6O_DHCPV4_MSG); - if (msgs.empty()) { - isc_throw(Dhcp4o6IpcError, "DHCPv4 message option not present in the" - " DHCPv4o6 message received by the DHCPv4 server"); - - } else if (msgs.size() > 1) { - isc_throw(Dhcp4o6IpcError, "expected exactly one DHCPv4 message within" - " DHCPv4 message option received by the DHCPv4 server"); - } - - OptionPtr msg = msgs.begin()->second; - if (!msg) { - isc_throw(Dhcp4o6IpcError, "null DHCPv4 message option in the" - " DHCPv4o6 message received by the DHCPv4 server"); - } - - // Record this message. - ipc.received_.reset(new Pkt4o6(msg->getData(), pkt)); -} - -Pkt4o6Ptr& Dhcp4to6Ipc::getReceived() { - return (received_); -} - -}; // namespace dhcp - -}; // namespace isc diff --git a/src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h b/src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h deleted file mode 100644 index f0d7752d77..0000000000 --- a/src/bin/dhcp4/dhcp4_dhcp4o6_ipc.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef DHCP4_DHCP4O6_IPC_H -#define DHCP4_DHCP4O6_IPC_H - -/// @file dhcp4_dhcp4o6_ipc.h Defines the Dhcp4o6Ipc class. -/// This file defines the class Kea uses to act as the DHCPv4 server -/// side of DHCPv4-over-DHCPv6 communication between servers. -/// - -#include -#include -#include - -namespace isc { -namespace dhcp { - -/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv4 server side -class Dhcp4to6Ipc : public Dhcp4o6IpcBase { -protected: - /// @brief Constructor - /// - /// Default constructor - Dhcp4to6Ipc(); - - /// @brief Destructor. - virtual ~Dhcp4to6Ipc() { } - -public: - /// @brief Returns pointer to the sole instance of Dhcp4o6Ipc - /// - /// Dhcp4to6Ipc is a singleton class - /// - /// @return the only existing instance of DHCP4o6 IPC - static Dhcp4to6Ipc& instance(); - - /// @brief Open communication socket - /// - /// Call base open method and sets the handler/callback when needed - virtual void open(); - - /// @brief On receive handler - /// - /// The handler processes the DHCPv4-query DHCPv6 packet and - /// sends the DHCPv4-response DHCPv6 packet back to the DHCPv6 server - static void handler(); - - /// @brief Returns last received packet - /// - /// @return a reference to a shared pointer to the last received packet - /// @note This reference should be cleared after use - Pkt4o6Ptr& getReceived(); - -private: - /// @brief last received packet - Pkt4o6Ptr received_; -}; - -} // namespace isc -} // namespace dhcp - -#endif diff --git a/src/bin/dhcp4/json_config_parser.cc b/src/bin/dhcp4/json_config_parser.cc index d52c5094e2..866bf20bb2 100644 --- a/src/bin/dhcp4/json_config_parser.cc +++ b/src/bin/dhcp4/json_config_parser.cc @@ -422,10 +422,9 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id, if ((config_id.compare("valid-lifetime") == 0) || (config_id.compare("renew-timer") == 0) || (config_id.compare("rebind-timer") == 0) || - (config_id.compare("decline-probation-period") == 0) || - (config_id.compare("dhcp4o6-port") == 0) ) { + (config_id.compare("decline-probation-period") == 0) ) { parser = new Uint32Parser(config_id, - globalContext()->uint32_values_); + globalContext()->uint32_values_); } else if (config_id.compare("interfaces-config") == 0) { parser = new IfacesConfigParser4(); } else if (config_id.compare("subnet4") == 0) { @@ -473,7 +472,6 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id, /// /// - echo-client-id /// - decline-probation-period -/// - dhcp4o6-port void setGlobalParameters4() { // Although the function is modest for now, it is certain that the number // of global switches will increase over time, hence the name. @@ -496,15 +494,6 @@ void setGlobalParameters4() { } catch (...) { // That's not really needed. } - - // Set the DHCPv4-over-DHCPv6 interserver port. - try { - uint32_t dhcp4o6_port = globalContext()->uint32_values_ - ->getOptionalParam("dhcp4o6-port", 0); - CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(dhcp4o6_port); - } catch (...) { - // Ignore errors. This flag is optional - } } isc::data::ConstElementPtr diff --git a/src/bin/dhcp4/tests/Makefile.am b/src/bin/dhcp4/tests/Makefile.am index 8ba7690c56..df7ac93a2b 100644 --- a/src/bin/dhcp4/tests/Makefile.am +++ b/src/bin/dhcp4/tests/Makefile.am @@ -92,7 +92,6 @@ dhcp4_unittests_SOURCES += release_unittest.cc dhcp4_unittests_SOURCES += out_of_range_unittest.cc dhcp4_unittests_SOURCES += decline_unittest.cc dhcp4_unittests_SOURCES += kea_controller_unittest.cc -dhcp4_unittests_SOURCES += dhcp4_dhcp4o6_ipc_unittest.cc nodist_dhcp4_unittests_SOURCES = marker_file.h test_libraries.h diff --git a/src/bin/dhcp4/tests/dhcp4_dhcp4o6_ipc_unittest.cc b/src/bin/dhcp4/tests/dhcp4_dhcp4o6_ipc_unittest.cc deleted file mode 100644 index d731b74398..0000000000 --- a/src/bin/dhcp4/tests/dhcp4_dhcp4o6_ipc_unittest.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace isc; -using namespace isc::asiolink; -using namespace isc::dhcp; -using namespace isc::dhcp::test; -using namespace isc::util; - -namespace { - -/// @brief Port number used in tests. -const uint16_t TEST_PORT = 32000; - -/// @brief Define short name for the test IPC. -typedef Dhcp4o6TestIpc TestIpc; - -/// @brief Test fixture class for DHCPv4 endpoint of DHCPv4o6 IPC. -class Dhcp4to6IpcTest : public ::testing::Test { -public: - - /// @brief Constructor - /// - /// Configures IPC to use a test port. It also provides a fake - /// configuration of interfaces. - Dhcp4to6IpcTest() - : iface_mgr_test_config_(true) { - configurePort(TEST_PORT); - } - - /// @brief Configure DHCP4o6 port. - /// - /// @param port New port. - void configurePort(const uint16_t port); - - /// @brief Creates an instance of the DHCPv4o6 Message option. - /// - /// @return Pointer to the instance of the DHCPv4-query Message option. - OptionPtr createDHCPv4MsgOption() const; - -private: - - /// @brief Provides fake configuration of interfaces. - IfaceMgrTestConfig iface_mgr_test_config_; - -}; - -void -Dhcp4to6IpcTest::configurePort(const uint16_t port) { - CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(port); -} - -OptionPtr -Dhcp4to6IpcTest::createDHCPv4MsgOption() const { - // Create the DHCPv4 message. - Pkt4Ptr pkt(new Pkt4(DHCPREQUEST, 1234)); - // Make a wire representation of the DHCPv4 message. - pkt->pack(); - OutputBuffer& output_buffer = pkt->getBuffer(); - const uint8_t* data = static_cast(output_buffer.getData()); - OptionBuffer option_buffer(data, data + output_buffer.getLength()); - - // Create the DHCPv4 Message option holding the created message. - OptionPtr opt_msg(new Option(Option::V6, D6O_DHCPV4_MSG, option_buffer)); - return (opt_msg); -} - -// This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can -// receive messages. -TEST_F(Dhcp4to6IpcTest, receive) { - // Create instance of the IPC endpoint under test. - Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance(); - // Create instance of the IPC endpoint being used as a source of messages. - TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6); - - // Open both endpoints. - ASSERT_NO_THROW(ipc.open()); - ASSERT_NO_THROW(src_ipc.open()); - - // Create message to be sent over IPC. - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234)); - pkt->addOption(createDHCPv4MsgOption()); - pkt->setIface("eth0"); - pkt->setRemoteAddr(IOAddress("2001:db8:1::123")); - ASSERT_NO_THROW(pkt->pack()); - - // Send and wait up to 1 second to receive it. - ASSERT_NO_THROW(src_ipc.send(pkt)); - ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0)); - - // Make sure that the message has been received. - Pkt4o6Ptr pkt_received = ipc.getReceived(); - ASSERT_TRUE(pkt_received); - Pkt6Ptr pkt6_received = pkt_received->getPkt6(); - ASSERT_TRUE(pkt6_received); - EXPECT_EQ("eth0", pkt6_received->getIface()); - EXPECT_EQ("2001:db8:1::123", pkt6_received->getRemoteAddr().toText()); -} - -// This test verifies that message with multiple DHCPv4 query options -// is rejected. -TEST_F(Dhcp4to6IpcTest, receiveMultipleQueries) { - // Create instance of the IPC endpoint under test. - Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance(); - // Create instance of the IPC endpoint being used as a source of messages. - TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6); - - // Open both endpoints. - ASSERT_NO_THROW(ipc.open()); - ASSERT_NO_THROW(src_ipc.open()); - - // Create message to be sent over IPC. - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234)); - // Add two DHCPv4 query options. - pkt->addOption(createDHCPv4MsgOption()); - pkt->addOption(createDHCPv4MsgOption()); - pkt->setIface("eth0"); - pkt->setRemoteAddr(IOAddress("2001:db8:1::123")); - ASSERT_NO_THROW(pkt->pack()); - - // Send message. - ASSERT_NO_THROW(src_ipc.send(pkt)); - // Reception handler should throw exception. - EXPECT_THROW(IfaceMgr::instance().receive6(1, 0), Dhcp4o6IpcError); -} - -// This test verifies that message with no DHCPv4 query options is rejected. -TEST_F(Dhcp4to6IpcTest, receiveNoQueries) { - // Create instance of the IPC endpoint under test. - Dhcp4to6Ipc& ipc = Dhcp4to6Ipc::instance(); - // Create instance of the IPC endpoint being used as a source of messages. - TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6); - - // Open both endpoints. - ASSERT_NO_THROW(ipc.open()); - ASSERT_NO_THROW(src_ipc.open()); - - // Create message to be sent over IPC without DHCPv4 query option. - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234)); - pkt->setIface("eth0"); - pkt->setRemoteAddr(IOAddress("2001:db8:1::123")); - ASSERT_NO_THROW(pkt->pack()); - - // Send message. - ASSERT_NO_THROW(src_ipc.send(pkt)); - // Reception handler should throw exception. - EXPECT_THROW(IfaceMgr::instance().receive6(1, 0), Dhcp4o6IpcError); -} - - -} // end of anonymous namespace diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am index ad82c4d8dd..77d5d1f1c7 100644 --- a/src/bin/dhcp6/Makefile.am +++ b/src/bin/dhcp6/Makefile.am @@ -63,7 +63,6 @@ libdhcp6_la_SOURCES += dhcp6_log.cc dhcp6_log.h libdhcp6_la_SOURCES += dhcp6_srv.cc dhcp6_srv.h libdhcp6_la_SOURCES += ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h libdhcp6_la_SOURCES += json_config_parser.cc json_config_parser.h -libdhcp6_la_SOURCES += dhcp6_dhcp4o6_ipc.cc dhcp6_dhcp4o6_ipc.h libdhcp6_la_SOURCES += kea_controller.cc diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc index ca74c32ae8..f3453c2dc7 100644 --- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc +++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -210,16 +209,6 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) { return (isc::config::createAnswer(1, err.str())); } - // Setup DHCPv4-over-DHCPv6 IPC - try { - Dhcp6to4Ipc::instance().open(); - } catch (const std::exception& ex) { - std::ostringstream err; - err << "error starting DHCPv4-over-DHCPv6 IPC " - " after server reconfiguration: " << ex.what(); - return (isc::config::createAnswer(1, err.str())); - } - // Configuration may change active interfaces. Therefore, we have to reopen // sockets according to new configuration. It is possible that this // operation will fail for some interfaces but the openSockets function diff --git a/src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc b/src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc deleted file mode 100644 index 0bdfd1d472..0000000000 --- a/src/bin/dhcp6/dhcp6_dhcp4o6_ipc.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - - -#include - -#include -#include -#include -#include - -using namespace std; - -namespace isc { -namespace dhcp { - -Dhcp6to4Ipc::Dhcp6to4Ipc() : Dhcp4o6IpcBase() {} - -Dhcp6to4Ipc& Dhcp6to4Ipc::instance() { - static Dhcp6to4Ipc dhcp6to4_ipc; - return (dhcp6to4_ipc); -} - -void Dhcp6to4Ipc::open() { - uint32_t port = CfgMgr::instance().getStagingCfg()->getDhcp4o6Port(); - if (port == 0) { - Dhcp4o6IpcBase::close(); - return; - } - - int old_fd = socket_fd_; - socket_fd_ = Dhcp4o6IpcBase::open(static_cast(port), ENDPOINT_TYPE_V6); - if ((old_fd == -1) && (socket_fd_ != old_fd)) { - IfaceMgr::instance().addExternalSocket(socket_fd_, Dhcp6to4Ipc::handler); - } -} - -void Dhcp6to4Ipc::handler() { - Dhcp6to4Ipc& ipc = Dhcp6to4Ipc::instance(); - - // Receive message from IPC. - Pkt6Ptr pkt = ipc.receive(); - if (!pkt) { - return; - } - - // The received message has been unpacked by the receive() function. This - // method could have modified the message so it's better to pack() it - // again because we'll be forwarding it to a client. - isc::util::OutputBuffer& buf = pkt->getBuffer(); - buf.clear(); - pkt->pack(); - - uint8_t msg_type = pkt->getType(); - if ((msg_type == DHCPV6_RELAY_FORW) || (msg_type == DHCPV6_RELAY_REPL)) { - pkt->setRemotePort(DHCP6_SERVER_PORT); - } else { - pkt->setRemotePort(DHCP6_CLIENT_PORT); - } - - // Forward packet to the client. - IfaceMgr::instance().send(pkt); - // processStatsSent(pkt); -} - -}; // namespace dhcp - -}; // namespace isc diff --git a/src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h b/src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h deleted file mode 100644 index 892fe0ea1e..0000000000 --- a/src/bin/dhcp6/dhcp6_dhcp4o6_ipc.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef DHCP6_DHCP4O6_IPC_H -#define DHCP6_DHCP4O6_IPC_H - -/// @file dhcp6_dhcp4o6_ipc.h Defines the Dhcp4o6Ipc class. -/// This file defines the class Kea uses to act as the DHCPv6 server -/// side of DHCPv4-over-DHCPv6 communication between servers. -/// -#include -#include - -namespace isc { -namespace dhcp { - -/// @brief Handles DHCPv4-over-DHCPv6 IPC on the DHCPv6 server side -class Dhcp6to4Ipc : public Dhcp4o6IpcBase { -protected: - /// @brief Constructor - /// - /// Default constructor - Dhcp6to4Ipc(); - - /// @brief Destructor. - virtual ~Dhcp6to4Ipc() { } - -public: - /// @brief Returns pointer to the sole instance of Dhcp4o6Ipc - /// - /// Dhcp4o6Ipc is a singleton class - /// - /// @return the only existing instance of DHCP4o6 IPC - static Dhcp6to4Ipc& instance(); - - /// @brief Open communication socket - /// - /// Call base open method and sets the handler/callback when needed - virtual void open(); - - /// @brief On receive handler - /// - /// The handler sends the DHCPv6 packet back to the remote address - static void handler(); -}; - -} // namespace isc -} // namespace dhcp - -#endif diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 0e6da0edb3..2eaf423e2f 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -221,13 +220,6 @@ Dhcpv6Srv::~Dhcpv6Srv() { LOG_ERROR(dhcp6_logger, DHCP6_SRV_D2STOP_ERROR).arg(ex.what()); } - try { - Dhcp6to4Ipc::instance().close(); - } catch(const std::exception& ex) { - // Highly unlikely, but lets Report it but go on - // LOG_ERROR(dhcp6_logger, DHCP6_SRV_DHCP4O6_ERROR).arg(ex.what()); - } - IfaceMgr::instance().closeSockets(); LeaseMgrFactory::destroy(); diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 21e30ea98e..95eefd3ac4 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -674,8 +674,7 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id, (config_id.compare("valid-lifetime") == 0) || (config_id.compare("renew-timer") == 0) || (config_id.compare("rebind-timer") == 0) || - (config_id.compare("decline-probation-period") == 0) || - (config_id.compare("dhcp4o6-port") == 0) ) { + (config_id.compare("decline-probation-period") == 0) ) { parser = new Uint32Parser(config_id, globalContext()->uint32_values_); } else if (config_id.compare("interfaces-config") == 0) { @@ -726,7 +725,6 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id, /// Currently this method sets the following global parameters: /// /// - decline-probation-period -/// - dhcp4o6-port void setGlobalParameters6() { // Set the probation period for decline handling. @@ -738,15 +736,6 @@ void setGlobalParameters6() { } catch (...) { // That's not really needed. } - - // Set the DHCPv4-over-DHCPv6 interserver port. - try { - uint32_t dhcp4o6_port = globalContext()->uint32_values_ - ->getOptionalParam("dhcp4o6-port", 0); - CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(dhcp4o6_port); - } catch (...) { - // Ignore errors. This flag is optional - } } isc::data::ConstElementPtr diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am index 2c855fa33e..58a518dbf3 100644 --- a/src/bin/dhcp6/tests/Makefile.am +++ b/src/bin/dhcp6/tests/Makefile.am @@ -93,8 +93,8 @@ dhcp6_unittests_SOURCES += confirm_unittest.cc dhcp6_unittests_SOURCES += infrequest_unittest.cc dhcp6_unittests_SOURCES += decline_unittest.cc dhcp6_unittests_SOURCES += dhcp6_message_test.cc dhcp6_message_test.h + dhcp6_unittests_SOURCES += kea_controller_unittest.cc -dhcp6_unittests_SOURCES += dhcp6_dhcp4o6_ipc_unittest.cc nodist_dhcp6_unittests_SOURCES = marker_file.h test_libraries.h diff --git a/src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc b/src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc deleted file mode 100644 index e499bc74a0..0000000000 --- a/src/bin/dhcp6/tests/dhcp6_dhcp4o6_ipc_unittest.cc +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace isc; -using namespace isc::asiolink; -using namespace isc::dhcp; -using namespace isc::dhcp::test; -using namespace isc::util; - -namespace { - -/// @brief Port number used in tests. -const uint16_t TEST_PORT = 32000; - -/// @brief Define short name for the test IPC. -typedef Dhcp4o6TestIpc TestIpc; - -/// @brief Test fixture class for DHCPv4 endpoint of DHCPv4o6 IPC. -class Dhcp6to4IpcTest : public ::testing::Test { -public: - - /// @brief Constructor - /// - /// Configures IPC to use a test port. It also provides a fake - /// configuration of interfaces and opens IPv6 sockets. - Dhcp6to4IpcTest() - : iface_mgr_test_config_(true) { - IfaceMgr::instance().openSockets6(); - configurePort(TEST_PORT); - } - - /// @brief Configure DHCP4o6 port. - /// - /// @param port New port. - void configurePort(const uint16_t port); - - /// @brief Creates an instance of the DHCPv4o6 Message option. - /// - /// @return Pointer to the instance of the DHCPv4-query Message option. - OptionPtr createDHCPv4MsgOption() const; - -private: - - /// @brief Provides fake configuration of interfaces. - IfaceMgrTestConfig iface_mgr_test_config_; -}; - -void -Dhcp6to4IpcTest::configurePort(const uint16_t port) { - CfgMgr::instance().getStagingCfg()->setDhcp4o6Port(port); -} - -OptionPtr -Dhcp6to4IpcTest::createDHCPv4MsgOption() const { - // Create the DHCPv4 message. - Pkt4Ptr pkt(new Pkt4(DHCPREQUEST, 1234)); - // Make a wire representation of the DHCPv4 message. - pkt->pack(); - OutputBuffer& output_buffer = pkt->getBuffer(); - const uint8_t* data = static_cast(output_buffer.getData()); - OptionBuffer option_buffer(data, data + output_buffer.getLength()); - - // Create the DHCPv4 Message option holding the created message. - OptionPtr opt_msg(new Option(Option::V6, D6O_DHCPV4_MSG, option_buffer)); - return (opt_msg); -} - -// This test verifies that the DHCPv4 endpoint of the DHCPv4o6 IPC can -// receive messages. -TEST_F(Dhcp6to4IpcTest, receive) { - // Create instance of the IPC endpoint under test. - Dhcp6to4Ipc& ipc = Dhcp6to4Ipc::instance(); - // Create instance of the IPC endpoint being used as a source of messages. - TestIpc src_ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - - // Open both endpoints. - ASSERT_NO_THROW(ipc.open()); - ASSERT_NO_THROW(src_ipc.open()); - - // Create message to be sent over IPC. - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 1234)); - pkt->addOption(createDHCPv4MsgOption()); - pkt->setIface("eth0"); - pkt->setRemoteAddr(IOAddress("2001:db8:1::123")); - ASSERT_NO_THROW(pkt->pack()); - - // Send and wait up to 1 second to receive it. - ASSERT_NO_THROW(src_ipc.send(pkt)); - ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0)); - - - // The stub packet filter exposes static function to retrieve messages - // sent over the fake sockets/interfaces. This is the message that the - // IPC endpoint should forward to the client after receiving it - // from the DHCPv4 server. - Pkt6Ptr forwarded = PktFilter6TestStub::popSent(); - ASSERT_TRUE(forwarded); - - // Verify the packet received. - EXPECT_EQ(DHCP6_CLIENT_PORT, forwarded->getRemotePort()); - EXPECT_EQ(forwarded->getType(), pkt->getType()); - EXPECT_TRUE(forwarded->getOption(D6O_DHCPV4_MSG)); - EXPECT_EQ("eth0", forwarded->getIface()); - EXPECT_EQ("2001:db8:1::123", forwarded->getRemoteAddr().toText()); -} - -} // end of anonymous namespace diff --git a/src/lib/dhcp/tests/pkt_filter6_test_stub.cc b/src/lib/dhcp/tests/pkt_filter6_test_stub.cc index 8460196d76..810c53a0d1 100644 --- a/src/lib/dhcp/tests/pkt_filter6_test_stub.cc +++ b/src/lib/dhcp/tests/pkt_filter6_test_stub.cc @@ -13,71 +13,22 @@ // PERFORMANCE OF THIS SOFTWARE. #include -#include -#include #include -#include -#include -namespace { - -/// @brief Retrieves a queue of sent messages. -std::list& getSent() { - static std::list sent; - return (sent); -} - -} +#include namespace isc { namespace dhcp { namespace test { PktFilter6TestStub::PktFilter6TestStub() { - getSent().clear(); } SocketInfo PktFilter6TestStub::openSocket(const Iface&, const isc::asiolink::IOAddress& addr, const uint16_t port, const bool) { - // Create a socket which may be used on select() but which is unlikely - // to return any data. - int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) { - isc_throw(Unexpected, "PktFilter6TestStub: opening socket failed"); - } - - // Set reuse address - int flag = 1; - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, static_cast(&flag), - sizeof(flag)) < 0) { - ::close(sock); - isc_throw(Unexpected, "PktFilter6TestStub:: failed to set SO_REUSEADDR on" - " socket"); - } - - // Set no blocking - if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { - ::close(sock); - isc_throw(Unexpected, "PktFilter6TestStub: failed to set O_NONBLOCK on" - " socket"); - } - - // Bind to the local address and random port. - struct sockaddr_in6 local6; - memset(&local6, 0, sizeof(local6)); - local6.sin6_family = AF_INET6; -#ifdef HAVE_SA_LEN - local6.sin6_len = sizeof(local6); -#endif - - if (bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) { - ::close(sock); - isc_throw(Unexpected, "PktFilter6TestStub: failed to bind socket"); - } - - return (SocketInfo(addr, port, sock)); + return (SocketInfo(addr, port, 0)); } Pkt6Ptr @@ -92,22 +43,10 @@ PktFilter6TestStub::joinMulticast(int, const std::string&, } int -PktFilter6TestStub::send(const Iface&, uint16_t, const Pkt6Ptr& pkt) { - getSent().push_back(pkt); +PktFilter6TestStub::send(const Iface&, uint16_t, const Pkt6Ptr&) { return (0); } -Pkt6Ptr -PktFilter6TestStub::popSent() { - std::list& sent = getSent(); - if (sent.empty()) { - return (Pkt6Ptr()); - } - Pkt6Ptr pkt = sent.front(); - sent.pop_front(); - return (pkt); -} - } } } diff --git a/src/lib/dhcp/tests/pkt_filter6_test_stub.h b/src/lib/dhcp/tests/pkt_filter6_test_stub.h index 96d8cc8a05..8a0c567029 100644 --- a/src/lib/dhcp/tests/pkt_filter6_test_stub.h +++ b/src/lib/dhcp/tests/pkt_filter6_test_stub.h @@ -36,10 +36,11 @@ public: /// @brief Constructor. PktFilter6TestStub(); - /// @brief Open a socket. + /// @brief Simulate opening of the socket. /// - /// This function opens a socket. This socket is bound to any address - /// and port. The select() function may be called on this socket. + /// This function simulates opening a primary socket. In reality, it doesn't + /// open a socket but the socket descriptor returned in the SocketInfo + /// structure is always set to 0. /// /// @param iface An interface descriptor. /// @param addr Address on the interface to be used to send packets. @@ -49,7 +50,8 @@ public: /// /// @note All parameters are ignored. /// - /// @return A SocketInfo structure with the socket descriptor. + /// @return A SocketInfo structure with the socket descriptor set to 0. The + /// fallback socket descriptor is set to a negative value. virtual SocketInfo openSocket(const Iface& iface, const isc::asiolink::IOAddress& addr, const uint16_t port, @@ -88,13 +90,6 @@ public: /// @return true if multicast join was successful static bool joinMulticast(int sock, const std::string& ifname, const std::string & mcast); - - /// @brief Retrieve next sent message. - /// - /// @return Pointer to the next sent message or NULL if there are no - /// more messages. - static Pkt6Ptr popSent(); - }; } // namespace isc::dhcp::test diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am index d8abc60f2d..066b4105e6 100755 --- a/src/lib/dhcpsrv/Makefile.am +++ b/src/lib/dhcpsrv/Makefile.am @@ -104,7 +104,6 @@ libkea_dhcpsrv_la_SOURCES += d2_client_mgr.cc d2_client_mgr.h libkea_dhcpsrv_la_SOURCES += daemon.cc daemon.h libkea_dhcpsrv_la_SOURCES += database_connection.cc database_connection.h libkea_dhcpsrv_la_SOURCES += db_exceptions.h -libkea_dhcpsrv_la_SOURCES += dhcp4o6_ipc.cc dhcp4o6_ipc.h libkea_dhcpsrv_la_SOURCES += dhcpsrv_log.cc dhcpsrv_log.h libkea_dhcpsrv_la_SOURCES += host.cc host.h libkea_dhcpsrv_la_SOURCES += host_container.h diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.cc b/src/lib/dhcpsrv/dhcp4o6_ipc.cc deleted file mode 100644 index f1e9d4e108..0000000000 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.cc +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace isc::asiolink; -using namespace isc::util; -using namespace std; - -namespace isc { -namespace dhcp { - -Dhcp4o6IpcBase::Dhcp4o6IpcBase() : port_(0), socket_fd_(-1) {} - -Dhcp4o6IpcBase::~Dhcp4o6IpcBase() { - close(); -} - -int Dhcp4o6IpcBase::open(const uint16_t port, const EndpointType& endpoint_type) { - // Check if the port value is correct. - if (port > 65534) { - isc_throw(Dhcp4o6IpcError, "specified port " << port << " is out of" - " range. The port value must not be greater than 65534 "); - } - - if (port == port_) { - // No change: nothing to do - return (socket_fd_); - } - - // Open socket - int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) { - isc_throw(Dhcp4o6IpcError, "Failed to create DHCP4o6 socket."); - } - - // Set reuse address - int flag = 1; - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, static_cast(&flag), - sizeof(flag)) < 0) { - ::close(sock); - isc_throw(Dhcp4o6IpcError, "Failed to set SO_REUSEADDR on DHCP4o6 socket."); - } - - // Set no blocking - if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { - ::close(sock); - isc_throw(Dhcp4o6IpcError, "Failed to set O_NONBLOCK on DHCP4o6 socket."); - } - - // Bind to the local address - struct sockaddr_in6 local6; - memset(&local6, 0, sizeof(local6)); - local6.sin6_family = AF_INET6; -#ifdef HAVE_SA_LEN - local6.sin6_len = sizeof(local6); -#endif - if (endpoint_type == ENDPOINT_TYPE_V6) { - local6.sin6_port = htons(port); - } else { - local6.sin6_port = htons(port + 1); - } - if (bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) { - ::close(sock); - isc_throw(Dhcp4o6IpcError, "Failed to bind DHCP4o6 socket."); - } - - // Connect to the remote address - struct sockaddr_in6 remote6; - memset(&remote6, 0, sizeof(remote6)); - remote6.sin6_family = AF_INET6; -#ifdef HAVE_SA_LEN - remote6.sin6_len = sizeof(remote6); -#endif - if (endpoint_type == ENDPOINT_TYPE_V6) { - remote6.sin6_port = htons(port + 1); - } else { - remote6.sin6_port = htons(port); - } - if (connect(sock, reinterpret_cast(&remote6), - sizeof(remote6)) < 0) { - ::close(sock); - isc_throw(Dhcp4o6IpcError, "Failed to connect DHCP4o6 socket."); - } - - if (socket_fd_ != -1) { - if (dup2(sock, socket_fd_) == -1) { - ::close(sock); - isc_throw(Dhcp4o6IpcError, "Failed to duplicate DHCP4o6 socket."); - } - if (sock != socket_fd_) { - ::close(sock); - sock = socket_fd_; - } - } - - // Success - port_ = port; - socket_fd_ = sock; - return (socket_fd_); -} - -void Dhcp4o6IpcBase::close() { - port_ = 0; - if (socket_fd_ != -1) { - IfaceMgr::instance().deleteExternalSocket(socket_fd_); - ::close(socket_fd_); - socket_fd_ = -1; - } -} - -Pkt6Ptr Dhcp4o6IpcBase::receive() { - uint8_t buf[65536]; - ssize_t cc = recv(socket_fd_, buf, sizeof(buf), 0); - if (cc < 0) { - isc_throw(Dhcp4o6IpcError, "Failed to receive on DHCP4o6 socket."); - } - Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(buf, cc)); - pkt->updateTimestamp(); - - // Get interface name and remote address - pkt->unpack(); - - // Vendor option is initially NULL. If we find the instance of the vendor - // option with the ISC enterprise id this pointer will point to it. - OptionVendorPtr option_vendor; - - // Get all vendor option and look for the one with the ISC enterprise id. - OptionCollection vendor_options = pkt->getOptions(D6O_VENDOR_OPTS); - for (OptionCollection::const_iterator opt = vendor_options.begin(); - opt != vendor_options.end(); ++opt) { - option_vendor = boost::dynamic_pointer_cast(opt->second); - if (option_vendor) { - if (option_vendor->getVendorId() == ENTERPRISE_ID_ISC) { - break; - } - - } else { - option_vendor.reset(); - } - } - - // Vendor option must exist. - if (!option_vendor) { - isc_throw(Dhcp4o6IpcError, "option " << D6O_VENDOR_OPTS - << " with ISC enterprise id is not present in the DHCP4o6" - " message sent between the servers"); - } - - // The option carrying interface name is required. - OptionStringPtr ifname = boost::dynamic_pointer_cast< - OptionString>(option_vendor->getOption(ISC_V6_4O6_INTERFACE)); - if (!ifname) { - isc_throw(Dhcp4o6IpcError, "option " << D6O_VENDOR_OPTS - << " doesn't contain the " << ISC_V6_4O6_INTERFACE - << " option required in the DHCP4o6 message sent" - " between Kea servers"); - } - - // Check if this interface is present in the system. - IfacePtr iface = IfaceMgr::instance().getIface(ifname->getValue()); - if (!iface) { - isc_throw(Dhcp4o6IpcError, "option " << ISC_V6_4O6_INTERFACE - << " sent in the DHCP4o6 message contains non-existing" - " interface name '" << ifname->getValue() << "'"); - } - - // Get the option holding source IPv6 address. - OptionCustomPtr srcs = boost::dynamic_pointer_cast< - OptionCustom>(option_vendor->getOption(ISC_V6_4O6_SRC_ADDRESS)); - if (!srcs) { - isc_throw(Dhcp4o6IpcError, "option " << D6O_VENDOR_OPTS - << " doesn't contain the " << ISC_V6_4O6_SRC_ADDRESS - << " option required in the DHCP4o6 message sent" - " between Kea servers"); - } - - // Update the packet. - pkt->setRemoteAddr(srcs->readAddress()); - pkt->setIface(iface->getName()); - pkt->setIndex(iface->getIndex()); - - // Remove options that have been added by the IPC sender. - static_cast(option_vendor->delOption(ISC_V6_4O6_INTERFACE)); - static_cast(option_vendor->delOption(ISC_V6_4O6_SRC_ADDRESS)); - - // If there are no more options, the IPC sender has probably created the - // vendor option, in which case we should remove it here. - if (option_vendor->getOptions().empty()) { - static_cast(pkt->delOption(D6O_VENDOR_OPTS)); - } - - return (pkt); -} - -void Dhcp4o6IpcBase::send(const Pkt6Ptr& pkt) { - // This shouldn't happen, i.e. send() shouldn't be called if there is - // no message. - if (!pkt) { - isc_throw(Dhcp4o6IpcError, "DHCP4o6 message must not be NULL while" - " trying to send it over the IPC"); - } - - // Disabled: nowhere to send - if (socket_fd_ == -1) { - isc_throw(Dhcp4o6IpcError, "unable to send DHCP4o6 message because" - " IPC socket is closed"); - } - - // Check if vendor option exists. - OptionVendorPtr option_vendor = boost::dynamic_pointer_cast< - OptionVendor>(pkt->getOption(D6O_VENDOR_OPTS)); - - // If vendor option doesn't exist or its enterprise id is not ISC's - // enterprise id, let's create it. - if (!option_vendor || (option_vendor->getVendorId() != ENTERPRISE_ID_ISC)) { - option_vendor.reset(new OptionVendor(Option::V6, ENTERPRISE_ID_ISC)); - pkt->addOption(option_vendor); - - } - - // Push interface name and source address in it - option_vendor->addOption(OptionStringPtr(new OptionString(Option::V6, - ISC_V6_4O6_INTERFACE, - pkt->getIface()))); - option_vendor->addOption(Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, - pkt->getRemoteAddr()))); - // Get packet content - OutputBuffer& buf = pkt->getBuffer(); - buf.clear(); - pkt->pack(); - - // Try to send the message. - if (::send(socket_fd_, buf.getData(), buf.getLength(), 0) < 0) { - isc_throw(Dhcp4o6IpcError, "failed to send DHCP4o6 message over the IPC: " - << strerror(errno)); - } - -} - -}; // namespace dhcp - -}; // namespace isc diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.h b/src/lib/dhcpsrv/dhcp4o6_ipc.h deleted file mode 100644 index 1b92326dad..0000000000 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef DHCP4O6_IPC_H -#define DHCP4O6_IPC_H - -/// @file dhcp4o6_ipc.h Defines the Dhcp4o6IpcBase class. -/// This file defines the class Kea uses as a base for -/// DHCPv4-over-DHCPv6 communication between servers. -/// - -#include -#include -#include -#include - -namespace isc { -namespace dhcp { - -/// @brief Exception thrown when error occurs as a result of use of IPC. -class Dhcp4o6IpcError : public Exception { -public: - Dhcp4o6IpcError(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) { }; -}; - -/// @brief Base class implementing transmission of the DHCPv4 over -/// DHCPv6 messages (RFC 7341) between the Kea servers. -/// -/// When the DHCPv6 server receives the DHCPv4 query message it needs -/// to forward it to the DHCPv4 server for processing. The DHCPv4 -/// server processes the message and answers with the DHCPv4 response -/// message to the DHCPv6 server. The server forwards it back to the -/// client. This class implements the communication between the DHCPv4 -/// and DHCPv6 servers to allow for transmission of the DHCPv4 query -/// and DHCPv6 response messages. -/// -/// This class creates a socket (when @c open is called) and binds it -/// to a port, depending on the configuration. The port number is -/// explicitly specified in the server configuration. This explicit -/// port value is used directly on the DHCPv6 server side. The DHCPv4 -/// server uses the port specified + 1. -/// -/// The DHCPv4 and DHCPv6 servers use distict instances of classes derived -/// from this base class. Each of these instances is used to send and -/// receive messages sent by the other server. -/// -/// In order to make address allocation decisions, the DHCPv4 server -/// requires information about the interface and the source address of -/// the original DHCPv4 query message sent by the client. This -/// information is known by the DHCPv6 server and needs to be conveyed -/// to the DHCPv4 server. The IPC conveys it in the -/// @c ISC_V6_4O6_INTERFACE and @c ISC_V6_4O6_SRC_ADDRESS options -/// within the Vendor Specific Information option, with ISC -/// enterprise id. These options are added by the IPC sender and removed -/// by the IPC receiver. -class Dhcp4o6IpcBase : public boost::noncopyable { -public: - - /// @brief Endpoint type: DHCPv4 or DHCPv6 server. - enum EndpointType { - ENDPOINT_TYPE_V4, - ENDPOINT_TYPE_V6 - }; - -protected: - /// @brief Constructor - /// - /// Default constructor - Dhcp4o6IpcBase(); - - /// @brief Destructor. - virtual ~Dhcp4o6IpcBase(); - - /// @brief Open communication socket (from base class). - /// - /// @param port Port number to use. The socket is bound to this port - /// if the endpoint type is DHCPv6 server, otherwise the port + 1 - /// value is used. - /// @param endpoint_type Endpoint type (DHCPv4 or DHCPv6 server). - /// - /// @return New socket descriptor. - int open(const uint16_t port, const EndpointType& endpoint_type); - -public: - - /// @brief Open communication socket (for derived classes). - virtual void open() = 0; - - /// @brief Close communication socket. - void close(); - - /// @brief Receive message over IPC. - /// - /// @return a pointer to a DHCPv6 message with interface and remote - /// address set from the IPC message - Pkt6Ptr receive(); - - /// @brief Send message over IPC. - /// - /// The IPC uses @c ISC_V6_4O6_INTERFACE and @c ISC_V6_4O6_SRC_ADDRESS - /// options conveyed within the Vendor Specific Information option, with - /// ISC enterprise id, to communicate the client remote address and the - /// interface on which the DHCPv4 query was received. These options will - /// be removed by the receiver. - /// - /// @param pkt Pointer to a DHCPv6 message with interface and remote - /// address. - void send(const Pkt6Ptr& pkt); - -protected: - - /// @brief Port number configured for IPC communication. - uint16_t port_; - - /// @brief Socket descriptor. - int socket_fd_; -}; - -} // namespace isc -} // namespace dhcp - -#endif diff --git a/src/lib/dhcpsrv/srv_config.cc b/src/lib/dhcpsrv/srv_config.cc index 385f266dc2..67b9d31086 100644 --- a/src/lib/dhcpsrv/srv_config.cc +++ b/src/lib/dhcpsrv/srv_config.cc @@ -33,7 +33,7 @@ SrvConfig::SrvConfig() cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()), cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()), class_dictionary_(new ClientClassDictionary()), - decline_timer_(0), dhcp4o6_port_(0) { + decline_timer_(0) { } SrvConfig::SrvConfig(const uint32_t sequence) @@ -43,7 +43,7 @@ SrvConfig::SrvConfig(const uint32_t sequence) cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()), cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()), class_dictionary_(new ClientClassDictionary()), - decline_timer_(0), dhcp4o6_port_(0) { + decline_timer_(0) { } std::string diff --git a/src/lib/dhcpsrv/srv_config.h b/src/lib/dhcpsrv/srv_config.h index 8523329892..7dc9afbeb6 100644 --- a/src/lib/dhcpsrv/srv_config.h +++ b/src/lib/dhcpsrv/srv_config.h @@ -439,24 +439,6 @@ public: return (decline_timer_); } - /// @brief Sets DHCP4o6 IPC port - /// - /// DHCPv4-over-DHCPv6 uses a UDP socket for interserver communication, - /// this socket is bound and connected to this port and port + 1 - /// - /// @param port port and port + 1 to use - void setDhcp4o6Port(uint32_t port) { - dhcp4o6_port_ = port; - } - - /// @brief Returns DHCP4o6 IPC port - /// - /// See @ref setDhcp4o6Port or brief discussion. - /// @return value of DHCP4o6 IPC port - uint32_t getDhcp4o6Port() { - return (dhcp4o6_port_); - } - private: /// @brief Sequence number identifying the configuration. @@ -522,12 +504,6 @@ private: /// This timer specifies decline probation period, the time after a declined /// lease is recovered back to available state. Expressed in seconds. uint32_t decline_timer_; - - /// @brief DHCP4o6 IPC port - /// - /// DHCPv4-over-DHCPv6 uses a UDP socket for interserver communication, - /// this socket is bound and connected to this port and port + 1 - uint32_t dhcp4o6_port_; }; /// @name Pointers to the @c SrvConfig object. diff --git a/src/lib/dhcpsrv/tests/Makefile.am b/src/lib/dhcpsrv/tests/Makefile.am index f7f2ebfd7e..d01bcb3108 100755 --- a/src/lib/dhcpsrv/tests/Makefile.am +++ b/src/lib/dhcpsrv/tests/Makefile.am @@ -85,7 +85,6 @@ libdhcpsrv_unittests_SOURCES += d2_udp_unittest.cc libdhcpsrv_unittests_SOURCES += daemon_unittest.cc libdhcpsrv_unittests_SOURCES += database_connection_unittest.cc libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc -libdhcpsrv_unittests_SOURCES += dhcp4o6_ipc_unittest.cc libdhcpsrv_unittests_SOURCES += duid_config_parser_unittest.cc libdhcpsrv_unittests_SOURCES += expiration_config_parser_unittest.cc libdhcpsrv_unittests_SOURCES += host_mgr_unittest.cc diff --git a/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc b/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc deleted file mode 100644 index 7b2201d134..0000000000 --- a/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc +++ /dev/null @@ -1,577 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace isc::asiolink; -using namespace isc::dhcp; -using namespace isc::dhcp::test; -using namespace isc::util; - -namespace { - -/// @brief Test port. -const uint16_t TEST_PORT = 12345; - -/// @brief Number of iterations used by the tests. -const uint16_t TEST_ITERATIONS = 10; - -/// @brief Type definition for the function creating DHCP message. -typedef boost::function CreateMsgFun; - -/// @brief Define short name for test IPC class. -typedef Dhcp4o6TestIpc TestIpc; - -/// @brief Test fixture class for @c Dhcp4o6IpcBase. -class Dhcp4o6IpcBaseTest : public ::testing::Test { -protected: - - /// @brief Constructor. - /// - /// Replaces the real configuration of interfaces with a fake configuration. - /// The IPC uses the @c IfaceMgr to check whether the interfaces which names - /// are carried within DHCP options exist in the system. Providing the fake - /// configuration for the @c IfaceMgr guarantees that the configuration is - /// consistent on any machine running the unit tests. - Dhcp4o6IpcBaseTest(); - - /// @brief Concatenates the prefix and postfix. - /// - /// @param prefix Prefix. - /// @param postfix Postfix. - /// @return String representing concatenated prefix and postfix. - static std::string concatenate(const std::string& prefix, const uint16_t postfix); - - /// @brief Creates an instance of the DHCPv4o6 message. - //// - /// @param msg_type Message type. - /// @param postfix Postfix to be appended to the remote address. For example, - /// for postfix = 5 the resulting remote address will be 2001:db8:1::5. - /// The postifx value is also used to generate the postfix for the interface. - /// The possible interface names are "eth0" and "eth1". For even postfix values - /// the "eth0" will be used, for odd postfix values "eth1" will be used. - /// - /// @return Pointer to the created message. - static Pkt6Ptr createDHCPv4o6Message(const uint16_t msg_type, - const uint16_t postfix = 0); - - /// @brief Creates an instance of the DHCPv4o6 message with vendor option. - /// - /// @param msg_type Message type. - /// @param postfix Postfix to be appended to the remote address. See the - /// documentation of @c createDHCPv4o6Message for details. - /// - /// @return Pointer to the created message. - static Pkt6Ptr createDHCPv4o6MsgWithVendorOption(const uint16_t msg_type, - const uint16_t postfix, - const uint32_t enterprise_id); - - /// @brief Creates an instance of the DHCPv4o6 message with ISC - /// vendor option. - /// - /// This is useful to test scenarios when the IPC is forwarding messages - /// that contain vendor option with ISC enterprise ID. - /// - /// @param msg_type Message type. - /// @param postfix Postfix to be appended to the remote address. See the - /// documentation of @c createDHCPv4o6Message for details. - /// - /// @return Pointer to the created message. - static Pkt6Ptr createDHCPv4o6MsgWithISCVendorOption(const uint16_t msg_type, - const uint16_t postfix); - - /// @brief Creates an instance of the DHCPv4o6 message with vendor - /// option holding enterprise id of 32000. - /// - /// This is useful to test scenarios when the IPC is forwarding messages - /// that contain some vendor option and when IPC also appends the ISC - /// vendor option to carry some DHCPv4o6 specific information. - /// - /// @param msg_type Message type. - /// @param postfix Postfix to be appended to the remote address. See the - /// documentation of @c createDHCPv4o6Message for details. - /// - /// @return Pointer to the created message. - static Pkt6Ptr createDHCPv4o6MsgWithAnyVendorOption(const uint16_t msg_type, - const uint16_t postfix); - - /// @brief Creates an instance of the DHCPv4o6 Message option. - /// - /// @param src Type of the source endpoint. It can be 4 or 6. - /// @return Pointer to the instance of the option. - static OptionPtr createDHCPv4MsgOption(const TestIpc::EndpointType& src); - - /// @brief Tests sending and receiving packets over the IPC. - /// - /// @param iterations_num Number of packets to be sent over the IPC. - /// @param src Type of the source IPC endpoint. It can be 4 or 6. - /// @param dest Type of the destination IPC endpoint. It can be 4 or 6. - void testSendReceive(const uint16_t iterations_num, - const TestIpc::EndpointType& src, - const TestIpc::EndpointType& dest, - const CreateMsgFun& create_msg_fun); - - /// @brief Tests that error is reported when invalid message is received. - /// - /// @param pkt Pointer to the invalid message. - void testReceiveError(const Pkt6Ptr& pkt); - -private: - - /// @brief Holds the fake configuration of the interfaces. - IfaceMgrTestConfig iface_mgr_test_config_; - -}; - -Dhcp4o6IpcBaseTest::Dhcp4o6IpcBaseTest() - : iface_mgr_test_config_(true) { -} - -std::string -Dhcp4o6IpcBaseTest::concatenate(const std::string& prefix, - const uint16_t postfix) { - std::ostringstream s; - s << prefix << postfix; - return (s.str()); -} - -Pkt6Ptr -Dhcp4o6IpcBaseTest::createDHCPv4o6Message(const uint16_t msg_type, - const uint16_t postfix) { - // Create the DHCPv4o6 message. - Pkt6Ptr pkt(new Pkt6(msg_type, 0)); - - // The interface name is carried in the dedicated option between - // the servers. The receiving server will check that such interface - // is present in the system. The fake configuration we're using for - // this test includes two interfaces: "eth0" and "eth1". Therefore, - // we pick one or another, depending on the index of the interation. - pkt->setIface(concatenate("eth", postfix % 2)); - - // The remote address of the sender of the DHCPv6 packet is carried - // between the servers in the dedicated option. We use different - // address for each iteration to make sure that the IPC delivers the - // right address. - pkt->setRemoteAddr(IOAddress(concatenate("2001:db8:1::", postfix))); - - // Determine the endpoint type using the message type. - const TestIpc::EndpointType src = (msg_type == DHCPV6_DHCPV4_QUERY) ? - TestIpc::ENDPOINT_TYPE_V6 : TestIpc::ENDPOINT_TYPE_V4; - - // Add DHCPv4 Message option to make sure it is conveyed by the IPC. - pkt->addOption(createDHCPv4MsgOption(src)); - - return (pkt); -} - -Pkt6Ptr -Dhcp4o6IpcBaseTest::createDHCPv4o6MsgWithVendorOption(const uint16_t msg_type, - const uint16_t postfix, - const uint32_t enterprise_id) { - Pkt6Ptr pkt = createDHCPv4o6Message(msg_type, postfix); - - // Create vendor option with ISC enterprise id. - OptionVendorPtr option_vendor(new OptionVendor(Option::V6, enterprise_id)); - - // Add some option to the vendor option. - option_vendor->addOption(OptionPtr(new Option(Option::V6, 100))); - - // Add vendor option to the message. - pkt->addOption(option_vendor); - - return (pkt); -} - -Pkt6Ptr -Dhcp4o6IpcBaseTest::createDHCPv4o6MsgWithISCVendorOption(const uint16_t msg_type, - const uint16_t postfix) { - return (createDHCPv4o6MsgWithVendorOption(msg_type, postfix, ENTERPRISE_ID_ISC)); -} - -Pkt6Ptr -Dhcp4o6IpcBaseTest::createDHCPv4o6MsgWithAnyVendorOption(const uint16_t msg_type, - const uint16_t postfix) { - return (createDHCPv4o6MsgWithVendorOption(msg_type, postfix, 32000)); -} - -OptionPtr -Dhcp4o6IpcBaseTest::createDHCPv4MsgOption(const TestIpc::EndpointType& src) { - // Create the DHCPv4 message. - Pkt4Ptr pkt(new Pkt4(src == TestIpc::ENDPOINT_TYPE_V4 ? DHCPACK : DHCPREQUEST, - 1234)); - // Make a wire representation of the DHCPv4 message. - pkt->pack(); - OutputBuffer& output_buffer = pkt->getBuffer(); - const uint8_t* data = static_cast(output_buffer.getData()); - OptionBuffer option_buffer(data, data + output_buffer.getLength()); - - // Create the DHCPv4 Message option holding the created message. - OptionPtr opt_msg(new Option(Option::V6, D6O_DHCPV4_MSG, option_buffer)); - return (opt_msg); -} - -void -Dhcp4o6IpcBaseTest::testSendReceive(const uint16_t iterations_num, - const TestIpc::EndpointType& src, - const TestIpc::EndpointType& dest, - const CreateMsgFun& create_msg_fun) { - // Create IPC instances representing the source and destination endpoints. - TestIpc ipc_src(TEST_PORT, src); - TestIpc ipc_dest(TEST_PORT, dest); - - // Open the IPC on both ends. - ASSERT_NO_THROW(ipc_src.open()); - ASSERT_NO_THROW(ipc_dest.open()); - - // Depnding if we're sending from DHCPv6 to DHCPv4 or the opposite - // direction we use different message type. This is not really required - // for testing IPC, but it better simulates the real use case. - uint16_t msg_type = (src == TestIpc::ENDPOINT_TYPE_V6 ? DHCPV6_DHCPV4_QUERY : - DHCPV6_DHCPV4_RESPONSE); - - std::vector has_vendor_option; - - // Send the number of messages configured for the test. - for (uint16_t i = 1; i <= iterations_num; ++i) { - // Create the DHCPv4o6 message. - Pkt6Ptr pkt = create_msg_fun(msg_type, i); - - // Remember if the vendor option exists in the source packet. The - // received packet should also contain this option if it exists - // in the source packet. - has_vendor_option.push_back(static_cast(pkt->getOption(D6O_VENDOR_OPTS))); - - // Actaully send the message through the IPC. - ASSERT_NO_THROW(ipc_src.send(pkt)) - << "Failed to send the message over the IPC for iteration " << i; - } - - // Try to receive all messages. - for (uint16_t i = 1; i <= iterations_num; ++i) { - - // Call receive with a timeout. The data should appear on the socket - // within this time. - ASSERT_NO_THROW(IfaceMgr::instance().receive6(1, 0)); - - // Pop the received message. - Pkt6Ptr pkt_received = ipc_dest.popPktReceived(); - ASSERT_TRUE(pkt_received); - - // Check that the message type is correct. - EXPECT_EQ(msg_type, pkt_received->getType()); - - // Check that the interface is correct. - EXPECT_EQ(concatenate("eth", i % 2), pkt_received->getIface()); - - // Check that the address conveyed is correct. - EXPECT_EQ(concatenate("2001:db8:1::", i), - pkt_received->getRemoteAddr().toText()); - - // Check that encapsulated DHCPv4 message has been received. - EXPECT_TRUE(pkt_received->getOption(D6O_DHCPV4_MSG)); - - if (has_vendor_option[i - 1]) { - // Make sure that the vendor option wasn't deleted when the packet was - // received. - OptionPtr option_vendor = pkt_received->getOption(D6O_VENDOR_OPTS); - ASSERT_TRUE(option_vendor) - << "vendor option deleted in the received DHCPv4o6 packet for" - " iteration " << i; - - // ISC_V6_4O6_INTERFACE shouldn't be present. - EXPECT_FALSE(option_vendor->getOption(ISC_V6_4O6_INTERFACE)); - - // ISC_V6_4O6_SRC_ADDRESS shouldn't be present. - EXPECT_FALSE(option_vendor->getOption(ISC_V6_4O6_SRC_ADDRESS)); - - } else { - EXPECT_FALSE(pkt_received->getOption(D6O_VENDOR_OPTS)); - } - } -} - -void -Dhcp4o6IpcBaseTest::testReceiveError(const Pkt6Ptr& pkt) { - TestIpc ipc_src(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6); - TestIpc ipc_dest(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - - // Open the IPC on both ends. - ASSERT_NO_THROW(ipc_src.open()); - ASSERT_NO_THROW(ipc_dest.open()); - - pkt->setIface("eth0"); - pkt->setRemoteAddr(IOAddress("2001:db8:1::1")); - pkt->addOption(createDHCPv4MsgOption(TestIpc::ENDPOINT_TYPE_V6)); - - OutputBuffer& buf = pkt->getBuffer(); - buf.clear(); - ASSERT_NO_THROW(pkt->pack()); - - ASSERT_NE(-1, ::send(ipc_src.getSocketFd(), buf.getData(), - buf.getLength(), 0)); - - // Call receive with a timeout. The data should appear on the socket - // within this time. - ASSERT_THROW(IfaceMgr::instance().receive6(1, 0), Dhcp4o6IpcError); -} - - -// This test verifies that the IPC can transmit messages between the -// DHCPv4 and DHCPv6 server. -TEST_F(Dhcp4o6IpcBaseTest, send4To6) { - testSendReceive(TEST_ITERATIONS, TestIpc::ENDPOINT_TYPE_V4, - TestIpc::ENDPOINT_TYPE_V6, &createDHCPv4o6Message); -} - -// This test verifies that the IPC can transmit messages between the -// DHCPv6 and DHCPv4 server. -TEST_F(Dhcp4o6IpcBaseTest, send6To4) { - testSendReceive(TEST_ITERATIONS, TestIpc::ENDPOINT_TYPE_V6, - TestIpc::ENDPOINT_TYPE_V4, &createDHCPv4o6Message); -} - -// This test verifies that the IPC will transmit message already containing -// vendor option with ISC enterprise ID, between the DHCPv6 and DHCPv4 -// server. -TEST_F(Dhcp4o6IpcBaseTest, send6To4WithISCVendorOption) { - testSendReceive(TEST_ITERATIONS, TestIpc::ENDPOINT_TYPE_V6, - TestIpc::ENDPOINT_TYPE_V4, - &createDHCPv4o6MsgWithISCVendorOption); -} - -// This test verifies that the IPC will transmit message already containing -// vendor option with ISC enterprise ID, between the DHCPv6 and DHCPv4 -// server. -TEST_F(Dhcp4o6IpcBaseTest, send4To6WithISCVendorOption) { - testSendReceive(TEST_ITERATIONS, TestIpc::ENDPOINT_TYPE_V4, - TestIpc::ENDPOINT_TYPE_V6, - &createDHCPv4o6MsgWithISCVendorOption); -} - -// This test verifies that the IPC will transmit message already containing -// vendor option with enterprise id different than ISC, between the DHCPv6 -// and DHCPv4 server. -TEST_F(Dhcp4o6IpcBaseTest, send6To4WithAnyVendorOption) { - testSendReceive(TEST_ITERATIONS, TestIpc::ENDPOINT_TYPE_V6, - TestIpc::ENDPOINT_TYPE_V4, - &createDHCPv4o6MsgWithAnyVendorOption); -} - -// This test verifies that the IPC will transmit message already containing -// vendor option with enterprise id different than ISC, between the DHCPv4 -// and DHCPv6 server. -TEST_F(Dhcp4o6IpcBaseTest, send4To6WithAnyVendorOption) { - testSendReceive(TEST_ITERATIONS, TestIpc::ENDPOINT_TYPE_V4, - TestIpc::ENDPOINT_TYPE_V6, - &createDHCPv4o6MsgWithAnyVendorOption); -} - -// This test checks that the values of the socket descriptor are correct -// when the socket is opened and then closed. -TEST_F(Dhcp4o6IpcBaseTest, openClose) { - TestIpc ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - EXPECT_EQ(-1, ipc.getSocketFd()); - - ASSERT_NO_THROW(ipc.open()); - EXPECT_NE(-1, ipc.getSocketFd()); - - ASSERT_NO_THROW(ipc.close()); - EXPECT_EQ(-1, ipc.getSocketFd()); -} - -// This test verifies that it is call open() while the socket is already -// opened. If the port changes, the new socket should be opened. -TEST_F(Dhcp4o6IpcBaseTest, openMultipleTimes) { - TestIpc ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V6); - ASSERT_NO_THROW(ipc.open()); - int sock_fd = ipc.getSocketFd(); - ASSERT_NE(-1, sock_fd); - ASSERT_EQ(TEST_PORT, ipc.getPort()); - - ASSERT_NO_THROW(ipc.open()); - ASSERT_EQ(sock_fd, ipc.getSocketFd()); - ASSERT_EQ(TEST_PORT, ipc.getPort()); - - ipc.setDesiredPort(TEST_PORT + 10); - ASSERT_NO_THROW(ipc.open()); - ASSERT_NE(-1, ipc.getSocketFd()); - - EXPECT_EQ(TEST_PORT + 10, ipc.getPort()); -} - -// This test verifies that the socket remains open if there is a failure -// to open a new socket. -TEST_F(Dhcp4o6IpcBaseTest, openError) { - TestIpc ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - ASSERT_NO_THROW(ipc.open()); - int sock_fd = ipc.getSocketFd(); - ASSERT_NE(-1, sock_fd); - - TestIpc ipc_bound(TEST_PORT + 10, TestIpc::ENDPOINT_TYPE_V4); - ASSERT_NO_THROW(ipc_bound.open()); - ASSERT_NE(-1, ipc_bound.getSocketFd()); - - ipc.setDesiredPort(TEST_PORT + 10); - ASSERT_THROW(ipc.open(), isc::dhcp::Dhcp4o6IpcError); - - EXPECT_EQ(sock_fd, ipc.getSocketFd()); - EXPECT_EQ(TEST_PORT, ipc.getPort()); - - ASSERT_NO_THROW(ipc_bound.close()); - ASSERT_NO_THROW(ipc.open()); - EXPECT_NE(-1, ipc.getSocketFd()); - EXPECT_EQ(TEST_PORT + 10, ipc.getPort()); -} - -// This test verifies that the IPC returns an error when trying to bind -// to the out of range port. -TEST_F(Dhcp4o6IpcBaseTest, invalidPortError4) { - TestIpc ipc(65535, TestIpc::ENDPOINT_TYPE_V4); - EXPECT_THROW(ipc.open(), Dhcp4o6IpcError); -} - -// This test verifies that the IPC returns an error when trying to bind -// to the out of range port. -TEST_F(Dhcp4o6IpcBaseTest, invalidPortError6) { - TestIpc ipc(65535, TestIpc::ENDPOINT_TYPE_V6); - EXPECT_THROW(ipc.open(), Dhcp4o6IpcError); -} - -// This test verifies that receiving packet over the IPC fails when there -// is no vendor option present. -TEST_F(Dhcp4o6IpcBaseTest, receiveWithoutVendorOption) { - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 0)); - testReceiveError(pkt); -} - -// This test verifies that receving packet over the IPC fails when the -// enterprise ID carried in the vendor option is invalid. -TEST_F(Dhcp4o6IpcBaseTest, receiveInvalidEnterpriseId) { - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 0)); - OptionVendorPtr option_vendor(new OptionVendor(Option::V6, 1)); - option_vendor->addOption( - OptionStringPtr(new OptionString(Option::V6, ISC_V6_4O6_INTERFACE, - "eth0"))); - option_vendor->addOption( - Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, - IOAddress("2001:db8:1::1"))) - ); - - pkt->addOption(option_vendor); - testReceiveError(pkt); -} - -// This test verifies that receiving packet over the IPC fails when the -// interface option is not present. -TEST_F(Dhcp4o6IpcBaseTest, receiveWithoutInterfaceOption) { - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 0)); - OptionVendorPtr option_vendor(new OptionVendor(Option::V6, - ENTERPRISE_ID_ISC)); - option_vendor->addOption( - Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, - IOAddress("2001:db8:1::1"))) - ); - - pkt->addOption(option_vendor); - testReceiveError(pkt); -} - -// This test verifies that receiving packet over the IPC fails when the -// interface which name is carried in the option is not present in the -// system. -TEST_F(Dhcp4o6IpcBaseTest, receiveWithInvalidInterface) { - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 0)); - OptionVendorPtr option_vendor(new OptionVendor(Option::V6, - ENTERPRISE_ID_ISC)); - option_vendor->addOption( - OptionStringPtr(new OptionString(Option::V6, ISC_V6_4O6_INTERFACE, - "ethX"))); - option_vendor->addOption( - Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, - IOAddress("2001:db8:1::1"))) - ); - - pkt->addOption(option_vendor); - testReceiveError(pkt); -} - - -// This test verifies that receving packet over the IPC fails when the -// source address option is not present. -TEST_F(Dhcp4o6IpcBaseTest, receiveWithoutSourceAddressOption) { - Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 0)); - OptionVendorPtr option_vendor(new OptionVendor(Option::V6, - ENTERPRISE_ID_ISC)); - option_vendor->addOption( - OptionStringPtr(new OptionString(Option::V6, ISC_V6_4O6_INTERFACE, - "eth0"))); - - pkt->addOption(option_vendor); - testReceiveError(pkt); -} - -// This test verifies that send method throws exception when the packet -// is NULL. -TEST_F(Dhcp4o6IpcBaseTest, sendNullMessage) { - TestIpc ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - ASSERT_NO_THROW(ipc.open()); - - // NULL message. - EXPECT_THROW(ipc.send(Pkt6Ptr()), Dhcp4o6IpcError); -} - -// This test verifies that send method throws exception when the IPC -// socket is not opened. -TEST_F(Dhcp4o6IpcBaseTest, sendOverClosedSocket) { - TestIpc ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - - // Create a message. - Pkt6Ptr pkt(createDHCPv4o6Message(DHCPV6_DHCPV4_QUERY)); - - // Sending over the closed socket should fail. - EXPECT_THROW(ipc.send(pkt), Dhcp4o6IpcError); -} - -// This test verifies that send method throws exception when the IPC -// socket has been unexpectedly closed. -TEST_F(Dhcp4o6IpcBaseTest, sendOverUnexpectedlyClosedSocket) { - TestIpc ipc(TEST_PORT, TestIpc::ENDPOINT_TYPE_V4); - ASSERT_NO_THROW(ipc.open()); - - // Close the socket behind the scenes. The IPC doesn't know that the - // socket has been closed and it still holds the descriptor. - ::close(ipc.getSocketFd()); - - // Create a message. - Pkt6Ptr pkt(createDHCPv4o6Message(DHCPV6_DHCPV4_QUERY)); - - // Sending over the closed socket should fail. - EXPECT_THROW(ipc.send(pkt), Dhcp4o6IpcError); -} - -} // end of anonymous namespace diff --git a/src/lib/dhcpsrv/testutils/Makefile.am b/src/lib/dhcpsrv/testutils/Makefile.am index 650cfbbcae..f420fb4302 100644 --- a/src/lib/dhcpsrv/testutils/Makefile.am +++ b/src/lib/dhcpsrv/testutils/Makefile.am @@ -16,8 +16,6 @@ if HAVE_GTEST noinst_LTLIBRARIES = libdhcpsrvtest.la libdhcpsrvtest_la_SOURCES = config_result_check.cc config_result_check.h -libdhcpsrvtest_la_SOURCES += dhcp4o6_test_ipc.cc dhcp4o6_test_ipc.h - libdhcpsrvtest_la_CXXFLAGS = $(AM_CXXFLAGS) libdhcpsrvtest_la_CPPFLAGS = $(AM_CPPFLAGS) libdhcpsrvtest_la_LDFLAGS = $(AM_LDFLAGS) diff --git a/src/lib/dhcpsrv/testutils/dhcp4o6_test_ipc.cc b/src/lib/dhcpsrv/testutils/dhcp4o6_test_ipc.cc deleted file mode 100644 index ed7bbedd59..0000000000 --- a/src/lib/dhcpsrv/testutils/dhcp4o6_test_ipc.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include -#include -#include -#include - -namespace isc { -namespace dhcp { -namespace test { - -Dhcp4o6TestIpc::Dhcp4o6TestIpc(const uint16_t port, - const EndpointType& endpoint_type) - : desired_port_(port), endpoint_type_(endpoint_type), pkt_received_() { -} - -void -Dhcp4o6TestIpc::open() { - // Use the base IPC to open the socket. - socket_fd_ = Dhcp4o6IpcBase::open(desired_port_, endpoint_type_); - // If the socket has been opened correctly, register it in the @c IfaceMgr. - if (socket_fd_ != -1) { - IfaceMgr& iface_mgr = IfaceMgr::instance(); - iface_mgr.addExternalSocket(socket_fd_, - boost::bind(&Dhcp4o6TestIpc::receiveHandler, - this)); - } -} - -void -Dhcp4o6TestIpc::receiveHandler() { - pkt_received_ = receive(); -} - - -} // end of isc::dhcp::test namespace -} // end of isc::dhcp namespace -} // end of isc namespace diff --git a/src/lib/dhcpsrv/testutils/dhcp4o6_test_ipc.h b/src/lib/dhcpsrv/testutils/dhcp4o6_test_ipc.h deleted file mode 100644 index 1a8cd0917b..0000000000 --- a/src/lib/dhcpsrv/testutils/dhcp4o6_test_ipc.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef DHCP4O6_TEST_IPC_H -#define DHCP4O6_TEST_IPC_H - -#include -#include -#include -#include -#include -#include - -namespace isc { -namespace dhcp { -namespace test { - -/// @brief Implements a simple IPC for the test. -class Dhcp4o6TestIpc : public Dhcp4o6IpcBase { -public: - - /// @brief Constructor. - /// - /// @param port Desired port. - /// @param endpoint_type Type of the IPC endpoint. It should be 4 or 6. - Dhcp4o6TestIpc(const uint16_t port, const EndpointType& endpoint_type); - - /// @brief Sets new port to be used with @c open. - /// - /// @param desired_port New desired port. - void setDesiredPort(const uint16_t desired_port) { - desired_port_ = desired_port; - } - - /// @brief Opens the IPC socket and registers it in @c IfaceMgr. - /// - /// This method opens the IPC socket and registers it as external - /// socket in the IfaceMgr. The @c TestIpc::receiveHandler is used as a - /// callback to be called by the @c IfaceMgr when the data is received - /// over the socket. - virtual void open(); - - /// @brief Retrieve port which socket is bound to. - uint16_t getPort() const { - return (port_); - } - - /// @brief Retrieve socket descriptor. - int getSocketFd() const { - return (socket_fd_); - } - - /// @brief Pops and returns a received message. - /// - /// @return Pointer to the received message over the IPC. - Pkt6Ptr popPktReceived() { - // Copy the received message. - Pkt6Ptr pkt_copy(pkt_received_); - // Set the received message to NULL (pop). - pkt_received_.reset(); - // Return the copy. - return (pkt_copy); - } - -private: - - /// @brief Callback for the IPC socket. - /// - /// This callback is called by the @c IfaceMgr when the data is received - /// over the IPC socket. - void receiveHandler(); - - /// @brief Port number. - uint16_t desired_port_; - - /// @brief Endpoint type, i.e. 4 or 6. - EndpointType endpoint_type_; - - /// @brief Pointer to the last received message. - Pkt6Ptr pkt_received_; -}; - - - -}; // end of isc::dhcp::test namespace -}; // end of isc::dhcp namespace -}; // end of isc namespace - -#endif // DHCP4O6_TEST_IPC_H