summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp/tests/pkt_filter_inet_unittest.cc')
-rw-r--r--src/lib/dhcp/tests/pkt_filter_inet_unittest.cc148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc b/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
new file mode 100644
index 0000000..a8d495c
--- /dev/null
+++ b/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
@@ -0,0 +1,148 @@
+// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <asiolink/io_address.h>
+#include <dhcp/iface_mgr.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt_filter_inet.h>
+#include <dhcp/tests/pkt_filter_test_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <sys/socket.h>
+
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+namespace {
+
+/// Port number used by tests.
+const uint16_t PORT = 10067;
+/// Size of the buffer holding received packets.
+const size_t RECV_BUF_SIZE = 2048;
+
+// Test fixture class inherits from the class common for all packet
+// filter tests.
+class PktFilterInetTest : public isc::dhcp::test::PktFilterTest {
+public:
+ PktFilterInetTest() : PktFilterTest(PORT) {
+ }
+};
+
+// This test verifies that the PktFilterInet class reports its lack
+// of capability to send packets to the host having no IP address
+// assigned.
+TEST_F(PktFilterInetTest, isDirectResponseSupported) {
+ // Create object under test.
+ PktFilterInet pkt_filter;
+ // This Packet Filter class does not support direct responses
+ // under any conditions.
+ EXPECT_FALSE(pkt_filter.isDirectResponseSupported());
+}
+
+// This test verifies that the INET datagram socket is correctly opened and
+// bound to the appropriate address and port.
+TEST_F(PktFilterInetTest, openSocket) {
+ // Create object representing loopback interface.
+ Iface iface(ifname_, ifindex_);
+ // Set loopback address.
+ IOAddress addr("127.0.0.1");
+
+ // Try to open socket.
+ PktFilterInet pkt_filter;
+ sock_info_ = pkt_filter.openSocket(iface, addr, PORT,
+ false, false);
+ // For the packet filter in use, the fallback socket shouldn't be opened.
+ // Fallback is typically opened for raw sockets.
+ EXPECT_LT(sock_info_.fallbackfd_, 0);
+
+ // Test the primary socket.
+ testDgramSocket(sock_info_.sockfd_);
+}
+
+// This test verifies that the packet is correctly sent over the INET
+// datagram socket.
+TEST_F(PktFilterInetTest, send) {
+ // Packet will be sent over loopback interface.
+ Iface iface(ifname_, ifindex_);
+ IOAddress addr("127.0.0.1");
+
+ // Create an instance of the class which we are testing.
+ PktFilterInet pkt_filter;
+ // Open socket. We don't check that the socket has appropriate
+ // options and family set because we have checked that in the
+ // openSocket test already.
+ sock_info_ = pkt_filter.openSocket(iface, addr, PORT, false, false);
+ ASSERT_GE(sock_info_.sockfd_, 0);
+
+ // Send the packet over the socket.
+ int result = -1;
+ ASSERT_NO_THROW(result = pkt_filter.send(iface, sock_info_.sockfd_, test_message_));
+ ASSERT_EQ(0, result);
+
+ // Read the data from socket.
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(sock_info_.sockfd_, &readfds);
+
+ struct timeval timeout;
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+ result = select(sock_info_.sockfd_ + 1, &readfds, NULL, NULL, &timeout);
+ // We should receive some data from loopback interface.
+ ASSERT_GT(result, 0);
+
+ // Get the actual data.
+ uint8_t rcv_buf[RECV_BUF_SIZE];
+ result = recv(sock_info_.sockfd_, rcv_buf, RECV_BUF_SIZE, 0);
+ ASSERT_GT(result, 0);
+
+ // Create the DHCPv4 packet from the received data.
+ Pkt4Ptr rcvd_pkt(new Pkt4(rcv_buf, result));
+ ASSERT_TRUE(rcvd_pkt);
+
+ // Parse the packet.
+ ASSERT_NO_THROW(rcvd_pkt->unpack());
+
+ // Check if the received message is correct.
+ testRcvdMessage(rcvd_pkt);
+
+}
+
+// This test verifies that the DHCPv4 packet is correctly received via
+// INET datagram socket and that it matches sent packet.
+TEST_F(PktFilterInetTest, receive) {
+
+ // Packet will be received over loopback interface.
+ Iface iface(ifname_, ifindex_);
+ IOAddress addr("127.0.0.1");
+
+ // Create an instance of the class which we are testing.
+ PktFilterInet pkt_filter;
+ // Open socket. We don't check that the socket has appropriate
+ // options and family set because we have checked that in the
+ // openSocket test already.
+ sock_info_ = pkt_filter.openSocket(iface, addr, PORT, false, false);
+ ASSERT_GE(sock_info_.sockfd_, 0);
+
+ // Send a DHCPv4 message to the local loopback address and server's port.
+ sendMessage();
+
+ // Receive the packet.
+ Pkt4Ptr rcvd_pkt = pkt_filter.receive(iface, sock_info_);
+ // Check that the packet has been correctly received.
+ ASSERT_TRUE(rcvd_pkt);
+
+ // Parse the packet.
+ ASSERT_NO_THROW(rcvd_pkt->unpack());
+
+ // Check if the received message is correct.
+ testRcvdMessage(rcvd_pkt);
+ testRcvdMessageAddressPort(rcvd_pkt);
+}
+
+} // anonymous namespace