// If relay information is specified for this subnet, it must match.
// Otherwise, we ignore this subnet.
- if (!(*subnet)->getRelayInfo().addr_.isV4Zero()) {
- if (selector.giaddr_ != (*subnet)->getRelayInfo().addr_) {
+ if ((*subnet)->hasRelays()) {
+ if (!(*subnet)->hasRelayAddress(selector.giaddr_)) {
continue;
}
-
} else {
// Relay information is not specified on the subnet level,
// so let's try matching on the shared network level.
SharedNetwork4Ptr network;
(*subnet)->getSharedNetwork(network);
- if (!network || (selector.giaddr_ != network->getRelayInfo().addr_)) {
+ if (!network || !(network->hasRelayAddress(selector.giaddr_))) {
continue;
}
}
for (Subnet6Collection::const_iterator subnet = subnets_.begin();
subnet != subnets_.end(); ++subnet) {
- // If the specified address matches the relay address, return this
+ // If the specified address matches a relay address, return this
// subnet.
if (is_relay_address &&
- ((*subnet)->getRelayInfo().addr_ == address) &&
+ ((*subnet)->hasRelayAddress(address)) &&
(*subnet)->clientSupported(client_classes)) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
DHCPSRV_CFGMGR_SUBNET6_RELAY)
.arg((*subnet)->toText()).arg(address.toText());
return (*subnet);
}
+
}
}
namespace isc {
namespace dhcp {
-Network::RelayInfo::RelayInfo(const isc::asiolink::IOAddress& addr)
- :addr_(addr) {
+void
+Network::RelayInfo::addAddress(const asiolink::IOAddress& addr) {
+ if (containsAddress(addr)) {
+ isc_throw (BadValue, "RelayInfo already contains address: "
+ << addr.toText());
+ }
+
+ addresses_.push_back(addr);
+}
+
+bool
+Network::RelayInfo::hasAddresses() const {
+ return (addresses_.size() > 0);
+}
+
+bool
+Network::RelayInfo::containsAddress(const asiolink::IOAddress& addr) const {
+ for (auto address = addresses_.begin(); address != addresses_.end();
+ ++address) {
+ if ((*address) == addr) {
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+const IOAddressList&
+Network::RelayInfo::getAddresses() const {
+ return (addresses_);
+}
+
+void
+Network::addRelayAddress(const asiolink::IOAddress& addr) {
+ relay_.addAddress(addr);
+}
+
+bool
+Network::hasRelays() const {
+ return (relay_.hasAddresses());
+}
+
+bool
+Network::hasRelayAddress(const asiolink::IOAddress& addr) const {
+ return (relay_.containsAddress(addr));
+}
+
+const IOAddressList&
+Network::getRelayAddresses() const {
+ return (relay_.getAddresses());
}
bool
map->set("interface", Element::create(iface));
}
- // Set relay info
- const RelayInfo& relay_info = getRelayInfo();
- ElementPtr relay = Element::createMap();
- relay->set("ip-address", Element::create(relay_info.addr_.toText()));
- map->set("relay", relay);
+ ElementPtr relay_map = Element::createMap();
+ ElementPtr address_list = Element::createList();
+ const IOAddressList addresses = getRelayAddresses();
+ for (auto address = addresses.begin(); address != addresses.end(); ++address) {
+ address_list->add(Element::create((*address).toText()));
+ }
+
+ relay_map->set("ip-addresses", address_list);
+ map->set("relay", relay_map);
// Set client-class
const ClientClass& cclass = getClientClass();
namespace isc {
namespace dhcp {
+/// List of IOAddresses
+typedef std::vector<isc::asiolink::IOAddress> IOAddressList;
+
/// @brief Common interface representing a network to which the DHCP clients
/// are connected.
///
/// derived classes.
class Network : public virtual UserContext, public data::CfgToElement {
public:
-
/// @brief Holds optional information about relay.
///
/// In some cases it is beneficial to have additional information about
/// a relay configured in the subnet. For now, the structure holds only
- /// IP address, but there may potentially be additional parameters added
+ /// IP addresses, but there may potentially be additional parameters added
/// later, e.g. relay interface-id or relay-id.
- struct RelayInfo {
+ class RelayInfo {
+ public:
- /// @brief default and the only constructor
+ /// @brief Adds an address to the list of addresses
///
- /// @param addr an IP address of the relay (may be :: or 0.0.0.0)
- RelayInfo(const isc::asiolink::IOAddress& addr);
+ /// @param addr address to add
+ /// @throw BadValue if the address is already in the list
+ void addAddress(const asiolink::IOAddress& addr);
- /// @brief IP address of the relay
- isc::asiolink::IOAddress addr_;
+ /// @brief Returns const reference to the list of addresses
+ ///
+ /// @return const reference to the list of addresses
+ const IOAddressList& getAddresses() const;
+
+ /// @brief Indicates whether or not the address list has entries
+ ///
+ /// @return True if the address list is not empty
+ bool hasAddresses() const;
+
+ /// @brief Checks the address list for the given address
+ ///
+ /// @return True if the address is found in the address list
+ bool containsAddress(const asiolink::IOAddress& addr) const;
+
+ private:
+ /// @brief List of relay IP addresses
+ IOAddressList addresses_;
};
+
/// @brief Specifies allowed host reservation mode.
///
typedef enum {
/// @brief Constructor.
Network()
- : iface_name_(), relay_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
- client_class_(""), t1_(0), t2_(0), valid_(0),
+ : iface_name_(), client_class_(""), t1_(0), t2_(0), valid_(0),
host_reservation_mode_(HR_ALL), cfg_option_(new CfgOption()) {
}
return (relay_);
}
+ /// @brief Adds an address to the list addresses in the network's relay info
+ ///
+ /// @param addr address of the relay
+ /// @throw BadValue if the address is already in the list
+ void addRelayAddress(const asiolink::IOAddress& addr);
+
+ /// @brief Returns the list of relay addresses from the network's relay info
+ ///
+ /// @return const reference to the list of addresses
+ const IOAddressList& getRelayAddresses() const;
+
+ /// @brief Indicates if network's relay info has relay addresses
+ ///
+ /// @return True the relay list is not empty, false otherwise
+ bool hasRelays() const;
+
+ /// @brief Tests if the network's relay info contains the given address
+ ///
+ /// @param address address to search for in the relay list
+ /// @return True if a relay with the given address is found, false otherwise
+ bool hasRelayAddress(const asiolink::IOAddress& address) const;
+
/// @brief Checks whether this network supports client that belongs to
/// specified classes.
///
/// @brief Constructor.
Network6()
: Network(), preferred_(0), interface_id_(), rapid_commit_(false) {
- setRelayInfo(asiolink::IOAddress::IPV6_ZERO_ADDRESS());
}
/// @brief Returns preferred lifetime (in seconds)
// Ok, we're done with parsing. Let's store the result in the structure
// we were given as configuration storage.
- *cfg = isc::dhcp::Network::RelayInfo(ip);
+ *cfg = isc::dhcp::Network::RelayInfo();
+ cfg->addAddress(ip);
}
//****************************** PoolParser ********************************
: pools_(new PoolStorage()),
address_family_(family),
options_(new CfgOption()) {
- string addr = family == AF_INET ? "0.0.0.0" : "::";
- relay_info_.reset(new isc::dhcp::Network::RelayInfo(IOAddress(addr)));
+ relay_info_.reset(new isc::dhcp::Network::RelayInfo());
}
SubnetPtr
sn6ptr->setRelayInfo(*relay_info_);
}
-
// Parse Host Reservations for this subnet if any.
ConstElementPtr reservations = subnet->get("reservations");
if (reservations) {
isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
<< " specified in subnet4");
}
- // Relay info.
- setRelayInfo(IOAddress::IPV4_ZERO_ADDRESS());
+
// Timers.
setT1(t1);
setT2(t2);
<< " specified in subnet6");
}
- // Relay info.
- setRelayInfo(RelayInfo(IOAddress::IPV6_ZERO_ADDRESS()));
// Timers.
setT1(t1);
setT2(t2);
SharedNetwork4Ptr network2(new SharedNetwork4("dog"));
network1->setIface("eth0");
+ network1->addRelayAddress(IOAddress("198.16.1.1"));
+ network1->addRelayAddress(IOAddress("198.16.1.2"));
+
network2->setIface("eth1");
CfgSharedNetworks4 cfg;
" \"name\": \"dog\",\n"
" \"option-data\": [ ],\n"
" \"rebind-timer\": 0,\n"
- " \"relay\": {\n"
- " \"ip-address\": \"0.0.0.0\"\n"
- " },\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"renew-timer\": 0,\n"
" \"reservation-mode\": \"all\","
" \"subnet4\": [ ],\n"
" \"name\": \"frog\",\n"
" \"option-data\": [ ],\n"
" \"rebind-timer\": 0,\n"
- " \"relay\": {\n"
- " \"ip-address\": \"0.0.0.0\"\n"
- " },\n"
+ " \"relay\": { \"ip-addresses\": [ \"198.16.1.1\", \"198.16.1.2\" ] },\n"
" \"renew-timer\": 0,\n"
" \"reservation-mode\": \"all\","
" \"subnet4\": [ ],\n"
SharedNetwork6Ptr network2(new SharedNetwork6("dog"));
network1->setIface("eth0");
+ network1->addRelayAddress(IOAddress("2001:db8:1::1"));
+ network1->addRelayAddress(IOAddress("2001:db8:1::2"));
network2->setIface("eth1");
CfgSharedNetworks6 cfg;
" \"preferred-lifetime\": 0,\n"
" \"rapid-commit\": false,\n"
" \"rebind-timer\": 0,\n"
- " \"relay\": {\n"
- " \"ip-address\": \"::\"\n"
- " },\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"renew-timer\": 0,\n"
" \"reservation-mode\": \"all\","
" \"subnet6\": [ ],\n"
" \"preferred-lifetime\": 0,\n"
" \"rapid-commit\": false,\n"
" \"rebind-timer\": 0,\n"
- " \"relay\": {\n"
- " \"ip-address\": \"::\"\n"
- " },\n"
+ " \"relay\": { \"ip-addresses\": [ \"2001:db8:1::1\", \"2001:db8:1::2\" ] },\n"
" \"renew-timer\": 0,\n"
" \"reservation-mode\": \"all\","
" \"subnet6\": [ ],\n"
// Over relay-info too
selector.giaddr_ = IOAddress("10.0.0.1");
- subnet2->setRelayInfo(IOAddress("10.0.0.1"));
+ subnet2->addRelayAddress(IOAddress("10.0.0.1"));
EXPECT_EQ(subnet3, cfg.selectSubnet(selector));
selector.option_select_ = IOAddress("0.0.0.0");
EXPECT_EQ(subnet2, cfg.selectSubnet(selector));
EXPECT_FALSE(cfg.selectSubnet(selector));
// Now specify relay info
- subnet1->setRelayInfo(IOAddress("10.0.0.1"));
- subnet2->setRelayInfo(IOAddress("10.0.0.2"));
- subnet3->setRelayInfo(IOAddress("10.0.0.3"));
+ subnet1->addRelayAddress(IOAddress("10.0.0.1"));
+ subnet2->addRelayAddress(IOAddress("10.0.0.2"));
+ subnet3->addRelayAddress(IOAddress("10.0.0.3"));
// And try again. This time relay-info is there and should match.
selector.giaddr_ = IOAddress("10.0.0.1");
// Now specify relay info. Note that for the second subnet we specify
// relay info on the network level.
- subnet1->setRelayInfo(IOAddress("10.0.0.1"));
- network->setRelayInfo(IOAddress("10.0.0.2"));
- subnet3->setRelayInfo(IOAddress("10.0.0.3"));
+ subnet1->addRelayAddress(IOAddress("10.0.0.1"));
+ network->addRelayAddress(IOAddress("10.0.0.2"));
+ subnet3->addRelayAddress(IOAddress("10.0.0.3"));
// And try again. This time relay-info is there and should match.
selector.giaddr_ = IOAddress("10.0.0.1");
// Now specify relay info. Note that for the second subnet we specify
// relay info on the network level.
- subnet1->setRelayInfo(IOAddress("10.0.0.1"));
- subnet2->setRelayInfo(IOAddress("10.0.0.2"));
- subnet3->setRelayInfo(IOAddress("10.0.0.3"));
+ subnet1->addRelayAddress(IOAddress("10.0.0.1"));
+ subnet2->addRelayAddress(IOAddress("10.0.0.2"));
+ subnet3->addRelayAddress(IOAddress("10.0.0.3"));
// And try again. This time relay-info is there and should match.
selector.giaddr_ = IOAddress("10.0.0.1");
Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3, 125));
subnet1->allowClientClass("foo");
subnet2->setIface("lo");
- subnet2->setRelayInfo(IOAddress("10.0.0.1"));
+ subnet2->addRelayAddress(IOAddress("10.0.0.1"));
subnet3->setIface("eth1");
subnet3->requireClientClass("foo");
subnet3->requireClientClass("bar");
" \"comment\": \"foo\",\n"
" \"id\": 123,\n"
" \"subnet\": \"192.0.2.0/26\",\n"
- " \"relay\": { \"ip-address\": \"0.0.0.0\" },\n"
" \"match-client-id\": true,\n"
" \"next-server\": \"0.0.0.0\",\n"
" \"server-hostname\": \"\",\n"
" \"boot-file-name\": \"\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"valid-lifetime\": 3,\n"
" \"client-class\": \"foo\",\n"
" \"4o6-interface\": \"\",\n"
"},{\n"
" \"id\": 124,\n"
" \"subnet\": \"192.0.2.64/26\",\n"
- " \"relay\": { \"ip-address\": \"10.0.0.1\" },\n"
" \"interface\": \"lo\",\n"
" \"match-client-id\": true,\n"
" \"next-server\": \"0.0.0.0\",\n"
" \"boot-file-name\": \"\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ \"10.0.0.1\" ] },\n"
" \"valid-lifetime\": 3,\n"
" \"4o6-interface\": \"\",\n"
" \"4o6-interface-id\": \"\",\n"
"},{\n"
" \"id\": 125,\n"
" \"subnet\": \"192.0.2.128/26\",\n"
- " \"relay\": { \"ip-address\": \"0.0.0.0\" },\n"
" \"interface\": \"eth1\",\n"
" \"match-client-id\": true,\n"
" \"next-server\": \"0.0.0.0\",\n"
" \"boot-file-name\": \"\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"valid-lifetime\": 3,\n"
" \"4o6-interface\": \"\",\n"
" \"4o6-interface-id\": \"\",\n"
"{\n"
" \"id\": 123,\n"
" \"subnet\": \"192.0.2.0/24\",\n"
- " \"relay\": { \"ip-address\": \"0.0.0.0\" },\n"
" \"match-client-id\": true,\n"
" \"next-server\": \"0.0.0.0\",\n"
" \"server-hostname\": \"\",\n"
" \"boot-file-name\": \"\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"valid-lifetime\": 3,\n"
" \"4o6-interface\": \"\",\n"
" \"4o6-interface-id\": \"\",\n"
EXPECT_FALSE(cfg.selectSubnet(selector));
// Now specify relay information.
- subnet1->setRelayInfo(IOAddress("2001:db8:ff::1"));
- subnet2->setRelayInfo(IOAddress("2001:db8:ff::2"));
- subnet3->setRelayInfo(IOAddress("2001:db8:ff::3"));
+ subnet1->addRelayAddress(IOAddress("2001:db8:ff::1"));
+ subnet2->addRelayAddress(IOAddress("2001:db8:ff::2"));
+ subnet3->addRelayAddress(IOAddress("2001:db8:ff::3"));
// And try again. This time relay-info is there and should match.
selector.first_relay_linkaddr_ = IOAddress("2001:db8:ff::1");
subnet1->setInterfaceId(ifaceid);
subnet1->allowClientClass("foo");
subnet2->setIface("lo");
- subnet2->setRelayInfo(IOAddress("2001:db8:ff::2"));
+ subnet2->addRelayAddress(IOAddress("2001:db8:ff::2"));
subnet3->setIface("eth1");
subnet3->requireClientClass("foo");
subnet3->requireClientClass("bar");
" \"comment\": \"foo\",\n"
" \"id\": 123,\n"
" \"subnet\": \"2001:db8:1::/48\",\n"
- " \"relay\": { \"ip-address\": \"::\" },\n"
" \"interface-id\": \"relay.eth0\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"preferred-lifetime\": 3,\n"
" \"valid-lifetime\": 4,\n"
" \"rapid-commit\": false,\n"
"},{\n"
" \"id\": 124,\n"
" \"subnet\": \"2001:db8:2::/48\",\n"
- " \"relay\": { \"ip-address\": \"2001:db8:ff::2\" },\n"
" \"interface\": \"lo\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ \"2001:db8:ff::2\" ] },\n"
" \"preferred-lifetime\": 3,\n"
" \"valid-lifetime\": 4,\n"
" \"rapid-commit\": false,\n"
"},{\n"
" \"id\": 125,\n"
" \"subnet\": \"2001:db8:3::/48\",\n"
- " \"relay\": { \"ip-address\": \"::\" },\n"
" \"interface\": \"eth1\",\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"preferred-lifetime\": 3,\n"
" \"valid-lifetime\": 4,\n"
" \"rapid-commit\": false,\n"
"{\n"
" \"id\": 123,\n"
" \"subnet\": \"2001:db8:1::/48\",\n"
- " \"relay\": { \"ip-address\": \"::\" },\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"preferred-lifetime\": 3,\n"
" \"valid-lifetime\": 4,\n"
" \"rapid-commit\": false,\n"
"{\n"
" \"id\": 123,\n"
" \"subnet\": \"2001:db8:1::/48\",\n"
- " \"relay\": { \"ip-address\": \"::\" },\n"
" \"renew-timer\": 1,\n"
" \"rebind-timer\": 2,\n"
+ " \"relay\": { \"ip-addresses\": [ ] },\n"
" \"preferred-lifetime\": 3,\n"
" \"valid-lifetime\": 4,\n"
" \"rapid-commit\": false,\n"
" }";
ElementPtr json = Element::fromJSON(config_str);
- // We need to set the default ip-address to something.
- Network::RelayInfoPtr result(new Network::RelayInfo(asiolink::IOAddress("0.0.0.0")));
+ // Create an "empty" RelayInfo to hold the parsed result.
+ Network::RelayInfoPtr result(new Network::RelayInfo());
RelayInfoParser parser(Option::V4);
- // Subnet4 parser will pass 0.0.0.0 to the RelayInfoParser
EXPECT_NO_THROW(parser.parse(result, json));
- EXPECT_EQ("192.0.2.1", result->addr_.toText());
+ EXPECT_TRUE(result->containsAddress(IOAddress("192.0.2.1")));
}
/// @brief Checks that a bogus relay info structure for IPv4 is rejected.
" }";
ElementPtr json_bogus3 = Element::fromJSON(config_str_bogus3);
- // We need to set the default ip-address to something.
- Network::RelayInfoPtr result(new Network::RelayInfo(IOAddress::IPV4_ZERO_ADDRESS()));
+ // Create an "empty" RelayInfo to hold the parsed result.
+ Network::RelayInfoPtr result(new Network::RelayInfo());
RelayInfoParser parser(Option::V4);
" }";
ElementPtr json = Element::fromJSON(config_str);
- // We need to set the default ip-address to something.
- Network::RelayInfoPtr result(new Network::RelayInfo(asiolink::IOAddress("::")));
+ // Create an "empty" RelayInfo to hold the parsed result.
+ Network::RelayInfoPtr result(new Network::RelayInfo());
RelayInfoParser parser(Option::V6);
- // Subnet4 parser will pass :: to the RelayInfoParser
+
EXPECT_NO_THROW(parser.parse(result, json));
- EXPECT_EQ("2001:db8::1", result->addr_.toText());
+ EXPECT_TRUE(result->containsAddress(IOAddress("2001:db8::1")));
}
/// @brief Checks that a valid relay info structure for IPv6 can be handled
" }";
ElementPtr json_bogus3 = Element::fromJSON(config_str_bogus3);
- // We need to set the default ip-address to something.
- Network::RelayInfoPtr result(new Network::RelayInfo(asiolink::IOAddress("::")));
+ // Create an "empty" RelayInfo to hold the parsed result.
+ Network::RelayInfoPtr result(new Network::RelayInfo());
RelayInfoParser parser(Option::V6);
EXPECT_EQ(subnet3->getID(), preferred->getID());
}
+// This test verifies operations on the network's relay list
+TEST(SharedNetwork4Test, relayInfoList) {
+ SharedNetwork4Ptr network(new SharedNetwork4("frog"));
+
+ EXPECT_FALSE(network->hasRelays());
+ EXPECT_FALSE(network->hasRelayAddress(IOAddress("192.168.2.1")));
+
+ // Add relay addresses to the network.
+ network->addRelayAddress(IOAddress("192.168.2.1"));
+ network->addRelayAddress(IOAddress("192.168.2.2"));
+ network->addRelayAddress(IOAddress("192.168.2.3"));
+
+ // Verify we believe we have relays and we can match them accordingly.
+ EXPECT_TRUE(network->hasRelays());
+ EXPECT_TRUE(network->hasRelayAddress(IOAddress("192.168.2.1")));
+ EXPECT_TRUE(network->hasRelayAddress(IOAddress("192.168.2.2")));
+ EXPECT_TRUE(network->hasRelayAddress(IOAddress("192.168.2.3")));
+ EXPECT_FALSE(network->hasRelayAddress(IOAddress("192.168.2.4")));
+}
+
// This test verifies that unparsing shared network returns valid structure.
TEST(SharedNetwork4Test, unparse) {
SharedNetwork4Ptr network(new SharedNetwork4("frog"));
data::ElementPtr ctx = data::Element::fromJSON(uc);
network->setContext(ctx);
network->requireClientClass("foo");
+ network->addRelayAddress(IOAddress("192.168.2.1"));
// Add several subnets.
Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
SubnetID(1)));
+ subnet1->addRelayAddress(IOAddress("10.0.0.1"));
+ subnet1->addRelayAddress(IOAddress("10.0.0.2"));
+
Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), 24, 10, 20, 30,
SubnetID(2)));
network->add(subnet1);
" \"option-data\": [ ],\n"
" \"rebind-timer\": 150,\n"
" \"relay\": {\n"
- " \"ip-address\": \"0.0.0.0\"\n"
+ " \"ip-addresses\": [ \"192.168.2.1\" ]\n"
" },\n"
" \"renew-timer\": 100,\n"
" \"require-client-classes\": [ \"foo\" ],\n"
" \"pools\": [ ],\n"
" \"rebind-timer\": 20,\n"
" \"relay\": {\n"
- " \"ip-address\": \"0.0.0.0\"\n"
+ " \"ip-addresses\": [ \"10.0.0.1\", \"10.0.0.2\" ]\n"
" },\n"
" \"renew-timer\": 10,\n"
" \"reservation-mode\": \"all\",\n"
" \"pools\": [ ],\n"
" \"rebind-timer\": 20,\n"
" \"relay\": {\n"
- " \"ip-address\": \"0.0.0.0\"\n"
+ " \"ip-addresses\": [ ]\n"
" },\n"
" \"renew-timer\": 10,\n"
" \"reservation-mode\": \"all\",\n"
EXPECT_EQ(subnet3->getID(), preferred->getID());
}
+// This test verifies operations on the network's relay list
+TEST(SharedNetwork6Test, relayInfoList) {
+ SharedNetwork6Ptr network(new SharedNetwork6("frog"));
+
+ EXPECT_FALSE(network->hasRelays());
+ EXPECT_FALSE(network->hasRelayAddress(IOAddress("2001:db8:2::1")));
+
+ // Add realy addresses to the network.
+ network->addRelayAddress(IOAddress("2001:db8:2::1"));
+ network->addRelayAddress(IOAddress("2001:db8:2::2"));
+ network->addRelayAddress(IOAddress("2001:db8:2::3"));
+
+ // Verify we believe we have relays and we can match them accordingly.
+ EXPECT_TRUE(network->hasRelays());
+ EXPECT_TRUE(network->hasRelayAddress(IOAddress("2001:db8:2::1")));
+ EXPECT_TRUE(network->hasRelayAddress(IOAddress("2001:db8:2::2")));
+ EXPECT_TRUE(network->hasRelayAddress(IOAddress("2001:db8:2::3")));
+ EXPECT_FALSE(network->hasRelayAddress(IOAddress("2001:db8:2::4")));
+}
+
// This test verifies that unparsing shared network returns valid structure.
TEST(SharedNetwork6Test, unparse) {
SharedNetwork6Ptr network(new SharedNetwork6("frog"));
network->setContext(ctx);
network->requireClientClass("foo");
+ network->addRelayAddress(IOAddress("2001:db8:1::7"));
+ network->addRelayAddress(IOAddress("2001:db8:1::8"));
+
// Add several subnets.
Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 10, 20, 30,
40, SubnetID(1)));
Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 16, 10, 20, 30, 40,
SubnetID(2)));
+ subnet2->addRelayAddress(IOAddress("2001:db8:1::8"));
+
network->add(subnet1);
network->add(subnet2);
" \"rapid-commit\": true,\n"
" \"rebind-timer\": 150,\n"
" \"relay\": {\n"
- " \"ip-address\": \"::\"\n"
+ " \"ip-addresses\": [ \"2001:db8:1::7\", \"2001:db8:1::8\" ]\n"
" },\n"
" \"renew-timer\": 100,\n"
" \"require-client-classes\": [ \"foo\" ],\n"
" \"rapid-commit\": false,\n"
" \"rebind-timer\": 20,\n"
" \"relay\": {\n"
- " \"ip-address\": \"::\"\n"
+ " \"ip-addresses\": [ ]\n"
" },\n"
" \"renew-timer\": 10,\n"
" \"reservation-mode\": \"all\",\n"
" \"rapid-commit\": false,\n"
" \"rebind-timer\": 20,\n"
" \"relay\": {\n"
- " \"ip-address\": \"::\"\n"
+ " \"ip-addresses\": [ \"2001:db8:1::8\" ]\n"
" },\n"
" \"renew-timer\": 10,\n"
" \"reservation-mode\": \"all\",\n"
EXPECT_EQ(2000, subnet.getT2());
EXPECT_EQ(3000, subnet.getValid());
- EXPECT_EQ("0.0.0.0", subnet.getRelayInfo().addr_.toText());
+ EXPECT_FALSE(subnet.hasRelays());
EXPECT_FALSE(subnet.inRange(IOAddress("192.0.0.0")));
EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.0")));
EXPECT_FALSE(subnet.inRange(IOAddress("255.255.255.255")));
}
-// Checks whether the relay field has sane default and if it can
-// be changed, stored and retrieved
+// Checks whether the relay list is empty by default
+// and basic operations function
TEST(Subnet4Test, relay) {
Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
- EXPECT_EQ("0.0.0.0", subnet.getRelayInfo().addr_.toText());
+ // Should be empty.
+ EXPECT_FALSE(subnet.hasRelays());
+ EXPECT_EQ(0, subnet.getRelayAddresses().size());
- subnet.setRelayInfo(IOAddress("192.0.123.45"));
- EXPECT_EQ("192.0.123.45", subnet.getRelayInfo().addr_.toText());
+ // Matching should fail.
+ EXPECT_FALSE(subnet.hasRelayAddress(IOAddress("192.0.123.45")));
+
+ // Should be able to add them.
+ subnet.addRelayAddress(IOAddress("192.0.123.45"));
+ subnet.addRelayAddress(IOAddress("192.0.123.46"));
+
+ // Should not be empty.
+ EXPECT_TRUE(subnet.hasRelays());
+
+ // Should be two in the list.
+ EXPECT_EQ(2, subnet.getRelayAddresses().size());
+
+ // Should be able to match them if they are there.
+ EXPECT_TRUE(subnet.hasRelayAddress(IOAddress("192.0.123.45")));
+ EXPECT_TRUE(subnet.hasRelayAddress(IOAddress("192.0.123.46")));
+
+ // Should not match those that are not.
+ EXPECT_FALSE(subnet.hasRelayAddress(IOAddress("192.0.123.47")));
}
// Checks whether siaddr field can be set and retrieved correctly.
EXPECT_FALSE(subnet.inRange(IOAddress("::")));
}
-// Checks whether the relay field has sane default and if it can
-// be changed, stored and retrieved
+// Checks whether the relay list is empty by default
+// and basic operations function
TEST(Subnet6Test, relay) {
Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
- EXPECT_EQ("::", subnet.getRelayInfo().addr_.toText());
+ // Should be empty.
+ EXPECT_FALSE(subnet.hasRelays());
+ EXPECT_EQ(0, subnet.getRelayAddresses().size());
+
+ // Matching should fail.
+ EXPECT_FALSE(subnet.hasRelayAddress(IOAddress("2001:ffff::45")));
+
+ // Should be able to add them.
+ subnet.addRelayAddress(IOAddress("2001:ffff::45"));
+ subnet.addRelayAddress(IOAddress("2001:ffff::46"));
+
+ // Should not be empty.
+ EXPECT_TRUE(subnet.hasRelays());
+
+ // Should be two in the list.
+ EXPECT_EQ(2, subnet.getRelayAddresses().size());
- subnet.setRelayInfo(IOAddress("2001:ffff::1"));
+ // Should be able to match them if they are there.
+ EXPECT_TRUE(subnet.hasRelayAddress(IOAddress("2001:ffff::45")));
+ EXPECT_TRUE(subnet.hasRelayAddress(IOAddress("2001:ffff::46")));
- EXPECT_EQ("2001:ffff::1", subnet.getRelayInfo().addr_.toText());
+ // Should not match those that are not.
+ EXPECT_FALSE(subnet.hasRelayAddress(IOAddress("2001:ffff::47")));
}
// Test checks whether the number of addresses available in the pools are