From: Razvan Becheriu Date: Wed, 1 Apr 2026 21:44:03 +0000 (+0300) Subject: [#3144] added unit tests X-Git-Tag: Kea-3.1.9~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dd795e7dff34d28c081c88e46205ea54a5f352bc;p=thirdparty%2Fkea.git [#3144] added unit tests --- diff --git a/doc/sphinx/arm/ctrl-channel.rst b/doc/sphinx/arm/ctrl-channel.rst index a5c3eb80fb..679285f7b0 100644 --- a/doc/sphinx/arm/ctrl-channel.rst +++ b/doc/sphinx/arm/ctrl-channel.rst @@ -490,7 +490,8 @@ information about the processing of expired leases (lease reclamation). 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: @@ -498,7 +499,9 @@ The :isccmd:`interface-list` command retrieves. 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: @@ -506,7 +509,22 @@ The :isccmd:`interface-redetect` command retrieves. 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: diff --git a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc index 156d248352..f4ee1317a6 100644 --- a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc @@ -131,6 +131,7 @@ public: resetLogPath(); setSocketTestPath(); reset(); + IfaceMgr::instance().setFamily(AF_INET); IfaceMgr::instance().setTestMode(false); IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces, IfaceMgr::instancePtr().get(), ph::_1)); @@ -549,6 +550,9 @@ TEST_F(CtrlChannelDhcpv4SrvTest, commandsRegistration) { 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); @@ -1870,6 +1874,9 @@ TEST_F(CtrlChannelDhcpv4SrvTest, listCommands) { 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"); @@ -2421,6 +2428,173 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configSetDetectInterfaces) { 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) { diff --git a/src/bin/dhcp4/tests/http_control_socket_unittest.cc b/src/bin/dhcp4/tests/http_control_socket_unittest.cc index 62afb7e4d4..186c9789b6 100644 --- a/src/bin/dhcp4/tests/http_control_socket_unittest.cc +++ b/src/bin/dhcp4/tests/http_control_socket_unittest.cc @@ -106,6 +106,7 @@ public: /// 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)); @@ -573,6 +574,15 @@ public: // 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(); @@ -2969,6 +2979,9 @@ BaseCtrlChannelDhcpv4Test::testListCommands() { 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"); @@ -3624,6 +3637,197 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configSetDetectInterfaces) { 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 diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc index bcf60651aa..662a8947f0 100644 --- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc @@ -162,6 +162,7 @@ public: /// 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)); @@ -552,6 +553,9 @@ TEST_F(CtrlDhcpv6SrvTest, commandsRegistration) { 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); @@ -1870,6 +1874,9 @@ TEST_F(CtrlChannelDhcpv6SrvTest, listCommands) { 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"); @@ -2415,6 +2422,173 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSetDetectInterfaces) { 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) { diff --git a/src/bin/dhcp6/tests/http_control_socket_unittest.cc b/src/bin/dhcp6/tests/http_control_socket_unittest.cc index e33cdc58b1..6b54f16109 100644 --- a/src/bin/dhcp6/tests/http_control_socket_unittest.cc +++ b/src/bin/dhcp6/tests/http_control_socket_unittest.cc @@ -142,6 +142,7 @@ public: /// 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)); @@ -582,6 +583,15 @@ public: // 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(); @@ -2967,6 +2977,10 @@ BaseCtrlChannelDhcpv6Test::testListCommands() { 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"); @@ -3615,6 +3629,197 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configSetDetectInterfaces) { 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 diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc index d3cfbc6477..e3932ce523 100644 --- a/src/lib/dhcp/iface_mgr.cc +++ b/src/lib/dhcp/iface_mgr.cc @@ -180,7 +180,8 @@ bool Iface::delSocket(const uint16_t sockfd) { 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 diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc index f61c7fee1f..96afc67c1a 100644 --- a/src/lib/dhcp/tests/iface_mgr_unittest.cc +++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc @@ -1890,6 +1890,55 @@ TEST_F(IfaceMgrTest, getIfaceByIndex) { 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; @@ -3551,6 +3600,14 @@ TEST_F(IfaceMgrTest, hasOpenSocketForAddress6) { 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; diff --git a/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc b/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc index c935664165..8fc0d70c7c 100644 --- a/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfg_iface_unittest.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1737,6 +1738,44 @@ TEST_F(CfgIfaceTest, retryDoubleOpenServiceSockets6) { 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 diff --git a/src/share/api/interface-list.json b/src/share/api/interface-list.json index 3a926abf05..7f9ebfda5e 100644 --- a/src/share/api/interface-list.json +++ b/src/share/api/interface-list.json @@ -2,7 +2,7 @@ "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": [ diff --git a/src/share/api/interface-redetect.json b/src/share/api/interface-redetect.json index 7dcb8b10e6..5f9e71cdfa 100644 --- a/src/share/api/interface-redetect.json +++ b/src/share/api/interface-redetect.json @@ -2,7 +2,7 @@ "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." ], diff --git a/src/share/api/interface-use.json b/src/share/api/interface-use.json index b252688824..163d5a70e9 100644 --- a/src/share/api/interface-use.json +++ b/src/share/api/interface-use.json @@ -2,9 +2,8 @@ "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." ],