// of the IfaceMgr. Those modifications require that sockets are closed.
closeSockets();
// The loopback interface can be used only when:
- // - wildcard is not used
// - UDP socket will be used, i.e. not IPv4 and RAW socket
- // - there is one interface name only in the interface set
- // and this interface is a loopback interface.
- // - or the interface set is empty and all interfaces in the address
- // map are the same and a loopback interface.
+ // - the loopback interface is in the interface set or the address map.
bool loopback_used_ = false;
- if (!wildcard_used_ &&
- ((family == AF_INET6) || (socket_type_ == SOCKET_UDP)) &&
- (iface_set_.size() == 1) &&
- (address_map_.empty())) {
- // Get the first and only interface.
- IfacePtr iface = IfaceMgr::instance().getIface(*iface_set_.begin());
- if (iface && iface->flag_loopback_) {
- loopback_used_ = true;
+ if ((family == AF_INET6) || (socket_type_ == SOCKET_UDP)) {
+ // Check interface set
+ for (IfaceSet::const_iterator iface_name = iface_set_.begin();
+ iface_name != iface_set_.end(); ++iface_name) {
+ IfacePtr iface = IfaceMgr::instance().getIface(*iface_name);
+ if (iface && iface->flag_loopback_) {
+ loopback_used_ = true;
+ }
}
- } else if (!wildcard_used_ &&
- ((family == AF_INET6) || (socket_type_ == SOCKET_UDP)) &&
- iface_set_.empty() &&
- !address_map_.empty()) {
- // Get the first interface
- const std::string& name = address_map_.begin()->first;
- bool same = true;
+ // Check address map
for (ExplicitAddressMap::const_iterator unicast = address_map_.begin();
unicast != address_map_.end(); ++unicast) {
- if (unicast->first != name) {
- same = false;
- break;
- }
- }
- if (same) {
- IfacePtr iface = IfaceMgr::instance().getIface(name);
+ IfacePtr iface = IfaceMgr::instance().getIface(unicast->first);
if (iface && iface->flag_loopback_) {
loopback_used_ = true;
}
// interface names specified by the user. If wildcard interface was
// specified, mark all interfaces active. Mark loopback inactive when
// not explicitely allowed.
- setState(family, !wildcard_used_, loopback_used_);
+ setState(family, !wildcard_used_, !loopback_used_);
IfaceMgr& iface_mgr = IfaceMgr::instance();
// Remove selection of unicast addresses from all interfaces.
iface_mgr.clearUnicasts();
ASSERT_NO_THROW(cfg.use(AF_INET, "lo"));
ASSERT_NO_THROW(cfg.useSocketType(AF_INET, CfgIface::SOCKET_UDP));
cfg.openSockets(AF_INET, DHCP4_SERVER_PORT);
- // No loopback socket
- EXPECT_FALSE(socketOpen("lo", "127.0.0.1"));
+ // No wildcard is no longer a constraint
+ EXPECT_TRUE(socketOpen("lo", "127.0.0.1"));
+ cfg.closeSockets();
+ ASSERT_FALSE(socketOpen("lo", "127.0.0.1"));
// Retry without UDP sockets
cfg.reset();
ASSERT_NO_THROW(cfg.use(AF_INET, "lo"));
ASSERT_NO_THROW(cfg.useSocketType(AF_INET, CfgIface::SOCKET_UDP));
cfg.openSockets(AF_INET, DHCP4_SERVER_PORT);
- // No loopback socket
+ // Only loopback is no longer a constraint
+ EXPECT_TRUE(socketOpen("lo", "127.0.0.1"));
+ cfg.closeSockets();
EXPECT_FALSE(socketOpen("lo", "127.0.0.1"));
- // Finally with a second interface and address
+ // Finally with interfaces and addresses
cfg.reset();
ASSERT_NO_THROW(cfg.use(AF_INET, "eth0/10.0.0.1"));
- ASSERT_NO_THROW(cfg.use(AF_INET, "lo"));
+ ASSERT_NO_THROW(cfg.use(AF_INET, "lo/127.0.0.1"));
ASSERT_NO_THROW(cfg.useSocketType(AF_INET, CfgIface::SOCKET_UDP));
cfg.openSockets(AF_INET, DHCP4_SERVER_PORT);
- // No loopback socket
- EXPECT_FALSE(socketOpen("lo", "127.0.0.1"));
-}
-
-// Tests that the loopback socket is not opened in raw mode.
-TEST_F(CfgIfaceTest, explicitLoopbackV4Negative) {
- CfgIface cfg;
- ASSERT_NO_THROW(cfg.use(AF_INET, "lo"));
-
- // Use UDP sockets
- ASSERT_NO_THROW(cfg.useSocketType(AF_INET, CfgIface::SOCKET_RAW));
-
- // Open sockets on specified interfaces and addresses.
- cfg.openSockets(AF_INET, DHCP4_SERVER_PORT);
+ // Only loopback is no longer a constraint
+ EXPECT_TRUE(socketOpen("lo", "127.0.0.1"));
+ cfg.closeSockets();
EXPECT_FALSE(socketOpen("lo", "127.0.0.1"));
- EXPECT_FALSE(socketOpen("lo", AF_INET));
}
// This test checks that the interface names can be explicitly selected
EXPECT_FALSE(socketOpen("lo", AF_INET6));
}
-// This test checks that the loopback socket can be opened.
-TEST_F(CfgIfaceTest, loopback6) {
- CfgIface cfg;
- // Specify valid interface names. There should be no error.
- ASSERT_NO_THROW(cfg.use(AF_INET6, "lo"));
-
- // Open sockets on specified interfaces.
- cfg.openSockets(AF_INET6, DHCP6_SERVER_PORT);
-
- // There should be a socket open.
- EXPECT_FALSE(socketOpen("lo", AF_INET6));
- EXPECT_FALSE(socketOpen("lo", "::1"));
-}
-
// This test checks that the wildcard interface name can be specified to
// select all interfaces to open IPv4 sockets.
TEST_F(CfgIfaceTest, wildcardV4) {
ASSERT_NO_THROW(cfg.use(AF_INET6, "*"));
ASSERT_NO_THROW(cfg.use(AF_INET6, "lo/::1"));
cfg.openSockets(AF_INET6, DHCP6_SERVER_PORT);
- // No loopback socket
- EXPECT_FALSE(socketOpen("lo", AF_INET6));
+ // No wildcard is no longer a constraint
+ EXPECT_TRUE(socketOpen("lo", AF_INET6));
+ cfg.closeSockets();
+ ASSERT_FALSE(socketOpen("lo", AF_INET6));
// Retry with a second interface
cfg.reset();
ASSERT_NO_THROW(cfg.use(AF_INET6, "eth0"));
ASSERT_NO_THROW(cfg.use(AF_INET6, "lo/::1"));
cfg.openSockets(AF_INET6, DHCP6_SERVER_PORT);
- // No loopback socket
- EXPECT_FALSE(socketOpen("lo", AF_INET6));
+ // Only loopback is no longer a constraint
+ EXPECT_TRUE(socketOpen("lo", AF_INET6));
+ cfg.closeSockets();
+ ASSERT_FALSE(socketOpen("lo", AF_INET6));
- // Finally with a second interface and address
+ // Finally with interfaces and addresses
cfg.reset();
ASSERT_NO_THROW(cfg.use(AF_INET6, "eth0/2001:db8:1::1"));
ASSERT_NO_THROW(cfg.use(AF_INET6, "lo/::1"));
cfg.openSockets(AF_INET6, DHCP6_SERVER_PORT);
- // No loopback socket
- EXPECT_FALSE(socketOpen("lo", AF_INET6));
+ // Only loopback is no longer a constraint
+ EXPECT_TRUE(socketOpen("lo", AF_INET6));
+ cfg.closeSockets();
+ ASSERT_FALSE(socketOpen("lo", AF_INET6));
}
// Test that the equality and inequality operators work fine for CfgIface.