|
@@ -17,6 +17,7 @@
|
|
|
#include <config/ccsession.h>
|
|
|
#include <dhcp/libdhcp++.h>
|
|
|
#include <dhcp/option6_ia.h>
|
|
|
+#include <dhcp/iface_mgr.h>
|
|
|
#include <dhcp6/config_parser.h>
|
|
|
#include <dhcp6/dhcp6_srv.h>
|
|
|
#include <dhcpsrv/cfgmgr.h>
|
|
@@ -46,6 +47,23 @@ public:
|
|
|
// srv_(0) means to not open any sockets. We don't want to
|
|
|
// deal with sockets here, just check if configuration handling
|
|
|
// is sane.
|
|
|
+
|
|
|
+ const IfaceMgr::IfaceCollection& ifaces = IfaceMgr::instance().getIfaces();
|
|
|
+
|
|
|
+ // There must be some interface detected
|
|
|
+ if (ifaces.empty()) {
|
|
|
+ // We can't use ASSERT in constructor
|
|
|
+ ADD_FAILURE() << "No interfaces detected.";
|
|
|
+ }
|
|
|
+
|
|
|
+ valid_iface_ = ifaces.begin()->getName();
|
|
|
+ bogus_iface_ = "nonexisting0";
|
|
|
+
|
|
|
+ if (IfaceMgr::instance().getIface(bogus_iface_)) {
|
|
|
+ ADD_FAILURE() << "The '" << bogus_iface_ << "' exists on this system"
|
|
|
+ << " while the test assumes that it doesn't, to execute"
|
|
|
+ << " some negative scenarios. Can't continue this test.";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
~Dhcp6ParserTest() {
|
|
@@ -261,6 +279,9 @@ public:
|
|
|
|
|
|
int rcode_;
|
|
|
ConstElementPtr comment_;
|
|
|
+
|
|
|
+ string valid_iface_;
|
|
|
+ string bogus_iface_;
|
|
|
};
|
|
|
|
|
|
// Goal of this test is a verification if a very simple config update
|
|
@@ -294,9 +315,8 @@ TEST_F(Dhcp6ParserTest, bogusCommand) {
|
|
|
EXPECT_EQ(1, rcode_);
|
|
|
}
|
|
|
|
|
|
-/// The goal of this test is to verify if wrongly defined subnet will
|
|
|
-/// be rejected. Properly defined subnet must include at least one
|
|
|
-/// pool definition.
|
|
|
+/// The goal of this test is to verify if configuration without any
|
|
|
+/// subnets defined can be accepted.
|
|
|
TEST_F(Dhcp6ParserTest, emptySubnet) {
|
|
|
|
|
|
ConstElementPtr status;
|
|
@@ -387,6 +407,99 @@ TEST_F(Dhcp6ParserTest, subnetLocal) {
|
|
|
EXPECT_EQ(4, subnet->getValid());
|
|
|
}
|
|
|
|
|
|
+// This test checks if it is possible to define a subnet with an
|
|
|
+// interface defined.
|
|
|
+TEST_F(Dhcp6ParserTest, subnetInterface) {
|
|
|
+
|
|
|
+ ConstElementPtr status;
|
|
|
+
|
|
|
+ // There should be at least one interface
|
|
|
+
|
|
|
+ string config = "{ \"interface\": [ \"all\" ],"
|
|
|
+ "\"preferred-lifetime\": 3000,"
|
|
|
+ "\"rebind-timer\": 2000, "
|
|
|
+ "\"renew-timer\": 1000, "
|
|
|
+ "\"subnet6\": [ { "
|
|
|
+ " \"pool\": [ \"2001:db8:1::1 - 2001:db8:1::ffff\" ],"
|
|
|
+ " \"interface\": \"" + valid_iface_ + "\","
|
|
|
+ " \"subnet\": \"2001:db8:1::/64\" } ],"
|
|
|
+ "\"valid-lifetime\": 4000 }";
|
|
|
+ cout << config << endl;
|
|
|
+
|
|
|
+ ElementPtr json = Element::fromJSON(config);
|
|
|
+
|
|
|
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
|
|
+
|
|
|
+ // returned value should be 0 (configuration success)
|
|
|
+ ASSERT_TRUE(status);
|
|
|
+ comment_ = parseAnswer(rcode_, status);
|
|
|
+ EXPECT_EQ(0, rcode_);
|
|
|
+
|
|
|
+ Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"));
|
|
|
+ ASSERT_TRUE(subnet);
|
|
|
+ EXPECT_EQ(valid_iface_, subnet->getIface());
|
|
|
+}
|
|
|
+
|
|
|
+// This test checks if invalid interface name will be rejected in
|
|
|
+// Subnet6 definition.
|
|
|
+TEST_F(Dhcp6ParserTest, subnetInterfaceBogus) {
|
|
|
+
|
|
|
+ ConstElementPtr status;
|
|
|
+
|
|
|
+ // There should be at least one interface
|
|
|
+
|
|
|
+ string config = "{ \"interface\": [ \"all\" ],"
|
|
|
+ "\"preferred-lifetime\": 3000,"
|
|
|
+ "\"rebind-timer\": 2000, "
|
|
|
+ "\"renew-timer\": 1000, "
|
|
|
+ "\"subnet6\": [ { "
|
|
|
+ " \"pool\": [ \"2001:db8:1::1 - 2001:db8:1::ffff\" ],"
|
|
|
+ " \"interface\": \"" + bogus_iface_ + "\","
|
|
|
+ " \"subnet\": \"2001:db8:1::/64\" } ],"
|
|
|
+ "\"valid-lifetime\": 4000 }";
|
|
|
+ cout << config << endl;
|
|
|
+
|
|
|
+ ElementPtr json = Element::fromJSON(config);
|
|
|
+
|
|
|
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
|
|
+
|
|
|
+ // returned value should be 1 (configuration error)
|
|
|
+ ASSERT_TRUE(status);
|
|
|
+ comment_ = parseAnswer(rcode_, status);
|
|
|
+ EXPECT_EQ(1, rcode_);
|
|
|
+
|
|
|
+ Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"));
|
|
|
+ EXPECT_FALSE(subnet);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// This test checks if it is not allowed to define global interface
|
|
|
+// parameter.
|
|
|
+TEST_F(Dhcp6ParserTest, interfaceGlobal) {
|
|
|
+
|
|
|
+ ConstElementPtr status;
|
|
|
+
|
|
|
+ string config = "{ \"interface\": [ \"all\" ],"
|
|
|
+ "\"preferred-lifetime\": 3000,"
|
|
|
+ "\"rebind-timer\": 2000, "
|
|
|
+ "\"renew-timer\": 1000, "
|
|
|
+ "\"interface\": \"" + valid_iface_ + "\"," // Not valid. Can be defined in subnet only
|
|
|
+ "\"subnet6\": [ { "
|
|
|
+ " \"pool\": [ \"2001:db8:1::1 - 2001:db8:1::ffff\" ],"
|
|
|
+ " \"subnet\": \"2001:db8:1::/64\" } ],"
|
|
|
+ "\"valid-lifetime\": 4000 }";
|
|
|
+ cout << config << endl;
|
|
|
+
|
|
|
+ ElementPtr json = Element::fromJSON(config);
|
|
|
+
|
|
|
+ EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
|
|
+
|
|
|
+ // returned value should be 1 (parse error)
|
|
|
+ ASSERT_TRUE(status);
|
|
|
+ comment_ = parseAnswer(rcode_, status);
|
|
|
+ EXPECT_EQ(1, rcode_);
|
|
|
+}
|
|
|
+
|
|
|
// Test verifies that a subnet with pool values that do not belong to that
|
|
|
// pool are rejected.
|
|
|
TEST_F(Dhcp6ParserTest, poolOutOfSubnet) {
|
|
@@ -411,7 +524,6 @@ TEST_F(Dhcp6ParserTest, poolOutOfSubnet) {
|
|
|
// as the pool does not belong to that subnet
|
|
|
ASSERT_TRUE(status);
|
|
|
comment_ = parseAnswer(rcode_, status);
|
|
|
-
|
|
|
EXPECT_EQ(1, rcode_);
|
|
|
}
|
|
|
|