The ``interface-list`` Command
------------------------------
-The :isccmd:`interface-list` command retrieves.
+The :isccmd:`interface-list` command retrieves the list of detected interfaces.
+This command does not take any parameters.
.. isccmd:: interface-redetect
.. _command-interface-redetect:
The ``interface-redetect`` Command
----------------------------------
-The :isccmd:`interface-redetect` command retrieves.
+The :isccmd:`interface-redetect` command retrieves the list of detected interfaces
+after performing a re-detect procedure.
+This command does not take any parameters."
.. isccmd:: interface-use
.. _command-interface-use:
The ``interface-use`` Command
-----------------------------
-The :isccmd:`interface-use` command updates.
+The :isccmd:`interface-use` command updates the list of interfaces used
+to process DHCP traffic.
+The command takes as parameter the list of interfaces with respective
+addresses (if specified) on which the server should start listening for
+DHCP traffic.
+
+Please note that the new configuration is
+retained in memory only; if the server is restarted or a configuration
+reload is triggered via a signal, the server uses the configuration
+stored in its configuration file. The server's response contains a
+numeric code, ``result`` (0 for success, non-zero on failure), and a
+string, ``text``, describing the outcome:
+
+::
+
+ {"result": 0, "text": "Configuration successful." }
.. isccmd:: list-commands
.. _command-list-commands:
resetLogPath();
setSocketTestPath();
reset();
+ IfaceMgr::instance().setFamily(AF_INET);
IfaceMgr::instance().setTestMode(false);
IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
IfaceMgr::instancePtr().get(), ph::_1));
EXPECT_TRUE(command_list.find("\"config-hash-get\"") != string::npos);
EXPECT_TRUE(command_list.find("\"config-set\"") != string::npos);
EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"interface-list\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"interface-redetect\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"interface-use\"") != string::npos);
EXPECT_TRUE(command_list.find("\"kea-lfc-start\"") != string::npos);
EXPECT_TRUE(command_list.find("\"leases-reclaim\"") != string::npos);
EXPECT_TRUE(command_list.find("\"subnet4-select-test\"") != string::npos);
checkListCommands(rsp, "config-set");
checkListCommands(rsp, "config-test");
checkListCommands(rsp, "config-write");
+ checkListCommands(rsp, "interface-list");
+ checkListCommands(rsp, "interface-redetect");
+ checkListCommands(rsp, "interface-use");
checkListCommands(rsp, "kea-lfc-start");
checkListCommands(rsp, "list-commands");
checkListCommands(rsp, "leases-reclaim");
EXPECT_EQ(2U, subnets->size());
}
+// Tests if interface-list works properly.
+TEST_F(CtrlChannelDhcpv4SrvTest, interfaceList) {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createUnixChannelServer();
+ SKIP_IF(skipped_);
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-list\" }";
+
+ sendUnixCommand(command, response);
+ string expected = "{ \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" }";
+ EXPECT_EQ(response, expected);
+}
+
+// Tests if interface-redetect works properly.
+TEST_F(CtrlChannelDhcpv4SrvTest, interfaceRedetect) {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ eth0->inactive4_ = true;
+ eth0->inactive6_ = true;
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createUnixChannelServer();
+ SKIP_IF(skipped_);
+ std::string response;
+
+ IfacePtr eth1 = IfaceMgrTestConfig::createIface("eth1", ETH1_INDEX,
+ "AA:BB:CC:DD:EE:FF");
+ eth1->inactive4_ = true;
+ eth1->inactive6_ = true;
+ auto detectUpdateIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ } else {
+ if (!IfaceMgr::instance().getIface("eth1")) {
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ }
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectUpdateIfaces);
+
+ std::string command = "{ \"command\": \"interface-redetect\" }";
+
+ sendUnixCommand(command, response);
+ string expected = "{ \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "}, { "
+ "\"addresses\": [ \"192.0.2.3\", \"fe80::3a60:77ff:fed5:abcd\", \"3001:db8:100::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 2, "
+ "\"mac\": \"aa:bb:cc:dd:ee:ff\", "
+ "\"name\": \"eth1\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"2 interfaces detected.\" }";
+ EXPECT_EQ(response, expected);
+}
+
+// Tests if interface-use works properly.
+TEST_F(CtrlChannelDhcpv4SrvTest, interfaceUse) {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createUnixChannelServer();
+ SKIP_IF(skipped_);
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-use\", \"arguments\": { \"interfaces\": [ \"eth0\" ] } }";
+
+ sendUnixCommand(command, response);
+ EXPECT_EQ(response, "{ \"result\": 0, \"text\": \"Configuration successful.\" }");
+
+ command = "{ \"command\": \"interface-list\" }";
+ sendUnixCommand(command, response);
+ string expected = "{ \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": true, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" }";
+ EXPECT_EQ(response, expected);
+}
+
// This test verifies that disable DHCP service command performs sanity check on
// parameters.
TEST_F(CtrlChannelDhcpv4SrvTest, dhcpDisableBadParam) {
/// Sets socket path to its default value.
BaseCtrlChannelDhcpv4Test() : interfaces_("\"*\""), handle_stop_(false) {
reset();
+ IfaceMgr::instance().setFamily(AF_INET);
IfaceMgr::instance().setTestMode(false);
IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
IfaceMgr::instancePtr().get(), ph::_1));
// which is added after server startup.
void testConfigSetDetectInterfaces();
+ // Tests if interface-list works properly.
+ void testInterfaceList();
+
+ // Tests if interface-redetect works properly.
+ void testInterfaceRedetect();
+
+ // Tests if interface-use works properly.
+ void testInterfaceUse();
+
// This test verifies that disable DHCP service command performs
// sanity check on parameters.
void testDhcpDisableBadParam();
checkListCommands(rsp, "config-set");
checkListCommands(rsp, "config-test");
checkListCommands(rsp, "config-write");
+ checkListCommands(rsp, "interface-list");
+ checkListCommands(rsp, "interface-redetect");
+ checkListCommands(rsp, "interface-use");
checkListCommands(rsp, "kea-lfc-start");
checkListCommands(rsp, "list-commands");
checkListCommands(rsp, "leases-reclaim");
testConfigSetDetectInterfaces();
}
+// Tests if interface-list works properly.
+void
+BaseCtrlChannelDhcpv4Test::testInterfaceList() {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createHttpChannelServer();
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-list\" }";
+
+ sendHttpCommand(command, response);
+ string expected = "[ { \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" } ]";
+ EXPECT_EQ(response, expected);
+}
+
+TEST_F(HttpCtrlChannelDhcpv4Test, interfaceList) {
+ testInterfaceList();
+}
+
+TEST_F(HttpsCtrlChannelDhcpv4Test, interfaceList) {
+ testInterfaceList();
+}
+
+// Tests if interface-redetect works properly.
+void
+BaseCtrlChannelDhcpv4Test::testInterfaceRedetect() {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ eth0->inactive4_ = true;
+ eth0->inactive6_ = true;
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createHttpChannelServer();
+ std::string response;
+
+ IfacePtr eth1 = IfaceMgrTestConfig::createIface("eth1", ETH1_INDEX,
+ "AA:BB:CC:DD:EE:FF");
+ eth1->inactive4_ = true;
+ eth1->inactive6_ = true;
+ auto detectUpdateIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ } else {
+ if (!IfaceMgr::instance().getIface("eth1")) {
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ }
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectUpdateIfaces);
+
+ std::string command = "{ \"command\": \"interface-redetect\" }";
+
+ sendHttpCommand(command, response);
+ string expected = "[ { \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "}, { "
+ "\"addresses\": [ \"192.0.2.3\", \"fe80::3a60:77ff:fed5:abcd\", \"3001:db8:100::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 2, "
+ "\"mac\": \"aa:bb:cc:dd:ee:ff\", "
+ "\"name\": \"eth1\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"2 interfaces detected.\" } ]";
+ EXPECT_EQ(response, expected);
+}
+
+TEST_F(HttpCtrlChannelDhcpv4Test, interfaceRedetect) {
+ testInterfaceRedetect();
+}
+
+TEST_F(HttpsCtrlChannelDhcpv4Test, interfaceRedetect) {
+ testInterfaceRedetect();
+}
+
+// Tests if interface-use works properly.
+void
+BaseCtrlChannelDhcpv4Test::testInterfaceUse() {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createHttpChannelServer();
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-use\", \"arguments\": { \"interfaces\": [ \"eth0\" ] } }";
+
+ sendHttpCommand(command, response);
+ EXPECT_EQ(response, "[ { \"result\": 0, \"text\": \"Configuration successful.\" } ]");
+
+ command = "{ \"command\": \"interface-list\" }";
+ sendHttpCommand(command, response);
+ string expected = "[ { \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": true, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" } ]";
+ EXPECT_EQ(response, expected);
+}
+
+TEST_F(HttpCtrlChannelDhcpv4Test, interfaceUse) {
+ testInterfaceUse();
+}
+
+TEST_F(HttpsCtrlChannelDhcpv4Test, interfaceUse) {
+ testInterfaceUse();
+}
+
// This test verifies that disable DHCP service command performs
// sanity check on parameters.
void
/// Sets socket path to its default value.
CtrlChannelDhcpv6SrvTest() : interfaces_("\"*\""), skipped_(false) {
reset();
+ IfaceMgr::instance().setFamily(AF_INET6);
IfaceMgr::instance().setTestMode(false);
IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
IfaceMgr::instancePtr().get(), ph::_1));
EXPECT_TRUE(command_list.find("\"config-hash-get\"") != string::npos);
EXPECT_TRUE(command_list.find("\"config-set\"") != string::npos);
EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"interface-list\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"interface-redetect\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"interface-use\"") != string::npos);
EXPECT_TRUE(command_list.find("\"kea-lfc-start\"") != string::npos);
EXPECT_TRUE(command_list.find("\"leases-reclaim\"") != string::npos);
EXPECT_TRUE(command_list.find("\"subnet6-select-test\"") != string::npos);
checkListCommands(rsp, "config-set");
checkListCommands(rsp, "config-test");
checkListCommands(rsp, "config-write");
+ checkListCommands(rsp, "interface-list");
+ checkListCommands(rsp, "interface-redetect");
+ checkListCommands(rsp, "interface-use");
checkListCommands(rsp, "kea-lfc-start");
checkListCommands(rsp, "list-commands");
checkListCommands(rsp, "leases-reclaim");
EXPECT_EQ(2U, subnets->size());
}
+// Tests if interface-list works properly.
+TEST_F(CtrlChannelDhcpv6SrvTest, interfaceList) {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createUnixChannelServer();
+ SKIP_IF(skipped_);
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-list\" }";
+
+ sendUnixCommand(command, response);
+ string expected = "{ \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" }";
+ EXPECT_EQ(response, expected);
+}
+
+// Tests if interface-redetect works properly.
+TEST_F(CtrlChannelDhcpv6SrvTest, interfaceRedetect) {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ eth0->inactive4_ = true;
+ eth0->inactive6_ = true;
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createUnixChannelServer();
+ SKIP_IF(skipped_);
+ std::string response;
+
+ IfacePtr eth1 = IfaceMgrTestConfig::createIface("eth1", ETH1_INDEX,
+ "AA:BB:CC:DD:EE:FF");
+ eth1->inactive4_ = true;
+ eth1->inactive6_ = true;
+ auto detectUpdateIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ } else {
+ if (!IfaceMgr::instance().getIface("eth1")) {
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ }
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectUpdateIfaces);
+
+ std::string command = "{ \"command\": \"interface-redetect\" }";
+
+ sendUnixCommand(command, response);
+ string expected = "{ \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "}, { "
+ "\"addresses\": [ \"192.0.2.3\", \"fe80::3a60:77ff:fed5:abcd\", \"3001:db8:100::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 2, "
+ "\"mac\": \"aa:bb:cc:dd:ee:ff\", "
+ "\"name\": \"eth1\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"2 interfaces detected.\" }";
+ EXPECT_EQ(response, expected);
+}
+
+// Tests if interface-use works properly.
+TEST_F(CtrlChannelDhcpv6SrvTest, interfaceUse) {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createUnixChannelServer();
+ SKIP_IF(skipped_);
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-use\", \"arguments\": { \"interfaces\": [ \"eth0\" ] } }";
+
+ sendUnixCommand(command, response);
+ EXPECT_EQ(response, "{ \"result\": 0, \"text\": \"Configuration successful.\" }");
+
+ command = "{ \"command\": \"interface-list\" }";
+ sendUnixCommand(command, response);
+ string expected = "{ \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": true, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" }";
+ EXPECT_EQ(response, expected);
+}
+
// This test verifies that disable DHCP service command performs sanity check on
// parameters.
TEST_F(CtrlChannelDhcpv6SrvTest, dhcpDisableBadParam) {
/// Sets socket path to its default value.
BaseCtrlChannelDhcpv6Test() : interfaces_("\"*\""), handle_stop_(false) {
reset();
+ IfaceMgr::instance().setFamily(AF_INET6);
IfaceMgr::instance().setTestMode(false);
IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
IfaceMgr::instancePtr().get(), ph::_1));
// which is added after server startup.
void testConfigSetDetectInterfaces();
+ // Tests if interface-list works properly.
+ void testInterfaceList();
+
+ // Tests if interface-redetect works properly.
+ void testInterfaceRedetect();
+
+ // Tests if interface-use works properly.
+ void testInterfaceUse();
+
// This test verifies that disable DHCP service command performs
// sanity check on parameters.
void testDhcpDisableBadParam();
checkListCommands(rsp, "config-set");
checkListCommands(rsp, "config-test");
checkListCommands(rsp, "config-write");
+ checkListCommands(rsp, "interface-list");
+ checkListCommands(rsp, "interface-redetect");
+ checkListCommands(rsp, "interface-use");
+ checkListCommands(rsp, "kea-lfc-start");
checkListCommands(rsp, "list-commands");
checkListCommands(rsp, "leases-reclaim");
checkListCommands(rsp, "version-get");
testConfigSetDetectInterfaces();
}
+// Tests if interface-list works properly.
+void
+BaseCtrlChannelDhcpv6Test::testInterfaceList() {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createHttpChannelServer();
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-list\" }";
+
+ sendHttpCommand(command, response);
+ string expected = "[ { \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" } ]";
+ EXPECT_EQ(response, expected);
+}
+
+TEST_F(HttpCtrlChannelDhcpv6Test, interfaceList) {
+ testInterfaceList();
+}
+
+TEST_F(HttpsCtrlChannelDhcpv6Test, interfaceList) {
+ testInterfaceList();
+}
+
+// Tests if interface-redetect works properly.
+void
+BaseCtrlChannelDhcpv6Test::testInterfaceRedetect() {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ eth0->inactive4_ = true;
+ eth0->inactive6_ = true;
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createHttpChannelServer();
+ std::string response;
+
+ IfacePtr eth1 = IfaceMgrTestConfig::createIface("eth1", ETH1_INDEX,
+ "AA:BB:CC:DD:EE:FF");
+ eth1->inactive4_ = true;
+ eth1->inactive6_ = true;
+ auto detectUpdateIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ } else {
+ if (!IfaceMgr::instance().getIface("eth1")) {
+ eth1->addAddress(IOAddress("192.0.2.3"));
+ eth1->addAddress(IOAddress("fe80::3a60:77ff:fed5:abcd"));
+ eth1->addAddress(IOAddress("3001:db8:100::1"));
+ IfaceMgr::instance().addInterface(eth1);
+ }
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectUpdateIfaces);
+
+ std::string command = "{ \"command\": \"interface-redetect\" }";
+
+ sendHttpCommand(command, response);
+ string expected = "[ { \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "}, { "
+ "\"addresses\": [ \"192.0.2.3\", \"fe80::3a60:77ff:fed5:abcd\", \"3001:db8:100::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 2, "
+ "\"mac\": \"aa:bb:cc:dd:ee:ff\", "
+ "\"name\": \"eth1\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"2 interfaces detected.\" } ]";
+ EXPECT_EQ(response, expected);
+}
+
+TEST_F(HttpCtrlChannelDhcpv6Test, interfaceRedetect) {
+ testInterfaceRedetect();
+}
+
+TEST_F(HttpsCtrlChannelDhcpv6Test, interfaceRedetect) {
+ testInterfaceRedetect();
+}
+
+// Tests if interface-use works properly.
+void
+BaseCtrlChannelDhcpv6Test::testInterfaceUse() {
+ interfaces_ = "";
+ IfacePtr eth0 = IfaceMgrTestConfig::createIface("eth0", ETH0_INDEX,
+ "11:22:33:44:55:66");
+ auto detectIfaces = [&](bool update_only) {
+ if (!update_only) {
+ eth0->addAddress(IOAddress("10.0.0.1"));
+ eth0->addAddress(IOAddress("fe80::3a60:77ff:fed5:cdef"));
+ eth0->addAddress(IOAddress("2001:db8:1::1"));
+ IfaceMgr::instance().addInterface(eth0);
+ }
+ return (false);
+ };
+ IfaceMgr::instance().setDetectCallback(detectIfaces);
+ IfaceMgr::instance().clearIfaces();
+ IfaceMgr::instance().closeSockets();
+ IfaceMgr::instance().detectIfaces();
+ createHttpChannelServer();
+ std::string response;
+
+ std::string command = "{ \"command\": \"interface-use\", \"arguments\": { \"interfaces\": [ \"eth0\" ] } }";
+
+ sendHttpCommand(command, response);
+ EXPECT_EQ(response, "[ { \"result\": 0, \"text\": \"Configuration successful.\" } ]");
+
+ command = "{ \"command\": \"interface-list\" }";
+ sendHttpCommand(command, response);
+ string expected = "[ { \"arguments\": { \"interfaces\": [ { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": true, "
+ "\"index\": 1, "
+ "\"mac\": \"11:22:33:44:55:66\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 1 "
+ "} ] }, \"result\": 0, \"text\": \"1 interfaces detected.\" } ]";
+ EXPECT_EQ(response, expected);
+}
+
+TEST_F(HttpCtrlChannelDhcpv6Test, interfaceUse) {
+ testInterfaceUse();
+}
+
+TEST_F(HttpsCtrlChannelDhcpv6Test, interfaceUse) {
+ testInterfaceUse();
+}
+
// This test verifies that disable DHCP service command performs
// sanity check on parameters.
void
IfaceMgr::IfaceMgr()
: packet_filter_(new PktFilterInet()),
packet_filter6_(new PktFilterInet6()),
- test_mode_(false), check_thread_id_(true), allow_loopback_(false) {
+ test_mode_(false), check_thread_id_(true),
+ allow_loopback_(false), family_(AF_INET) {
id_ = std::this_thread::get_id();
// Ensure that PQMs have been created to guarantee we have
EXPECT_TRUE(iface);
}
+// This test checks the getIface by index method.
+TEST_F(IfaceMgrTest, interfacesToElement) {
+ NakedIfaceMgr ifacemgr;
+
+ // Create a set of fake interfaces. At the same time, remove the actual
+ // interfaces that have been detected by the IfaceMgr.
+ ifacemgr.createIfaces();
+
+ auto ifaces = ifacemgr.ifacesToElement();
+ std::string expected = "[ { "
+ "\"addresses\": [ \"127.0.0.1\", \"::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": true, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": false, "
+ "\"index\": 0, "
+ "\"mac\": \"\", "
+ "\"name\": \"lo\", "
+ "\"type\": 0 "
+ "}, { "
+ "\"addresses\": [ \"10.0.0.1\", \"fe80::3a60:77ff:fed5:cdef\", \"2001:db8:1::1\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": true, "
+ "\"index\": 1, "
+ "\"mac\": \"\", "
+ "\"name\": \"eth0\", "
+ "\"type\": 0 "
+ "}, { "
+ "\"addresses\": [ \"192.0.2.3\", \"fe80::3a60:77ff:fed5:abcd\" ], "
+ "\"flag-broadcast\": false, "
+ "\"flag-loopback\": false, "
+ "\"flag-multicast\": true, "
+ "\"flag-running\": true, "
+ "\"flag-up\": true, "
+ "\"in-use\": true, "
+ "\"index\": 2, "
+ "\"mac\": \"\", "
+ "\"name\": \"eth1\", "
+ "\"type\": 0 "
+ "} ]";
+ EXPECT_EQ(ifaces->str(), expected);
+}
+
// This test checks the getIface by packet method.
TEST_F(IfaceMgrTest, getIfaceByPkt) {
NakedIfaceMgr ifacemgr;
EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:feed:1")));
}
+// Test the Iface structure itself
+TEST_F(IfaceMgrTest, family) {
+ NakedIfaceMgr ifacemgr;
+ EXPECT_EQ(ifacemgr.getFamily(), AF_INET);
+ ifacemgr.setFamily(AF_INET6);
+ EXPECT_EQ(ifacemgr.getFamily(), AF_INET6);
+}
+
// Test the Iface structure itself
TEST_F(IfaceMgrTest, iface) {
boost::scoped_ptr<Iface> iface;
#include <dhcp/testutils/pkt_filter_test_stub.h>
#include <dhcp/testutils/pkt_filter6_test_stub.h>
#include <dhcpsrv/cfg_iface.h>
+#include <dhcpsrv/parsers/ifaces_config_parser.h>
#include <asiolink/io_service.h>
#include <asiolink/asio_wrapper.h>
#include <asiolink/interval_timer.h>
EXPECT_EQ(second_port_calls, 2);
}
+// Test that merge CfgIface works properly.
+TEST_F(CfgIfaceTest, mergeV4CfgIface) {
+ CfgIfacePtr left(new CfgIface());
+ CfgIfacePtr right(new CfgIface());
+ std::string left_txt("{ \"interfaces\": [\"eth0\", \"eth1/192.0.2.3\"], \"re-detect\": false }");
+ std::string right_txt("{ \"interfaces\": [\"eth0/10.0.0.1\", \"eth1961\"], \"re-detect\": false }");
+ ConstElementPtr left_cfg = Element::fromJSON(left_txt);
+ ConstElementPtr right_cfg = Element::fromJSON(right_txt);
+ IfacesConfigParser parser(AF_INET, true);
+ EXPECT_NO_THROW(parser.parse(left, left_cfg));
+ auto lift_before = left->toElement()->str();
+ EXPECT_NO_THROW(parser.parse(right, right_cfg));
+ auto right_before = right->toElement()->str();
+ EXPECT_THROW(left->merge(*right, AF_INET), DuplicateIfaceName);
+ EXPECT_EQ(lift_before, left->toElement()->str());
+ EXPECT_THROW(right->merge(*left, AF_INET), DuplicateIfaceName);
+ EXPECT_EQ(right_before, right->toElement()->str());
+}
+
+// Test that merge CfgIface works properly.
+TEST_F(CfgIfaceTest, mergeV6CfgIface) {
+ CfgIfacePtr left(new CfgIface());
+ CfgIfacePtr right(new CfgIface());
+ std::string left_txt("{ \"interfaces\": [\"eth0/2001:db8:1::1\", \"eth1\"], \"re-detect\": false }");
+ std::string right_txt("{ \"interfaces\": [\"eth0/2001:db8:1::1\", \"eth1961\"], \"re-detect\": false }");
+ ConstElementPtr left_cfg = Element::fromJSON(left_txt);
+ ConstElementPtr right_cfg = Element::fromJSON(right_txt);
+ IfacesConfigParser parser(AF_INET6, true);
+ EXPECT_NO_THROW(parser.parse(left, left_cfg));
+ auto lift_before = left->toElement()->str();
+ EXPECT_NO_THROW(parser.parse(right, right_cfg));
+ auto right_before = right->toElement()->str();
+ EXPECT_THROW(left->merge(*right, AF_INET6), DuplicateAddress);
+ EXPECT_EQ(lift_before, left->toElement()->str());
+ EXPECT_THROW(right->merge(*left, AF_INET6), DuplicateAddress);
+ EXPECT_EQ(right_before, right->toElement()->str());
+}
+
// This test verifies that it is possible to specify the socket
// type to be used by the DHCPv4 server.
// This test is enabled on LINUX and BSD only, because the
"access": "read",
"avail": "3.1.8",
"brief": [
- "This command returns the list of detected interfaces.",
+ "This command retrieves the list of detected interfaces.",
"This command does not take any parameters."
],
"cmd-syntax": [
"access": "write",
"avail": "3.1.8",
"brief": [
- "This command returns the list of detected interfaces after performing",
+ "This command retrieves the list of detected interfaces after performing",
"a re-detect procedure.",
"This command does not take any parameters."
],
"access": "write",
"avail": "3.1.8",
"brief": [
- "This command returns the list of detected interfaces after performing",
- "a re-detect procedure.",
- "This command take as parameters the list of interfaces with respective",
+ "This command updates the list of interfaces used to process DHCP traffic.",
+ "This command takes as parameter the list of interfaces with respective",
"addresses (if specified) on which the server should start listening for",
"DHCP traffic."
],