|
@@ -44,7 +44,6 @@
|
|
|
|
|
|
#include <boost/scoped_ptr.hpp>
|
|
|
|
|
|
-#include <fstream>
|
|
|
#include <iostream>
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
@@ -59,72 +58,28 @@ using namespace isc::dhcp::test;
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
-/// dummy server-id file location
|
|
|
-const char* SRVID_FILE = "server-id-test.txt";
|
|
|
-
|
|
|
-// Sanity check. Verifies that both Dhcpv4Srv and its derived
|
|
|
-// class NakedDhcpv4Srv can be instantiated and destroyed.
|
|
|
-TEST_F(Dhcpv4SrvTest, basic) {
|
|
|
-
|
|
|
- // Check that the base class can be instantiated
|
|
|
- boost::scoped_ptr<Dhcpv4Srv> srv;
|
|
|
- ASSERT_NO_THROW(srv.reset(new Dhcpv4Srv(DHCP4_SERVER_PORT + 10000, "type=memfile",
|
|
|
- false, false)));
|
|
|
- srv.reset();
|
|
|
- // We have to close open sockets because further in this test we will
|
|
|
- // call the Dhcpv4Srv constructor again. This constructor will try to
|
|
|
- // set the appropriate packet filter class for IfaceMgr. This requires
|
|
|
- // that all sockets are closed.
|
|
|
- IfaceMgr::instance().closeSockets();
|
|
|
-
|
|
|
- // Check that the derived class can be instantiated
|
|
|
- boost::scoped_ptr<NakedDhcpv4Srv> naked_srv;
|
|
|
- ASSERT_NO_THROW(
|
|
|
- naked_srv.reset(new NakedDhcpv4Srv(DHCP4_SERVER_PORT + 10000)));
|
|
|
- EXPECT_TRUE(naked_srv->getServerID());
|
|
|
- // Close sockets again for the next test.
|
|
|
- IfaceMgr::instance().closeSockets();
|
|
|
-
|
|
|
- ASSERT_NO_THROW(naked_srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
- EXPECT_TRUE(naked_srv->getServerID());
|
|
|
-}
|
|
|
-
|
|
|
-// This test verifies that exception is not thrown when an error occurs during
|
|
|
-// opening sockets. This test forces an error by adding a fictious interface
|
|
|
-// to the IfaceMgr. An attempt to open socket on this interface must always
|
|
|
-// fail. The DHCPv4 installs the error handler function to prevent exceptions
|
|
|
-// being thrown from the openSockets4 function.
|
|
|
-// @todo The server tests for socket should be extended but currently the
|
|
|
-// ability to unit test the sockets code is somewhat limited.
|
|
|
-TEST_F(Dhcpv4SrvTest, openActiveSockets) {
|
|
|
- ASSERT_NO_THROW(CfgMgr::instance().activateAllIfaces());
|
|
|
-
|
|
|
- Iface iface("bogusiface", 255);
|
|
|
- iface.flag_loopback_ = false;
|
|
|
- iface.flag_up_ = true;
|
|
|
- iface.flag_running_ = true;
|
|
|
- iface.inactive4_ = false;
|
|
|
- iface.addAddress(IOAddress("192.0.0.0"));
|
|
|
- IfaceMgr::instance().addInterface(iface);
|
|
|
- ASSERT_NO_THROW(Dhcpv4Srv::openActiveSockets(DHCP4_SERVER_PORT, false));
|
|
|
-}
|
|
|
-
|
|
|
// This test verifies that the destination address of the response
|
|
|
// message is set to giaddr, when giaddr is set to non-zero address
|
|
|
// in the received message.
|
|
|
-TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRelay) {
|
|
|
- boost::scoped_ptr<NakedDhcpv4Srv> srv(new NakedDhcpv4Srv(0));
|
|
|
-
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, adjustIfaceDataRelay) {
|
|
|
// Create the instance of the incoming packet.
|
|
|
boost::shared_ptr<Pkt4> req(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
- // Set the giaddr to non-zero address as if it was relayed.
|
|
|
+ // Set the giaddr to non-zero address and hops to non-zero value
|
|
|
+ // as if it was relayed.
|
|
|
req->setGiaddr(IOAddress("192.0.2.1"));
|
|
|
+ req->setHops(2);
|
|
|
// Set ciaddr to zero. This simulates the client which applies
|
|
|
// for the new lease.
|
|
|
req->setCiaddr(IOAddress("0.0.0.0"));
|
|
|
// Clear broadcast flag.
|
|
|
req->setFlags(0x0000);
|
|
|
|
|
|
+ // Set local address, port and interface.
|
|
|
+ req->setLocalAddr(IOAddress("192.0.3.1"));
|
|
|
+ req->setLocalPort(1001);
|
|
|
+ req->setIface("eth0");
|
|
|
+ req->setIndex(1);
|
|
|
+
|
|
|
// Create a response packet. Assume that the new lease have
|
|
|
// been created and new address allocated. This address is
|
|
|
// stored in yiaddr field.
|
|
@@ -132,12 +87,24 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRelay) {
|
|
|
resp->setYiaddr(IOAddress("192.0.2.100"));
|
|
|
// Clear the remote address.
|
|
|
resp->setRemoteAddr(IOAddress("0.0.0.0"));
|
|
|
+ // Set hops value for the response.
|
|
|
+ resp->setHops(req->getHops());
|
|
|
|
|
|
// This function never throws.
|
|
|
- ASSERT_NO_THROW(srv->adjustRemoteAddr(req, resp));
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp));
|
|
|
|
|
|
// Now the destination address should be relay's address.
|
|
|
EXPECT_EQ("192.0.2.1", resp->getRemoteAddr().toText());
|
|
|
+ // The query has been relayed, so the response must be sent to the port 67.
|
|
|
+ EXPECT_EQ(DHCP4_SERVER_PORT, resp->getRemotePort());
|
|
|
+ // Local address should be copied from the query message.
|
|
|
+ EXPECT_EQ("192.0.3.1", resp->getLocalAddr().toText());
|
|
|
+ // The local port is always DHCPv4 server port 67.
|
|
|
+ EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
|
|
|
+ // We will send response over the same interface which was used to receive
|
|
|
+ // query.
|
|
|
+ EXPECT_EQ("eth0", resp->getIface());
|
|
|
+ EXPECT_EQ(1, resp->getIndex());
|
|
|
|
|
|
// Let's do another test and set other fields: ciaddr and
|
|
|
// flags. By doing it, we want to make sure that the relay
|
|
@@ -150,7 +117,7 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRelay) {
|
|
|
// Clear remote address.
|
|
|
resp->setRemoteAddr(IOAddress("0.0.0.0"));
|
|
|
|
|
|
- ASSERT_NO_THROW(srv->adjustRemoteAddr(req, resp));
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp));
|
|
|
|
|
|
// Response should be sent back to the relay address.
|
|
|
EXPECT_EQ("192.0.2.50", resp->getRemoteAddr().toText());
|
|
@@ -160,9 +127,7 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRelay) {
|
|
|
// is set to ciaddr when giaddr is set to zero and the ciaddr is set to
|
|
|
// non-zero address in the received message. This is the case when the
|
|
|
// client is in Renew or Rebind state.
|
|
|
-TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRenewRebind) {
|
|
|
- boost::scoped_ptr<NakedDhcpv4Srv> srv(new NakedDhcpv4Srv(0));
|
|
|
-
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, adjustIfaceDataRenew) {
|
|
|
// Create instance of the incoming packet.
|
|
|
boost::shared_ptr<Pkt4> req(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
|
|
@@ -179,6 +144,15 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRenewRebind) {
|
|
|
// whether to unicast the response to the acquired address or
|
|
|
// broadcast it.
|
|
|
req->setFlags(Pkt4::FLAG_BROADCAST_MASK);
|
|
|
+ // This is a direct message, so the hops should be cleared.
|
|
|
+ req->setHops(0);
|
|
|
+ // Set local unicast address as if we are renewing a lease.
|
|
|
+ req->setLocalAddr(IOAddress("192.0.3.1"));
|
|
|
+ // Request is received on the DHCPv4 server port.
|
|
|
+ req->setLocalPort(DHCP4_SERVER_PORT);
|
|
|
+ // Set the interface. The response should be sent over the same interface.
|
|
|
+ req->setIface("eth0");
|
|
|
+ req->setIndex(1);
|
|
|
|
|
|
// Create a response.
|
|
|
boost::shared_ptr<Pkt4> resp(new Pkt4(DHCPOFFER, 1234));
|
|
@@ -189,11 +163,25 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRenewRebind) {
|
|
|
resp->setYiaddr(IOAddress("192.0.2.13"));
|
|
|
// Clear the remote address.
|
|
|
resp->setRemoteAddr(IOAddress("0.0.0.0"));
|
|
|
+ // Copy hops value from the query.
|
|
|
+ resp->setHops(req->getHops());
|
|
|
|
|
|
- ASSERT_NO_THROW(srv->adjustRemoteAddr(req, resp));
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp));
|
|
|
|
|
|
// Check that server responds to ciaddr
|
|
|
EXPECT_EQ("192.0.2.15", resp->getRemoteAddr().toText());
|
|
|
+ // The query was non-relayed, so the response should be sent to a DHCPv4
|
|
|
+ // client port 68.
|
|
|
+ EXPECT_EQ(DHCP4_CLIENT_PORT, resp->getRemotePort());
|
|
|
+ // The response should be sent from the unicast address on which the
|
|
|
+ // query has been received.
|
|
|
+ EXPECT_EQ("192.0.3.1", resp->getLocalAddr().toText());
|
|
|
+ // The response should be sent from the DHCPv4 server port.
|
|
|
+ EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
|
|
|
+ // The interface data should match the data in the query.
|
|
|
+ EXPECT_EQ("eth0", resp->getIface());
|
|
|
+ EXPECT_EQ(1, resp->getIndex());
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// This test verifies that the destination address of the response message
|
|
@@ -203,9 +191,7 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressRenewRebind) {
|
|
|
// of the response should be set to yiaddr if server supports direct responses
|
|
|
// to the client which doesn't have an address yet or broadcast if the server
|
|
|
// doesn't support direct responses.
|
|
|
-TEST_F(Dhcpv4SrvTest, adjustRemoteAddressSelect) {
|
|
|
- boost::scoped_ptr<NakedDhcpv4Srv> srv(new NakedDhcpv4Srv(0));
|
|
|
-
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, adjustIfaceDataSelect) {
|
|
|
// Create instance of the incoming packet.
|
|
|
boost::shared_ptr<Pkt4> req(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
|
|
@@ -217,13 +203,31 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressSelect) {
|
|
|
// Let's clear the broadcast flag.
|
|
|
req->setFlags(0);
|
|
|
|
|
|
+ // This is a non-relayed message, so let's clear hops count.
|
|
|
+ req->setHops(0);
|
|
|
+ // The query is sent to the broadcast address in the Select state.
|
|
|
+ req->setLocalAddr(IOAddress("255.255.255.255"));
|
|
|
+ // The query has been received on the DHCPv4 server port 67.
|
|
|
+ req->setLocalPort(DHCP4_SERVER_PORT);
|
|
|
+ // Set the interface. The response should be sent via the same interface.
|
|
|
+ req->setIface("eth0");
|
|
|
+ req->setIndex(1);
|
|
|
+
|
|
|
// Create a response.
|
|
|
boost::shared_ptr<Pkt4> resp(new Pkt4(DHCPOFFER, 1234));
|
|
|
// Assign some new address for this client.
|
|
|
resp->setYiaddr(IOAddress("192.0.2.13"));
|
|
|
-
|
|
|
// Clear the remote address.
|
|
|
resp->setRemoteAddr(IOAddress("0.0.0.0"));
|
|
|
+ // Copy hops count.
|
|
|
+ resp->setHops(req->getHops());
|
|
|
+
|
|
|
+ // We want to test the case, when the server (packet filter) doesn't support
|
|
|
+ // ddirect responses to the client which doesn't have an address yet. In
|
|
|
+ // case, the server should send its response to the broadcast address.
|
|
|
+ // We can control whether the current packet filter returns that its support
|
|
|
+ // direct responses or not.
|
|
|
+ current_pkt_filter_->direct_resp_supported_ = false;
|
|
|
|
|
|
// When running unit tests, the IfaceMgr is using the default Packet
|
|
|
// Filtering class, PktFilterInet. This class does not support direct
|
|
@@ -231,24 +235,36 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressSelect) {
|
|
|
// are zero and client has just got new lease, the assigned address is
|
|
|
// carried in yiaddr. In order to send this address to the client,
|
|
|
// server must broadcast its response.
|
|
|
- ASSERT_NO_THROW(srv->adjustRemoteAddr(req, resp));
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp));
|
|
|
|
|
|
// Check that the response is sent to broadcast address as the
|
|
|
// server doesn't have capability to respond directly.
|
|
|
EXPECT_EQ("255.255.255.255", resp->getRemoteAddr().toText());
|
|
|
|
|
|
+ // Although the query has been sent to the broadcast address, the
|
|
|
+ // server should select a unicast address on the particular interface
|
|
|
+ // as a source address for the response.
|
|
|
+ EXPECT_EQ("192.0.3.1", resp->getLocalAddr().toText());
|
|
|
+
|
|
|
+ // The response should be sent from the DHCPv4 server port.
|
|
|
+ EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
|
|
|
+
|
|
|
+ // The response should be sent via the same interface through which
|
|
|
+ // query has been received.
|
|
|
+ EXPECT_EQ("eth0", resp->getIface());
|
|
|
+ EXPECT_EQ(1, resp->getIndex());
|
|
|
+
|
|
|
// We also want to test the case when the server has capability to
|
|
|
// respond directly to the client which is not configured. Server
|
|
|
// makes decision whether it responds directly or broadcast its
|
|
|
- // response based on the capability reported by IfaceMgr. In order
|
|
|
- // to set this capability we have to provide a dummy Packet Filter
|
|
|
- // class which would report the support for direct responses.
|
|
|
- // This class is called PktFilterTest.
|
|
|
- IfaceMgr::instance().setPacketFilter(PktFilterPtr(new PktFilterTest()));
|
|
|
+ // response based on the capability reported by IfaceMgr. We can
|
|
|
+ // control whether the current packet filter returns that it supports
|
|
|
+ // direct responses or not.
|
|
|
+ current_pkt_filter_->direct_resp_supported_ = true;
|
|
|
|
|
|
// Now we expect that the server will send its response to the
|
|
|
// address assigned for the client.
|
|
|
- ASSERT_NO_THROW(srv->adjustRemoteAddr(req, resp));
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp));
|
|
|
|
|
|
EXPECT_EQ("192.0.2.13", resp->getRemoteAddr().toText());
|
|
|
}
|
|
@@ -258,9 +274,7 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressSelect) {
|
|
|
// query. Client sets this flag to indicate that it can't receive direct
|
|
|
// responses from the server when it doesn't have its interface configured.
|
|
|
// Server must respect broadcast flag.
|
|
|
-TEST_F(Dhcpv4SrvTest, adjustRemoteAddressBroadcast) {
|
|
|
- boost::scoped_ptr<NakedDhcpv4Srv> srv(new NakedDhcpv4Srv(0));
|
|
|
-
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, adjustIfaceDataBroadcast) {
|
|
|
// Create instance of the incoming packet.
|
|
|
boost::shared_ptr<Pkt4> req(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
|
|
@@ -268,6 +282,13 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressBroadcast) {
|
|
|
req->setGiaddr(IOAddress("0.0.0.0"));
|
|
|
// Clear client address as it hasn't got any address configured yet.
|
|
|
req->setCiaddr(IOAddress("0.0.0.0"));
|
|
|
+ // The query is sent to the broadcast address in the Select state.
|
|
|
+ req->setLocalAddr(IOAddress("255.255.255.255"));
|
|
|
+ // The query has been received on the DHCPv4 server port 67.
|
|
|
+ req->setLocalPort(DHCP4_SERVER_PORT);
|
|
|
+ // Set the interface. The response should be sent via the same interface.
|
|
|
+ req->setIface("eth0");
|
|
|
+ req->setIndex(1);
|
|
|
|
|
|
// Let's set the broadcast flag.
|
|
|
req->setFlags(Pkt4::FLAG_BROADCAST_MASK);
|
|
@@ -280,25 +301,130 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressBroadcast) {
|
|
|
// Clear the remote address.
|
|
|
resp->setRemoteAddr(IOAddress("0.0.0.0"));
|
|
|
|
|
|
- // When running unit tests, the IfaceMgr is using the default Packet
|
|
|
- // Filtering class, PktFilterInet. This class does not support direct
|
|
|
- // responses to the clients without address assigned. If giaddr and
|
|
|
- // ciaddr are zero and client has just got the new lease, the assigned
|
|
|
- // address is carried in yiaddr. In order to send this address to the
|
|
|
- // client, server must send the response to the broadcast address when
|
|
|
- // direct response is not supported. This conflicts with the purpose
|
|
|
- // of this test which is supposed to verify that responses are sent
|
|
|
- // to broadcast address only, when broadcast flag is set. Therefore,
|
|
|
- // in order to simulate that direct responses are supported we have
|
|
|
- // to replace the default packet filtering class with a dummy class
|
|
|
- // which reports direct response capability.
|
|
|
- IfaceMgr::instance().setPacketFilter(PktFilterPtr(new PktFilterTest()));
|
|
|
-
|
|
|
- ASSERT_NO_THROW(srv->adjustRemoteAddr(req, resp));
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp));
|
|
|
|
|
|
// Server must repond to broadcast address when client desired that
|
|
|
// by setting the broadcast flag in its request.
|
|
|
EXPECT_EQ("255.255.255.255", resp->getRemoteAddr().toText());
|
|
|
+
|
|
|
+ // Although the query has been sent to the broadcast address, the
|
|
|
+ // server should select a unicast address on the particular interface
|
|
|
+ // as a source address for the response.
|
|
|
+ EXPECT_EQ("192.0.3.1", resp->getLocalAddr().toText());
|
|
|
+
|
|
|
+ // The response should be sent from the DHCPv4 server port.
|
|
|
+ EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort());
|
|
|
+
|
|
|
+ // The response should be sent via the same interface through which
|
|
|
+ // query has been received.
|
|
|
+ EXPECT_EQ("eth0", resp->getIface());
|
|
|
+ EXPECT_EQ(1, resp->getIndex());
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// This test verifies that exception is thrown of the invalid combination
|
|
|
+// of giaddr and hops is specified in a client's message.
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, adjustIfaceDataInvalid) {
|
|
|
+ boost::shared_ptr<Pkt4> req(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
+
|
|
|
+ // The hops and giaddr values are used to determine if the client's
|
|
|
+ // message has been relayed or sent directly. The allowed combinations
|
|
|
+ // are (giaddr = 0 and hops = 0) or (giaddr != 0 and hops != 0). Any
|
|
|
+ // other combination is invalid and the adjustIfaceData should throw
|
|
|
+ // an exception. We will test that exception is indeed thrown.
|
|
|
+ req->setGiaddr(IOAddress("0.0.0.0"));
|
|
|
+ req->setHops(1);
|
|
|
+
|
|
|
+ // Clear client address as it hasn't got any address configured yet.
|
|
|
+ req->setCiaddr(IOAddress("0.0.0.0"));
|
|
|
+ // The query is sent to the broadcast address in the Select state.
|
|
|
+ req->setLocalAddr(IOAddress("255.255.255.255"));
|
|
|
+ // The query has been received on the DHCPv4 server port 67.
|
|
|
+ req->setLocalPort(DHCP4_SERVER_PORT);
|
|
|
+ // Set the interface. The response should be sent via the same interface.
|
|
|
+ req->setIface("eth0");
|
|
|
+ req->setIndex(1);
|
|
|
+
|
|
|
+ // Create a response.
|
|
|
+ boost::shared_ptr<Pkt4> resp(new Pkt4(DHCPOFFER, 1234));
|
|
|
+ // Assign some new address for this client.
|
|
|
+ resp->setYiaddr(IOAddress("192.0.2.13"));
|
|
|
+
|
|
|
+ // Clear the remote address.
|
|
|
+ resp->setRemoteAddr(IOAddress("0.0.0.0"));
|
|
|
+
|
|
|
+ EXPECT_THROW(NakedDhcpv4Srv::adjustIfaceData(req, resp), isc::BadValue);
|
|
|
+}
|
|
|
+
|
|
|
+// This test verifies that the server identifier option is appended to
|
|
|
+// a specified DHCPv4 message and the server identifier is correct.
|
|
|
+TEST_F(Dhcpv4SrvTest, appendServerID) {
|
|
|
+ Pkt4Ptr response(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
+ // Set a local address. It is required by the function under test
|
|
|
+ // to create the Server Identifier option.
|
|
|
+ response->setLocalAddr(IOAddress("192.0.3.1"));
|
|
|
+
|
|
|
+ // Append the Server Identifier.
|
|
|
+ ASSERT_NO_THROW(NakedDhcpv4Srv::appendServerID(response));
|
|
|
+
|
|
|
+ // Make sure that the option has been added.
|
|
|
+ OptionPtr opt = response->getOption(DHO_DHCP_SERVER_IDENTIFIER);
|
|
|
+ ASSERT_TRUE(opt);
|
|
|
+ Option4AddrLstPtr opt_server_id =
|
|
|
+ boost::dynamic_pointer_cast<Option4AddrLst>(opt);
|
|
|
+ ASSERT_TRUE(opt_server_id);
|
|
|
+
|
|
|
+ // The option is represented as a list of IPv4 addresses but with
|
|
|
+ // only one address added.
|
|
|
+ Option4AddrLst::AddressContainer addrs = opt_server_id->getAddresses();
|
|
|
+ ASSERT_EQ(1, addrs.size());
|
|
|
+ // This address should match the local address of the packet.
|
|
|
+ EXPECT_EQ("192.0.3.1", addrs[0].toText());
|
|
|
+}
|
|
|
+
|
|
|
+// Sanity check. Verifies that both Dhcpv4Srv and its derived
|
|
|
+// class NakedDhcpv4Srv can be instantiated and destroyed.
|
|
|
+TEST_F(Dhcpv4SrvTest, basic) {
|
|
|
+
|
|
|
+ // Check that the base class can be instantiated
|
|
|
+ boost::scoped_ptr<Dhcpv4Srv> srv;
|
|
|
+ ASSERT_NO_THROW(srv.reset(new Dhcpv4Srv(DHCP4_SERVER_PORT + 10000, "type=memfile",
|
|
|
+ false, false)));
|
|
|
+ srv.reset();
|
|
|
+ // We have to close open sockets because further in this test we will
|
|
|
+ // call the Dhcpv4Srv constructor again. This constructor will try to
|
|
|
+ // set the appropriate packet filter class for IfaceMgr. This requires
|
|
|
+ // that all sockets are closed.
|
|
|
+ IfaceMgr::instance().closeSockets();
|
|
|
+
|
|
|
+ // Check that the derived class can be instantiated
|
|
|
+ boost::scoped_ptr<NakedDhcpv4Srv> naked_srv;
|
|
|
+ ASSERT_NO_THROW(
|
|
|
+ naked_srv.reset(new NakedDhcpv4Srv(DHCP4_SERVER_PORT + 10000)));
|
|
|
+ // Close sockets again for the next test.
|
|
|
+ IfaceMgr::instance().closeSockets();
|
|
|
+
|
|
|
+ ASSERT_NO_THROW(naked_srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
+}
|
|
|
+
|
|
|
+// This test verifies that exception is not thrown when an error occurs during
|
|
|
+// opening sockets. This test forces an error by adding a fictious interface
|
|
|
+// to the IfaceMgr. An attempt to open socket on this interface must always
|
|
|
+// fail. The DHCPv4 installs the error handler function to prevent exceptions
|
|
|
+// being thrown from the openSockets4 function.
|
|
|
+// @todo The server tests for socket should be extended but currently the
|
|
|
+// ability to unit test the sockets code is somewhat limited.
|
|
|
+TEST_F(Dhcpv4SrvTest, openActiveSockets) {
|
|
|
+ ASSERT_NO_THROW(CfgMgr::instance().activateAllIfaces());
|
|
|
+
|
|
|
+ Iface iface("bogusiface", 255);
|
|
|
+ iface.flag_loopback_ = false;
|
|
|
+ iface.flag_up_ = true;
|
|
|
+ iface.flag_running_ = true;
|
|
|
+ iface.inactive4_ = false;
|
|
|
+ iface.addAddress(IOAddress("192.0.0.0"));
|
|
|
+ IfaceMgr::instance().addInterface(iface);
|
|
|
+ ASSERT_NO_THROW(Dhcpv4Srv::openActiveSockets(DHCP4_SERVER_PORT, false));
|
|
|
}
|
|
|
|
|
|
// Verifies that DISCOVER message can be processed correctly,
|
|
@@ -309,7 +435,7 @@ TEST_F(Dhcpv4SrvTest, adjustRemoteAddressBroadcast) {
|
|
|
// are other tests that verify correctness of the allocation
|
|
|
// engine. See DiscoverBasic, DiscoverHint, DiscoverNoClientId
|
|
|
// and DiscoverInvalidHint.
|
|
|
-TEST_F(Dhcpv4SrvTest, processDiscover) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, processDiscover) {
|
|
|
testDiscoverRequest(DHCPDISCOVER);
|
|
|
}
|
|
|
|
|
@@ -321,11 +447,11 @@ TEST_F(Dhcpv4SrvTest, processDiscover) {
|
|
|
// are other tests that verify correctness of the allocation
|
|
|
// engine. See DiscoverBasic, DiscoverHint, DiscoverNoClientId
|
|
|
// and DiscoverInvalidHint.
|
|
|
-TEST_F(Dhcpv4SrvTest, processRequest) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, processRequest) {
|
|
|
testDiscoverRequest(DHCPREQUEST);
|
|
|
}
|
|
|
|
|
|
-TEST_F(Dhcpv4SrvTest, processRelease) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, processRelease) {
|
|
|
NakedDhcpv4Srv srv;
|
|
|
Pkt4Ptr pkt(new Pkt4(DHCPRELEASE, 1234));
|
|
|
|
|
@@ -333,7 +459,7 @@ TEST_F(Dhcpv4SrvTest, processRelease) {
|
|
|
EXPECT_NO_THROW(srv.processRelease(pkt));
|
|
|
}
|
|
|
|
|
|
-TEST_F(Dhcpv4SrvTest, processDecline) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, processDecline) {
|
|
|
NakedDhcpv4Srv srv;
|
|
|
Pkt4Ptr pkt(new Pkt4(DHCPDECLINE, 1234));
|
|
|
|
|
@@ -341,7 +467,7 @@ TEST_F(Dhcpv4SrvTest, processDecline) {
|
|
|
EXPECT_NO_THROW(srv.processDecline(pkt));
|
|
|
}
|
|
|
|
|
|
-TEST_F(Dhcpv4SrvTest, processInform) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, processInform) {
|
|
|
NakedDhcpv4Srv srv;
|
|
|
Pkt4Ptr pkt(new Pkt4(DHCPINFORM, 1234));
|
|
|
|
|
@@ -398,7 +524,7 @@ TEST_F(Dhcpv4SrvTest, serverReceivedPacketName) {
|
|
|
// - copy of client-id
|
|
|
// - server-id
|
|
|
// - offered address
|
|
|
-TEST_F(Dhcpv4SrvTest, DiscoverBasic) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, DiscoverBasic) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
|
|
@@ -406,6 +532,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverBasic) {
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an offer
|
|
|
Pkt4Ptr offer = srv->processDiscover(dis);
|
|
@@ -435,7 +562,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverBasic) {
|
|
|
// - copy of client-id
|
|
|
// - server-id
|
|
|
// - offered address
|
|
|
-TEST_F(Dhcpv4SrvTest, DiscoverHint) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, DiscoverHint) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
IOAddress hint("192.0.2.107");
|
|
@@ -445,6 +572,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverHint) {
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
dis->setYiaddr(hint);
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an offer
|
|
|
Pkt4Ptr offer = srv->processDiscover(dis);
|
|
@@ -475,7 +603,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverHint) {
|
|
|
// - copy of client-id
|
|
|
// - server-id
|
|
|
// - offered address
|
|
|
-TEST_F(Dhcpv4SrvTest, DiscoverNoClientId) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, DiscoverNoClientId) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
IOAddress hint("192.0.2.107");
|
|
@@ -484,6 +612,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverNoClientId) {
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
dis->setYiaddr(hint);
|
|
|
dis->setHWAddr(generateHWAddr(6));
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an offer
|
|
|
Pkt4Ptr offer = srv->processDiscover(dis);
|
|
@@ -513,7 +642,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverNoClientId) {
|
|
|
// - copy of client-id
|
|
|
// - server-id
|
|
|
// - offered address (!= hint)
|
|
|
-TEST_F(Dhcpv4SrvTest, DiscoverInvalidHint) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, DiscoverInvalidHint) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
IOAddress hint("10.1.2.3");
|
|
@@ -523,6 +652,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverInvalidHint) {
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
dis->setYiaddr(hint);
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an offer
|
|
|
Pkt4Ptr offer = srv->processDiscover(dis);
|
|
@@ -551,7 +681,7 @@ TEST_F(Dhcpv4SrvTest, DiscoverInvalidHint) {
|
|
|
// and this is a correct behavior. It is REQUEST that will fail for the third
|
|
|
// client. OFFER is basically saying "if you send me a request, you will
|
|
|
// probably get an address like this" (there are no guarantees).
|
|
|
-TEST_F(Dhcpv4SrvTest, ManyDiscovers) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, ManyDiscovers) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
|
|
@@ -563,6 +693,11 @@ TEST_F(Dhcpv4SrvTest, ManyDiscovers) {
|
|
|
dis2->setRemoteAddr(IOAddress("192.0.2.2"));
|
|
|
dis3->setRemoteAddr(IOAddress("192.0.2.3"));
|
|
|
|
|
|
+ // Assign interfaces
|
|
|
+ dis1->setIface("eth0");
|
|
|
+ dis2->setIface("eth0");
|
|
|
+ dis3->setIface("eth0");
|
|
|
+
|
|
|
// Different client-id sizes
|
|
|
OptionPtr clientid1 = generateClientId(4); // length 4
|
|
|
OptionPtr clientid2 = generateClientId(5); // length 5
|
|
@@ -611,13 +746,14 @@ TEST_F(Dhcpv4SrvTest, ManyDiscovers) {
|
|
|
// Checks whether echoing back client-id is controllable, i.e.
|
|
|
// whether the server obeys echo-client-id and sends (or not)
|
|
|
// client-id
|
|
|
-TEST_F(Dhcpv4SrvTest, discoverEchoClientId) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, discoverEchoClientId) {
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
|
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an offer
|
|
|
Pkt4Ptr offer = srv.processDiscover(dis);
|
|
@@ -649,7 +785,7 @@ TEST_F(Dhcpv4SrvTest, discoverEchoClientId) {
|
|
|
// - assigned address
|
|
|
//
|
|
|
// Test verifies that the lease is actually in the database.
|
|
|
-TEST_F(Dhcpv4SrvTest, RequestBasic) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, RequestBasic) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
|
|
@@ -659,6 +795,7 @@ TEST_F(Dhcpv4SrvTest, RequestBasic) {
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
req->addOption(clientid);
|
|
|
req->setYiaddr(hint);
|
|
|
+ req->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an advertise
|
|
|
Pkt4Ptr ack = srv->processRequest(req);
|
|
@@ -694,7 +831,7 @@ TEST_F(Dhcpv4SrvTest, RequestBasic) {
|
|
|
// - copy of client-id
|
|
|
// - server-id
|
|
|
// - assigned address (different for each client)
|
|
|
-TEST_F(Dhcpv4SrvTest, ManyRequests) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, ManyRequests) {
|
|
|
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
@@ -712,6 +849,11 @@ TEST_F(Dhcpv4SrvTest, ManyRequests) {
|
|
|
req2->setRemoteAddr(relay);
|
|
|
req3->setRemoteAddr(relay);
|
|
|
|
|
|
+ // Assign interfaces
|
|
|
+ req1->setIface("eth0");
|
|
|
+ req2->setIface("eth0");
|
|
|
+ req3->setIface("eth0");
|
|
|
+
|
|
|
req1->setYiaddr(req_addr1);
|
|
|
req2->setYiaddr(req_addr2);
|
|
|
req3->setYiaddr(req_addr3);
|
|
@@ -777,13 +919,14 @@ TEST_F(Dhcpv4SrvTest, ManyRequests) {
|
|
|
}
|
|
|
|
|
|
// Checks whether echoing back client-id is controllable
|
|
|
-TEST_F(Dhcpv4SrvTest, requestEchoClientId) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, requestEchoClientId) {
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
|
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get ACK
|
|
|
Pkt4Ptr ack = srv.processRequest(dis);
|
|
@@ -810,7 +953,7 @@ TEST_F(Dhcpv4SrvTest, requestEchoClientId) {
|
|
|
// - returned REPLY message has server-id
|
|
|
// - returned REPLY message has IA that includes IAADDR
|
|
|
// - lease is actually renewed in LeaseMgr
|
|
|
-TEST_F(Dhcpv4SrvTest, RenewBasic) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, RenewBasic) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
|
|
@@ -850,6 +993,7 @@ TEST_F(Dhcpv4SrvTest, RenewBasic) {
|
|
|
req->setRemoteAddr(IOAddress(addr));
|
|
|
req->setYiaddr(addr);
|
|
|
req->setCiaddr(addr); // client's address
|
|
|
+ req->setIface("eth0");
|
|
|
|
|
|
req->addOption(clientid);
|
|
|
req->addOption(srv->getServerID());
|
|
@@ -898,30 +1042,32 @@ TEST_F(Dhcpv4SrvTest, sanityCheck) {
|
|
|
pkt->setHWAddr(generateHWAddr(6));
|
|
|
|
|
|
// Server-id is optional for information-request, so
|
|
|
- EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::OPTIONAL));
|
|
|
+ EXPECT_NO_THROW(NakedDhcpv4Srv::sanityCheck(pkt, Dhcpv4Srv::OPTIONAL));
|
|
|
|
|
|
// Empty packet, no server-id
|
|
|
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::MANDATORY), RFCViolation);
|
|
|
+ EXPECT_THROW(NakedDhcpv4Srv::sanityCheck(pkt, Dhcpv4Srv::MANDATORY),
|
|
|
+ RFCViolation);
|
|
|
|
|
|
pkt->addOption(srv->getServerID());
|
|
|
|
|
|
// Server-id is mandatory and present = no exception
|
|
|
- EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::MANDATORY));
|
|
|
+ EXPECT_NO_THROW(NakedDhcpv4Srv::sanityCheck(pkt, Dhcpv4Srv::MANDATORY));
|
|
|
|
|
|
// Server-id is forbidden, but present => exception
|
|
|
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::FORBIDDEN),
|
|
|
+ EXPECT_THROW(NakedDhcpv4Srv::sanityCheck(pkt, Dhcpv4Srv::FORBIDDEN),
|
|
|
RFCViolation);
|
|
|
|
|
|
// There's no client-id and no HWADDR. Server needs something to
|
|
|
// identify the client
|
|
|
pkt->setHWAddr(generateHWAddr(0));
|
|
|
- EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::MANDATORY), RFCViolation);
|
|
|
+ EXPECT_THROW(NakedDhcpv4Srv::sanityCheck(pkt, Dhcpv4Srv::MANDATORY),
|
|
|
+ RFCViolation);
|
|
|
}
|
|
|
|
|
|
// This test verifies that incoming (positive) RELEASE can be handled properly.
|
|
|
// As there is no REPLY in DHCPv4, the only thing to verify here is that
|
|
|
// the lease is indeed removed from the database.
|
|
|
-TEST_F(Dhcpv4SrvTest, ReleaseBasic) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, ReleaseBasic) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
|
|
@@ -958,6 +1104,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseBasic) {
|
|
|
rel->addOption(clientid);
|
|
|
rel->addOption(srv->getServerID());
|
|
|
rel->setHWAddr(hw);
|
|
|
+ rel->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and hope for a REPLY
|
|
|
// Note: this is no response to RELEASE in DHCPv4
|
|
@@ -992,7 +1139,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseBasic) {
|
|
|
// 1. there is no such lease at all
|
|
|
// 2. there is such a lease, but it is assigned to a different IAID
|
|
|
// 3. there is such a lease, but it belongs to a different client
|
|
|
-TEST_F(Dhcpv4SrvTest, ReleaseReject) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, ReleaseReject) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
|
|
@@ -1021,6 +1168,7 @@ TEST_F(Dhcpv4SrvTest, ReleaseReject) {
|
|
|
rel->addOption(clientid);
|
|
|
rel->addOption(srv->getServerID());
|
|
|
rel->setHWAddr(bogus_hw);
|
|
|
+ rel->setIface("eth0");
|
|
|
|
|
|
// Case 1: No lease known to server
|
|
|
SCOPED_TRACE("CASE 1: Lease is not known to the server");
|
|
@@ -1079,38 +1227,8 @@ TEST_F(Dhcpv4SrvTest, ReleaseReject) {
|
|
|
EXPECT_FALSE(l);
|
|
|
}
|
|
|
|
|
|
-// This test verifies if the server-id disk operations (read, write) are
|
|
|
-// working properly.
|
|
|
-TEST_F(Dhcpv4SrvTest, ServerID) {
|
|
|
- NakedDhcpv4Srv srv(0);
|
|
|
-
|
|
|
- string srvid_text = "192.0.2.100";
|
|
|
- IOAddress srvid(srvid_text);
|
|
|
-
|
|
|
- fstream file1(SRVID_FILE, ios::out | ios::trunc);
|
|
|
- file1 << srvid_text;
|
|
|
- file1.close();
|
|
|
-
|
|
|
- // Test reading from a file
|
|
|
- EXPECT_TRUE(srv.loadServerID(SRVID_FILE));
|
|
|
- ASSERT_TRUE(srv.getServerID());
|
|
|
- EXPECT_EQ(srvid_text, srv.srvidToString(srv.getServerID()));
|
|
|
-
|
|
|
- // Now test writing to a file
|
|
|
- EXPECT_EQ(0, unlink(SRVID_FILE));
|
|
|
- EXPECT_NO_THROW(srv.writeServerID(SRVID_FILE));
|
|
|
-
|
|
|
- fstream file2(SRVID_FILE, ios::in);
|
|
|
- ASSERT_TRUE(file2.good());
|
|
|
- string text;
|
|
|
- file2 >> text;
|
|
|
- file2.close();
|
|
|
-
|
|
|
- EXPECT_EQ(srvid_text, text);
|
|
|
-}
|
|
|
-
|
|
|
// Checks if received relay agent info option is echoed back to the client
|
|
|
-TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, relayAgentInfoEcho) {
|
|
|
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
@@ -1153,7 +1271,7 @@ TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) {
|
|
|
|
|
|
// Checks if vendor options are parsed correctly and requested vendor options
|
|
|
// are echoed back.
|
|
|
-TEST_F(Dhcpv4SrvTest, vendorOptionsDocsis) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, vendorOptionsDocsis) {
|
|
|
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
@@ -1173,7 +1291,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsDocsis) {
|
|
|
" \"rebind-timer\": 2000, "
|
|
|
" \"renew-timer\": 1000, "
|
|
|
" \"valid-lifetime\": 4000,"
|
|
|
- " \"interface\": \"" + valid_iface_ + "\" "
|
|
|
+ " \"interface\": \"eth0\" "
|
|
|
" } ],"
|
|
|
"\"valid-lifetime\": 4000 }";
|
|
|
|
|
@@ -1347,7 +1465,7 @@ TEST_F(Dhcpv4SrvTest, unpackOptions) {
|
|
|
|
|
|
// Checks whether the server uses default (0.0.0.0) siaddr value, unless
|
|
|
// explicitly specified
|
|
|
-TEST_F(Dhcpv4SrvTest, siaddrDefault) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, siaddrDefault) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
IOAddress hint("192.0.2.107");
|
|
@@ -1357,6 +1475,7 @@ TEST_F(Dhcpv4SrvTest, siaddrDefault) {
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
dis->setYiaddr(hint);
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an offer
|
|
|
Pkt4Ptr offer = srv->processDiscover(dis);
|
|
@@ -1370,13 +1489,14 @@ TEST_F(Dhcpv4SrvTest, siaddrDefault) {
|
|
|
}
|
|
|
|
|
|
// Checks whether the server uses specified siaddr value
|
|
|
-TEST_F(Dhcpv4SrvTest, siaddr) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, siaddr) {
|
|
|
boost::scoped_ptr<NakedDhcpv4Srv> srv;
|
|
|
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
|
|
|
subnet_->setSiaddr(IOAddress("192.0.2.123"));
|
|
|
|
|
|
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
+ dis->setIface("eth0");
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
|
|
@@ -1395,7 +1515,7 @@ TEST_F(Dhcpv4SrvTest, siaddr) {
|
|
|
// specific value and returned in server messages. There's also similar test for
|
|
|
// checking parser only configuration, see Dhcp4ParserTest.nextServerOverride in
|
|
|
// config_parser_unittest.cc.
|
|
|
-TEST_F(Dhcpv4SrvTest, nextServerOverride) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, nextServerOverride) {
|
|
|
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
@@ -1422,6 +1542,7 @@ TEST_F(Dhcpv4SrvTest, nextServerOverride) {
|
|
|
|
|
|
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
+ dis->setIface("eth0");
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
|
|
@@ -1437,7 +1558,7 @@ TEST_F(Dhcpv4SrvTest, nextServerOverride) {
|
|
|
// when there is no specific value defined in subnet and returned to the client
|
|
|
// properly. There's also similar test for checking parser only configuration,
|
|
|
// see Dhcp4ParserTest.nextServerGlobal in config_parser_unittest.cc.
|
|
|
-TEST_F(Dhcpv4SrvTest, nextServerGlobal) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, nextServerGlobal) {
|
|
|
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
@@ -1463,6 +1584,7 @@ TEST_F(Dhcpv4SrvTest, nextServerGlobal) {
|
|
|
|
|
|
Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
dis->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
+ dis->setIface("eth0");
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
|
|
@@ -1499,7 +1621,7 @@ const uint8_t dummySname[] = "Lorem ipsum dolor sit amet, consectetur "
|
|
|
/// can't modify non-static members (for obvious reasons), so many
|
|
|
/// fields are declared static. It is still better to keep them as
|
|
|
/// one class rather than unrelated collection of global objects.
|
|
|
-class HooksDhcpv4SrvTest : public Dhcpv4SrvTest {
|
|
|
+class HooksDhcpv4SrvTest : public Dhcpv4SrvFakeIfaceTest {
|
|
|
|
|
|
public:
|
|
|
|
|
@@ -1986,7 +2108,7 @@ TEST_F(HooksDhcpv4SrvTest, Buffer4ReceiveSimple) {
|
|
|
|
|
|
// Checks if callouts installed on buffer4_receive is able to change
|
|
|
// the values and the parameters are indeed used by the server.
|
|
|
-TEST_F(HooksDhcpv4SrvTest, buffer4RreceiveValueChange) {
|
|
|
+TEST_F(HooksDhcpv4SrvTest, buffer4ReceiveValueChange) {
|
|
|
|
|
|
// Install callback that modifies MAC addr of incoming packet
|
|
|
EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
|
|
@@ -2407,7 +2529,7 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectSimple) {
|
|
|
"\"subnet4\": [ { "
|
|
|
" \"pool\": [ \"192.0.2.0/25\" ],"
|
|
|
" \"subnet\": \"192.0.2.0/24\", "
|
|
|
- " \"interface\": \"" + valid_iface_ + "\" "
|
|
|
+ " \"interface\": \"eth0\" "
|
|
|
" }, {"
|
|
|
" \"pool\": [ \"192.0.3.0/25\" ],"
|
|
|
" \"subnet\": \"192.0.3.0/24\" "
|
|
@@ -2426,7 +2548,7 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectSimple) {
|
|
|
// Prepare discover packet. Server should select first subnet for it
|
|
|
Pkt4Ptr sol = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
sol->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
- sol->setIface(valid_iface_);
|
|
|
+ sol->setIface("eth0");
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
sol->addOption(clientid);
|
|
|
|
|
@@ -2473,7 +2595,7 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectChange) {
|
|
|
"\"subnet4\": [ { "
|
|
|
" \"pool\": [ \"192.0.2.0/25\" ],"
|
|
|
" \"subnet\": \"192.0.2.0/24\", "
|
|
|
- " \"interface\": \"" + valid_iface_ + "\" "
|
|
|
+ " \"interface\": \"eth0\" "
|
|
|
" }, {"
|
|
|
" \"pool\": [ \"192.0.3.0/25\" ],"
|
|
|
" \"subnet\": \"192.0.3.0/24\" "
|
|
@@ -2492,7 +2614,7 @@ TEST_F(HooksDhcpv4SrvTest, subnet4SelectChange) {
|
|
|
// Prepare discover packet. Server should select first subnet for it
|
|
|
Pkt4Ptr sol = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
sol->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
- sol->setIface(valid_iface_);
|
|
|
+ sol->setIface("eth0");
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
sol->addOption(clientid);
|
|
|
|
|
@@ -2554,6 +2676,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSimple) {
|
|
|
req->setRemoteAddr(IOAddress(addr));
|
|
|
req->setYiaddr(addr);
|
|
|
req->setCiaddr(addr); // client's address
|
|
|
+ req->setIface("eth0");
|
|
|
|
|
|
req->addOption(clientid);
|
|
|
req->addOption(srv_->getServerID());
|
|
@@ -2645,6 +2768,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4RenewSkip) {
|
|
|
req->setRemoteAddr(IOAddress(addr));
|
|
|
req->setYiaddr(addr);
|
|
|
req->setCiaddr(addr); // client's address
|
|
|
+ req->setIface("eth0");
|
|
|
|
|
|
req->addOption(clientid);
|
|
|
req->addOption(srv_->getServerID());
|
|
@@ -2816,7 +2940,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
|
|
|
}
|
|
|
|
|
|
// Checks if server is able to handle a relayed traffic from DOCSIS3.0 modems
|
|
|
-TEST_F(Dhcpv4SrvTest, docsisVendorOptionsParse) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, docsisVendorOptionsParse) {
|
|
|
|
|
|
// Let's get a traffic capture from DOCSIS3.0 modem
|
|
|
Pkt4Ptr dis = captureRelayedDiscover();
|
|
@@ -2840,7 +2964,7 @@ TEST_F(Dhcpv4SrvTest, docsisVendorOptionsParse) {
|
|
|
}
|
|
|
|
|
|
// Checks if server is able to parse incoming docsis option and extract suboption 1 (docsis ORO)
|
|
|
-TEST_F(Dhcpv4SrvTest, docsisVendorORO) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, docsisVendorORO) {
|
|
|
|
|
|
// Let's get a traffic capture from DOCSIS3.0 modem
|
|
|
Pkt4Ptr dis = captureRelayedDiscover();
|
|
@@ -2862,7 +2986,7 @@ TEST_F(Dhcpv4SrvTest, docsisVendorORO) {
|
|
|
|
|
|
// This test checks if Option Request Option (ORO) in docsis (vendor-id=4491)
|
|
|
// vendor options is parsed correctly and the requested options are actually assigned.
|
|
|
-TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, vendorOptionsORO) {
|
|
|
|
|
|
NakedDhcpv4Srv srv(0);
|
|
|
|
|
@@ -2883,7 +3007,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
|
|
|
" \"rebind-timer\": 2000, "
|
|
|
" \"renew-timer\": 1000, "
|
|
|
" \"valid-lifetime\": 4000,"
|
|
|
- " \"interface\": \"" + valid_iface_ + "\" "
|
|
|
+ " \"interface\": \"eth0\" "
|
|
|
" } ],"
|
|
|
"\"valid-lifetime\": 4000 }";
|
|
|
|
|
@@ -2895,10 +3019,14 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
|
|
|
ASSERT_EQ(0, rcode_);
|
|
|
|
|
|
boost::shared_ptr<Pkt4> dis(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
- // Set the giaddr to non-zero address as if it was relayed.
|
|
|
+ // Set the giaddr and hops to non-zero address as if it was relayed.
|
|
|
dis->setGiaddr(IOAddress("192.0.2.1"));
|
|
|
+ dis->setHops(1);
|
|
|
+
|
|
|
OptionPtr clientid = generateClientId();
|
|
|
dis->addOption(clientid);
|
|
|
+ // Set interface. It is required by the server to generate server id.
|
|
|
+ dis->setIface("eth0");
|
|
|
|
|
|
// Pass it to the server and get an advertise
|
|
|
Pkt4Ptr offer = srv.processDiscover(dis);
|
|
@@ -2946,7 +3074,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
|
|
|
|
|
|
// Test checks whether it is possible to use option definitions defined in
|
|
|
// src/lib/dhcp/docsis3_option_defs.h.
|
|
|
-TEST_F(Dhcpv4SrvTest, vendorOptionsDocsisDefinitions) {
|
|
|
+TEST_F(Dhcpv4SrvFakeIfaceTest, vendorOptionsDocsisDefinitions) {
|
|
|
ConstElementPtr x;
|
|
|
string config_prefix = "{ \"interfaces\": [ \"all\" ],"
|
|
|
"\"rebind-timer\": 2000, "
|