Commit afad9d6d authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[4106] Throw exception of the packet sent over IPC is invalid.

parent e42ed520
......@@ -139,22 +139,48 @@ Pkt6Ptr Dhcp4o6IpcBase::receive() {
OptionVendorPtr vendor =
boost::dynamic_pointer_cast<OptionVendor>(pkt->getOption(D6O_VENDOR_OPTS));
if (!vendor || vendor->getVendorId() != ENTERPRISE_ID_ISC) {
return (Pkt6Ptr());
// Vendor option must exist.
if (!vendor) {
isc_throw(Dhcp4o6IpcError, "option " << D6O_VENDOR_OPTS
<< " not present in the DHCP4o6 message sent between the "
" servers");
}
// The vendor option must require appropriate enterprise-id.
if (vendor->getVendorId() != ENTERPRISE_ID_ISC) {
isc_throw(Dhcp4o6IpcError, "option " << D6O_VENDOR_OPTS
<< " in the DHCP4o6 message contains invalid enterprise-id '"
<< vendor->getVendorId() << "'. Expected enterprise-id '"
<< ENTERPRISE_ID_ISC << "'");
}
OptionStringPtr ifname =
boost::dynamic_pointer_cast<OptionString>(vendor->getOption(ISC_V6_4O6_INTERFACE));
// The option carrying interface name is required.
OptionStringPtr ifname = boost::dynamic_pointer_cast<
OptionString>(vendor->getOption(ISC_V6_4O6_INTERFACE));
if (!ifname) {
return (Pkt6Ptr());
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) {
return (Pkt6Ptr());
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>(vendor->getOption(ISC_V6_4O6_SRC_ADDRESS));
if (!srcs) {
return (Pkt6Ptr());
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 and return it
......@@ -180,11 +206,11 @@ void Dhcp4o6IpcBase::send(const Pkt6Ptr& pkt) {
OptionVendorPtr vendor(new OptionVendor(Option::V6, ENTERPRISE_ID_ISC));
// Push interface name and source address in it
vendor->addOption(OptionPtr(new OptionString(Option::V6,
ISC_V6_4O6_INTERFACE,
pkt->getIface())));
vendor->addOption(OptionPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS,
pkt->getRemoteAddr())));
vendor->addOption(OptionStringPtr(new OptionString(Option::V6,
ISC_V6_4O6_INTERFACE,
pkt->getIface())));
vendor->addOption(Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS,
pkt->getRemoteAddr())));
pkt->addOption(vendor);
// Get packet content
......
......@@ -17,6 +17,9 @@
#include <dhcp/option_vendor.h>
#include <dhcp/pkt6.h>
#include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp/option6_addrlst.h>
#include <dhcp/option_string.h>
#include <dhcp/option_vendor.h>
#include <dhcpsrv/dhcp4o6_ipc.h>
#include <boost/bind.hpp>
#include <gtest/gtest.h>
......@@ -164,6 +167,11 @@ protected:
void testSendReceive(const uint16_t iterations_num, const int src,
const int dest);
/// @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.
......@@ -269,6 +277,32 @@ Dhcp4o6IpcBaseTest::testSendReceive(const uint16_t iterations_num,
}
}
void
Dhcp4o6IpcBaseTest::testReceiveError(const Pkt6Ptr& pkt) {
TestIpc ipc_src(TEST_PORT, ENDPOINT_TYPE_V6);
TestIpc ipc_dest(TEST_PORT, 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(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
// DHCPv6 and DHCPv4 server.
TEST_F(Dhcp4o6IpcBaseTest, send4To6) {
......@@ -339,4 +373,78 @@ TEST_F(Dhcp4o6IpcBaseTest, openError) {
}
// 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 pakcet 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);
}
} // end of anonymous namespace
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment