Commit 94280840 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[master] Merge branch 'trac4303'

parents a0477d9f 97f5350c
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <dhcpsrv/addr_utilities.h> #include <dhcpsrv/addr_utilities.h>
#include <dhcpsrv/callout_handle_store.h> #include <dhcpsrv/callout_handle_store.h>
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/cfg_host_operations.h>
#include <dhcpsrv/cfg_subnets4.h> #include <dhcpsrv/cfg_subnets4.h>
#include <dhcpsrv/lease_mgr.h> #include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/lease_mgr_factory.h> #include <dhcpsrv/lease_mgr_factory.h>
...@@ -137,9 +138,17 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine, ...@@ -137,9 +138,17 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
.arg(query->getLabel()) .arg(query->getLabel())
.arg(subnet->getID()); .arg(subnet->getID());
} }
// Find static reservations if not disabled for our subnet.
if (subnet->getHostReservationMode() != Subnet::HR_DISABLED) {
// Before we can check for static reservations, we need to prepare a set
// of identifiers to be used for this.
setHostIdentifiers();
// Check for static reservations.
alloc_engine->findReservation(*context_);
}
} }
// Check for static reservations.
alloc_engine->findReservation(*context_);
}; };
void void
...@@ -232,6 +241,60 @@ Dhcpv4Exchange::copyDefaultOptions() { ...@@ -232,6 +241,60 @@ Dhcpv4Exchange::copyDefaultOptions() {
} }
} }
void
Dhcpv4Exchange::setHostIdentifiers() {
const ConstCfgHostOperationsPtr cfg =
CfgMgr::instance().getCurrentCfg()->getCfgHostOperations4();
// Collect host identifiers. The identifiers are stored in order of preference.
// The server will use them in that order to search for host reservations.
BOOST_FOREACH(const Host::IdentifierType& id_type,
cfg->getIdentifierTypes()) {
switch (id_type) {
case Host::IDENT_HWADDR:
if (context_->hwaddr_ && !context_->hwaddr_->hwaddr_.empty()) {
context_->addHostIdentifier(id_type, context_->hwaddr_->hwaddr_);
}
break;
case Host::IDENT_DUID:
if (context_->clientid_) {
const std::vector<uint8_t>& vec = context_->clientid_->getDuid();
if (!vec.empty()) {
// Client identifier type = DUID? Client identifier holding a DUID
// comprises Type (1 byte), IAID (4 bytes), followed by the actual
// DUID. Thus, the minimal length is 6.
if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) {
// Extract DUID, skip IAID.
context_->addHostIdentifier(id_type,
std::vector<uint8_t>(vec.begin() + 5,
vec.end()));
}
/// @todo Add support for other client identifiers (see #4317).
}
}
break;
case Host::IDENT_CIRCUIT_ID:
{
OptionPtr rai = query_->getOption(DHO_DHCP_AGENT_OPTIONS);
if (rai) {
OptionPtr circuit_id_opt = rai->getOption(RAI_OPTION_AGENT_CIRCUIT_ID);
if (circuit_id_opt) {
const OptionBuffer& circuit_id_vec = circuit_id_opt->getData();
if (!circuit_id_vec.empty()) {
context_->addHostIdentifier(id_type, circuit_id_vec);
}
}
}
}
break;
default:
;
}
}
}
const std::string Dhcpv4Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_"); const std::string Dhcpv4Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const bool use_bcast, Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const bool use_bcast,
......
...@@ -137,6 +137,14 @@ private: ...@@ -137,6 +137,14 @@ private:
/// not NULL. /// not NULL.
void copyDefaultOptions(); void copyDefaultOptions();
/// @brief Set host identifiers within a context.
///
/// This method sets an ordered list of host identifier types and
/// values which the server should use to find host reservations.
/// The order of the set is determined by the configuration parameter,
/// host-reservation-identifiers
void setHostIdentifiers();
/// @brief Pointer to the allocation engine used by the server. /// @brief Pointer to the allocation engine used by the server.
AllocEnginePtr alloc_engine_; AllocEnginePtr alloc_engine_;
/// @brief Pointer to the DHCPv4 message sent by the client. /// @brief Pointer to the DHCPv4 message sent by the client.
......
...@@ -448,6 +448,8 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id, ...@@ -448,6 +448,8 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
parser = new ExpirationConfigParser(); parser = new ExpirationConfigParser();
} else if (config_id.compare("client-classes") == 0) { } else if (config_id.compare("client-classes") == 0) {
parser = new ClientClassDefListParser(config_id, globalContext()); parser = new ClientClassDefListParser(config_id, globalContext());
} else if (config_id.compare("host-reservation-identifiers") == 0) {
parser = new HostReservationIdsParser4();
} else { } else {
isc_throw(DhcpConfigError, isc_throw(DhcpConfigError,
"unsupported global configuration parameter: " "unsupported global configuration parameter: "
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
...@@ -49,7 +49,8 @@ Dhcp4Client::Dhcp4Client(const Dhcp4Client::State& state) : ...@@ -49,7 +49,8 @@ Dhcp4Client::Dhcp4Client(const Dhcp4Client::State& state) :
server_facing_relay_addr_("10.0.0.2"), server_facing_relay_addr_("10.0.0.2"),
srv_(boost::shared_ptr<NakedDhcpv4Srv>(new NakedDhcpv4Srv(0))), srv_(boost::shared_ptr<NakedDhcpv4Srv>(new NakedDhcpv4Srv(0))),
state_(state), state_(state),
use_relay_(false) { use_relay_(false),
circuit_id_() {
} }
Dhcp4Client::Dhcp4Client(boost::shared_ptr<NakedDhcpv4Srv> srv, Dhcp4Client::Dhcp4Client(boost::shared_ptr<NakedDhcpv4Srv> srv,
...@@ -67,7 +68,8 @@ Dhcp4Client::Dhcp4Client(boost::shared_ptr<NakedDhcpv4Srv> srv, ...@@ -67,7 +68,8 @@ Dhcp4Client::Dhcp4Client(boost::shared_ptr<NakedDhcpv4Srv> srv,
server_facing_relay_addr_("10.0.0.2"), server_facing_relay_addr_("10.0.0.2"),
srv_(srv), srv_(srv),
state_(state), state_(state),
use_relay_(false) { use_relay_(false),
circuit_id_() {
} }
void void
...@@ -468,6 +470,15 @@ Dhcp4Client::sendMsg(const Pkt4Ptr& msg) { ...@@ -468,6 +470,15 @@ Dhcp4Client::sendMsg(const Pkt4Ptr& msg) {
msg->setHops(1); msg->setHops(1);
msg->setGiaddr(relay_addr_); msg->setGiaddr(relay_addr_);
msg->setLocalAddr(server_facing_relay_addr_); msg->setLocalAddr(server_facing_relay_addr_);
// Insert RAI
OptionPtr rai(new Option(Option::V4, DHO_DHCP_AGENT_OPTIONS));
// Insert circuit id, if specified.
if (!circuit_id_.empty()) {
rai->addOption(OptionPtr(new Option(Option::V4, RAI_OPTION_AGENT_CIRCUIT_ID,
OptionBuffer(circuit_id_.begin(),
circuit_id_.end()))));
}
msg->addOption(rai);
} }
// Repack the message to simulate wire-data parsing. // Repack the message to simulate wire-data parsing.
msg->pack(); msg->pack();
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
...@@ -284,6 +284,14 @@ public: ...@@ -284,6 +284,14 @@ public:
const uint8_t option2 = 0, const uint8_t option2 = 0,
const uint8_t option3 = 0); const uint8_t option3 = 0);
/// @brief Sets circuit-id value to be included in the circuit-id
/// sub option of the RAI option.
///
/// @param circuit_id New circuit-id value.
void setCircuitId(const std::string& circuit_id) {
circuit_id_ = circuit_id;
}
/// @brief Sets destination address for the messages being sent by the /// @brief Sets destination address for the messages being sent by the
/// client. /// client.
/// ///
...@@ -468,6 +476,10 @@ private: ...@@ -468,6 +476,10 @@ private:
/// @brief Enable relaying messages to the server. /// @brief Enable relaying messages to the server.
bool use_relay_; bool use_relay_;
/// @brief Specifies value to be inserted into circuit-id sub option
/// of the RAI option.
std::string circuit_id_;
/// @brief Extra options the client will send. /// @brief Extra options the client will send.
OptionCollection extra_options_; OptionCollection extra_options_;
}; };
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
...@@ -57,6 +57,11 @@ namespace { ...@@ -57,6 +57,11 @@ namespace {
/// - 1 pool: 10.0.0.10-10.0.0.100 /// - 1 pool: 10.0.0.10-10.0.0.100
/// - match-client-id flag is set to false, thus the server /// - match-client-id flag is set to false, thus the server
/// uses HW address for lease lookup, rather than client id /// uses HW address for lease lookup, rather than client id
///
/// - Configuration 4:
/// - The same as configuration 2, but using different values in
/// 'host-reservation-identifiers'
///
const char* DORA_CONFIGS[] = { const char* DORA_CONFIGS[] = {
// Configuration 0 // Configuration 0
"{ \"interfaces-config\": {" "{ \"interfaces-config\": {"
...@@ -125,6 +130,14 @@ const char* DORA_CONFIGS[] = { ...@@ -125,6 +130,14 @@ const char* DORA_CONFIGS[] = {
" {" " {"
" \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," " \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
" \"ip-address\": \"10.0.0.7\"" " \"ip-address\": \"10.0.0.7\""
" },"
" {"
" \"duid\": \"01:02:03:04:05\","
" \"ip-address\": \"10.0.0.8\""
" },"
" {"
" \"circuit-id\": \"'charter950'\","
" \"ip-address\": \"10.0.0.9\""
" }" " }"
" ]" " ]"
"} ]" "} ]"
...@@ -146,6 +159,32 @@ const char* DORA_CONFIGS[] = { ...@@ -146,6 +159,32 @@ const char* DORA_CONFIGS[] = {
" } ]" " } ]"
" } ]" " } ]"
"}", "}",
// Configuration 4
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"host-reservation-identifiers\": [ \"circuit-id\", \"hw-address\" ],"
"\"valid-lifetime\": 600,"
"\"subnet4\": [ { "
" \"subnet\": \"10.0.0.0/24\", "
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
" \"reservations\": [ "
" {"
" \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
" \"ip-address\": \"10.0.0.7\""
" },"
" {"
" \"duid\": \"01:02:03:04:05\","
" \"ip-address\": \"10.0.0.8\""
" },"
" {"
" \"circuit-id\": \"'charter950'\","
" \"ip-address\": \"10.0.0.9\""
" }"
" ]"
"} ]"
"}"
}; };
/// @brief Test fixture class for testing 4-way (DORA) exchanges. /// @brief Test fixture class for testing 4-way (DORA) exchanges.
...@@ -688,6 +727,71 @@ TEST_F(DORATest, reservation) { ...@@ -688,6 +727,71 @@ TEST_F(DORATest, reservation) {
ASSERT_TRUE(subnet->inPool(Lease::TYPE_V4, clientB.config_.lease_.addr_)); ASSERT_TRUE(subnet->inPool(Lease::TYPE_V4, clientB.config_.lease_.addr_));
} }
// This test checks that it is possible to make a reservation by
// circuit-id inserted by the relay agent.
TEST_F(DORATest, reservationByCircuitId) {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Use relay agent so as the circuit-id can be inserted.
client.useRelay(true, IOAddress("10.0.0.1"), IOAddress("10.0.0.2"));
// Specify circuit-id.
client.setCircuitId("charter950");
// Configure DHCP server.
configure(DORA_CONFIGS[2], *client.getServer());
// Client A performs 4-way exchange and should obtain a reserved
// address.
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
IOAddress>(new IOAddress("0.0.0.0"))));
// Make sure that the server responded.
ASSERT_TRUE(client.getContext().response_);
Pkt4Ptr resp = client.getContext().response_;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
// Make sure that the client has got the lease for the reserved address.
ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText());
}
// This test verifies that order in which host identifiers are used to
// retrieve host reservations can be controlled.
TEST_F(DORATest, hostIdentifiersOrder) {
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setHWAddress("aa:bb:cc:dd:ee:ff");
// Use relay agent so as the circuit-id can be inserted.
client.useRelay(true, IOAddress("10.0.0.1"), IOAddress("10.0.0.2"));
// Specify circuit-id.
client.setCircuitId("charter950");
// Configure DHCP server.
configure(DORA_CONFIGS[2], *client.getServer());
// Perform 4-way exchange to obtain reserved address.
// The client has in fact two reserved addresses, but the one assigned
// should be by hw-address.
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
IOAddress>(new IOAddress("0.0.0.0"))));
// Make sure that the server responded.
ASSERT_TRUE(client.getContext().response_);
Pkt4Ptr resp = client.getContext().response_;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
// Make sure that the client has got the lease for the reserved address.
ASSERT_EQ("10.0.0.7", client.config_.lease_.addr_.toText());
// Reconfigure the server to change the preference order of the
// host identifiers. The 'circuit-id' should now take precedence over
// the hw-address.
configure(DORA_CONFIGS[4], *client.getServer());
ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
IOAddress>(new IOAddress("0.0.0.0"))));
// Make sure that the server responded.
ASSERT_TRUE(client.getContext().response_);
resp = client.getContext().response_;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
// Make sure that the client has got the lease for the reserved address.
ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText());
}
// This test checks that setting the match-client-id value to false causes // This test checks that setting the match-client-id value to false causes
// the server to ignore changing client identifier when the client is // the server to ignore changing client identifier when the client is
// using consistent HW address. // using consistent HW address.
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <dhcp6/dhcp6_log.h> #include <dhcp6/dhcp6_log.h>
#include <dhcp6/dhcp6_srv.h> #include <dhcp6/dhcp6_srv.h>
#include <dhcpsrv/callout_handle_store.h> #include <dhcpsrv/callout_handle_store.h>
#include <dhcpsrv/cfg_host_operations.h>
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease_mgr.h> #include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/lease_mgr_factory.h> #include <dhcpsrv/lease_mgr_factory.h>
...@@ -276,10 +277,40 @@ AllocEngine::ClientContext6 ...@@ -276,10 +277,40 @@ AllocEngine::ClientContext6
Dhcpv6Srv::createContext(const Pkt6Ptr& pkt) { Dhcpv6Srv::createContext(const Pkt6Ptr& pkt) {
AllocEngine::ClientContext6 ctx; AllocEngine::ClientContext6 ctx;
ctx.subnet_ = selectSubnet(pkt); ctx.subnet_ = selectSubnet(pkt);
ctx.query_ = pkt;
ctx.duid_ = pkt->getClientId(); ctx.duid_ = pkt->getClientId();
ctx.hwaddr_ = getMAC(pkt); ctx.hwaddr_ = getMAC(pkt);
ctx.query_ = pkt;
alloc_engine_->findReservation(ctx); // Collect host identifiers if host reservations enabled. The identifiers
// are stored in order of preference. The server will use them in that
// order to search for host reservations.
if (ctx.subnet_ &&
(ctx.subnet_->getHostReservationMode() != Subnet::HR_DISABLED)) {
const ConstCfgHostOperationsPtr cfg =
CfgMgr::instance().getCurrentCfg()->getCfgHostOperations6();
BOOST_FOREACH(const Host::IdentifierType& id_type,
cfg->getIdentifierTypes()) {
switch (id_type) {
case Host::IDENT_DUID:
if (ctx.duid_) {
ctx.addHostIdentifier(id_type, ctx.duid_->getDuid());
}
break;
case Host::IDENT_HWADDR:
if (ctx.hwaddr_) {
ctx.addHostIdentifier(id_type, ctx.hwaddr_->hwaddr_);
}
break;
default:
;
}
}
// Find host reservations using specified identifiers.
alloc_engine_->findReservation(ctx);
}
return (ctx); return (ctx);
} }
...@@ -1321,6 +1352,7 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, ...@@ -1321,6 +1352,7 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
ctx.hwaddr_ = orig_ctx.hwaddr_; ctx.hwaddr_ = orig_ctx.hwaddr_;
ctx.host_ = orig_ctx.host_; ctx.host_ = orig_ctx.host_;
ctx.query_ = orig_ctx.query_; ctx.query_ = orig_ctx.query_;
ctx.host_identifiers_ = orig_ctx.host_identifiers_;
Lease6Collection leases = alloc_engine_->allocateLeases6(ctx); Lease6Collection leases = alloc_engine_->allocateLeases6(ctx);
...@@ -1442,6 +1474,7 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer, ...@@ -1442,6 +1474,7 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
ctx.hwaddr_ = orig_ctx.hwaddr_; ctx.hwaddr_ = orig_ctx.hwaddr_;
ctx.host_ = orig_ctx.host_; ctx.host_ = orig_ctx.host_;
ctx.query_ = orig_ctx.query_; ctx.query_ = orig_ctx.query_;
ctx.host_identifiers_ = orig_ctx.host_identifiers_;
Lease6Collection leases = alloc_engine_->allocateLeases6(ctx); Lease6Collection leases = alloc_engine_->allocateLeases6(ctx);
......
...@@ -702,6 +702,8 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id, ...@@ -702,6 +702,8 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
parser = new ClientClassDefListParser(config_id, globalContext()); parser = new ClientClassDefListParser(config_id, globalContext());
} else if (config_id.compare("server-id") == 0) { } else if (config_id.compare("server-id") == 0) {
parser = new DUIDConfigParser(); parser = new DUIDConfigParser();
} else if (config_id.compare("host-reservation-identifiers") == 0) {
parser = new HostReservationIdsParser6();
} else { } else {
isc_throw(DhcpConfigError, isc_throw(DhcpConfigError,
"unsupported global configuration parameter: " "unsupported global configuration parameter: "
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
...@@ -412,6 +412,13 @@ public: ...@@ -412,6 +412,13 @@ public:
iface_name_ = iface_name; iface_name_ = iface_name;
} }
/// @brief Sets link local address used by the client.
///
/// @param link_local New link local address.
void setLinkLocal(const asiolink::IOAddress& link_local) {
link_local_ = link_local;
}
/// @brief Set an address hint to be sent to a server. /// @brief Set an address hint to be sent to a server.
/// ///
/// @param pref_lft Preferred lifetime. /// @param pref_lft Preferred lifetime.
......
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h> #include <config.h>
#include <asiolink/io_address.h>
#include <dhcp/tests/iface_mgr_test_config.h> #include <dhcp/tests/iface_mgr_test_config.h>
#include <dhcp6/tests/dhcp6_test_utils.h> #include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp6/tests/dhcp6_client.h> #include <dhcp6/tests/dhcp6_client.h>
using namespace isc; using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp; using namespace isc::dhcp;
using namespace isc::dhcp::test; using namespace isc::dhcp::test;
...@@ -19,6 +21,11 @@ namespace { ...@@ -19,6 +21,11 @@ namespace {
/// ///
/// - Configuration 0: /// - Configuration 0:
/// Single subnet with two reservations, one with a hostname, one without /// Single subnet with two reservations, one with a hostname, one without
/// - Configuration 1:
/// Multiple reservations using different host identifiers.
/// - Configuration 2:
/// Same as configuration 1 but 'host-reservation-identifiers' specified
/// in non-default order.
const char* CONFIGS[] = { const char* CONFIGS[] = {
// Configuration 0: // Configuration 0:
"{ " "{ "
...@@ -45,6 +52,61 @@ const char* CONFIGS[] = { ...@@ -45,6 +52,61 @@ const char* CONFIGS[] = {
" \"ip-addresses\": [ \"2001:db8:1:1::babf\" ]" " \"ip-addresses\": [ \"2001:db8:1:1::babf\" ]"
" } ]" " } ]"
" } ]" " } ]"
"}",
// Configuration 1:
"{ "
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 4000, "
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"mac-sources\": [ \"ipv6-link-local\" ], "
"\"subnet6\": [ "
" { "
" \"subnet\": \"2001:db8:1::/48\", "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"interface\" : \"eth0\" , "
" \"reservations\": ["
" {"
" \"hw-address\": \"38:60:77:d5:ff:ee\","
" \"ip-addresses\": [ \"2001:db8:1::1\" ]"
" },"
" {"
" \"duid\": \"01:02:03:05\","
" \"ip-addresses\": [ \"2001:db8:1::2\" ]"
" } ]"
" } ]"
"}",
// Configuration 2:
"{ "
"\"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"