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

[4106] Improved IPC handler functions for DHCPv4 and DHCPv6 server.

parent 12bb3721
......@@ -48,20 +48,36 @@ void Dhcp4o6Ipc::open() {
void Dhcp4o6Ipc::handler() {
Dhcp4o6Ipc& ipc = Dhcp4o6Ipc::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.size() != 1) {
return;
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 = pkt->getOption(D6O_DHCPV4_MSG);
OptionPtr msg = msgs.begin()->second;
if (!msg) {
isc_throw(Unexpected, "Can't get DHCPv4 message option");
isc_throw(Dhcp4o6IpcError, "null DHCPv4 message option in the"
" DHCPv4o6 message received by the DHCPv4 server");
}
instance().received_.reset(new Pkt4o6(msg->getData(), pkt));
// Record this message.
ipc.received_.reset(new Pkt4o6(msg->getData(), pkt));
}
Pkt4o6Ptr& Dhcp4o6Ipc::getReceived() {
......
......@@ -46,23 +46,30 @@ void Dhcp4o6Ipc::open() {
}
void Dhcp4o6Ipc::handler() {
std::cout << "handler" << std::endl;
Dhcp4o6Ipc& ipc = Dhcp4o6Ipc::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 = buf[0];
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);
}
......
......@@ -111,6 +111,7 @@ TEST_F(Dhcp4o6IpcTest, receive) {
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
......
......@@ -13,7 +13,9 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <exceptions/exceptions.h>
#include <dhcp/tests/pkt_filter6_test_stub.h>
#include <netinet/in.h>
#include <list>
namespace {
......@@ -38,7 +40,43 @@ SocketInfo
PktFilter6TestStub::openSocket(const Iface&,
const isc::asiolink::IOAddress& addr,
const uint16_t port, const bool) {
return (SocketInfo(addr, port, 0));
// 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<const void*>(&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));
}
Pkt6Ptr
......
......@@ -36,11 +36,10 @@ public:
/// @brief Constructor.
PktFilter6TestStub();
/// @brief Simulate opening of the socket.
/// @brief Open a 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.
/// This function opens a socket. This socket is bound to any address
/// and port. The select() function may be called on this socket.
///
/// @param iface An interface descriptor.
/// @param addr Address on the interface to be used to send packets.
......@@ -50,8 +49,7 @@ public:
///
/// @note All parameters are ignored.
///
/// @return A SocketInfo structure with the socket descriptor set to 0. The
/// fallback socket descriptor is set to a negative value.
/// @return A SocketInfo structure with the socket descriptor.
virtual SocketInfo openSocket(const Iface& iface,
const isc::asiolink::IOAddress& addr,
const uint16_t port,
......
Markdown is supported
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