Commit b55dd296 authored by Marcin Siodelski's avatar Marcin Siodelski

[3705] Address review comments.

parent e09a9fe7
......@@ -885,6 +885,9 @@ temporarily override a list of interface names and listen on all interfaces.
<row><entry>clt-time</entry><entry>46</entry><entry>uint32</entry><entry>false</entry></row>
<row><entry>lq-relay-data</entry><entry>47</entry><entry>record</entry><entry>false</entry></row>
<row><entry>lq-client-link</entry><entry>48</entry><entry>ipv6-address</entry><entry>true</entry></row>
<row><entry>erp-local-domain-name</entry><entry>65</entry><entry>fqdn</entry><entry>false</entry></row>
<row><entry>rsoo</entry><entry>66</entry><entry>empty</entry><entry>false</entry></row>
<row><entry>client-linklayer-addr</entry><entry>79</entry><entry>binary</entry><entry>false</entry></row>
</tbody>
</tgroup>
</table>
......@@ -1371,7 +1374,7 @@ should include options from the isc option space:
<section id="dhcp6-rsoo">
<title>Relay-Supplied Options</title>
<para><ulink url="http://tools.ietf.org/html/rfc6422">RFC 6422</ulink>
defines a mechanism called Relay supplied options. In certain cases relay
defines a mechanism called Relay-Supplied DHCP Options. In certain cases relay
agents are the only entities that may have specific information. They can
insert options when relaying messages from the client to the server. The
server will then do certain checks and copy those options to the response
......@@ -1381,11 +1384,11 @@ should include options from the isc option space:
included. First, the server must not provide the option by itself. In
other words, if both relay and server provide an option, the server always
takes precedence. Second, the option must be RSOO-enabled. IANA mantains a
list of RSOO-enabled options here: <ulink url="http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#options-relay-supplied">List of RSOO-enabled options</ulink>.
However, there may cases when system administrators want to echo other
list of RSOO-enabled options <ulink url="http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#options-relay-supplied">here</ulink>.
However, there may be cases when system administrators want to echo other
options. Kea can be instructed to treat other options as RSOO-enabled.
For example, to mark options 110, 120 and 130 as RSOO-enabled, the following
syntax may be used:
syntax should be used:
<screen>
"Dhcp6": {
<userinput>"relay-supplied-options": [ "110", "120", "130" ],</userinput>
......
......@@ -2739,39 +2739,28 @@ void Dhcpv6Srv::processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp) {
return;
}
// Get the global options info. We'll use it to check whether an
// option is RSOO-enabled or not.
ConstCfgOptionPtr global_opts = CfgMgr::instance().getCurrentCfg()->
getCfgOption();
// Get RSOO configuration.
ConstCfgRSOOPtr cfg_rsoo = CfgMgr::instance().getCurrentCfg()->getCfgRSOO();
// Let's get over all relays (encapsulation levels). We need to do
// it in the same order as the client packet traversed the relays.
for (int i = query->relay_info_.size(); i > 0 ; --i) {
OptionPtr rsoo_container = query->getRelayOption(D6O_RSOO, i - 1);
if (!rsoo_container) {
// No relay-supplied options by this relay? Ok, carry on.
continue;
}
// There are RSOO options. Let's get through them one by one
// and if it's RSOO-enabled and there's no such option provided yet,
// copy it to the server's response
const OptionCollection& rsoo = rsoo_container->getOptions();
for (OptionCollection::const_iterator opt = rsoo.begin(); opt != rsoo.end();
++opt) {
if (!global_opts->isRSOOEnabled(opt->second->getType())) {
// We didn't copy this option, because it's not RSOO-enabled.
continue;
}
if (rsp->getOption(opt->second->getType())) {
// There is such an option in the server's response already,
// we'll skip relay's option
continue;
if (rsoo_container) {
// There are RSOO options. Let's get through them one by one
// and if it's RSOO-enabled and there's no such option provided yet,
// copy it to the server's response
const OptionCollection& rsoo = rsoo_container->getOptions();
for (OptionCollection::const_iterator opt = rsoo.begin();
opt != rsoo.end(); ++opt) {
// Echo option if it is RSOO enabled option and there is no such
// option added yet.
if (cfg_rsoo->enabled(opt->second->getType()) &&
!rsp->getOption(opt->second->getType())) {
rsp->addOption(opt->second);
}
}
// All checks went ok, let's add this option.
rsp->addOption(opt->second);
}
}
}
......
......@@ -41,6 +41,7 @@
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <limits>
#include <map>
#include <vector>
......@@ -575,10 +576,14 @@ public:
ParserCollection subnets_;
};
/// @brief parser for list of RSOO options
/// @brief Parser for list of RSOO options
///
/// This parser handles Dhcp6/relay-supplied-options entry.
/// It contains a list of option codes.
/// This parser handles Dhcp6/relay-supplied-options entry. It contains a
/// list of RSOO-enabled options which should be sent back to the client.
///
/// The option on this list can be specified using an option code or option
/// name. Therefore, the values on the list should always be enclosed in
/// "quotes".
class RSOOListConfigParser : public DhcpConfigParser {
public:
......@@ -603,34 +608,47 @@ public:
///
/// @param value pointer to the content of parsed values
virtual void build(isc::data::ConstElementPtr value) {
try {
BOOST_FOREACH(ConstElementPtr source_elem, value->listValue()) {
std::string option_str = source_elem->stringValue();
// This option can be either code (integer) or name. Let's try code first
int64_t code = 0;
try {
code = boost::lexical_cast<int64_t>(option_str);
// Protect against the negative value and too high value.
if (code < 0) {
isc_throw(BadValue, "invalid option code value specified '"
<< option_str << "', the option code must be a"
" non-negative value");
} else if (code > std::numeric_limits<uint16_t>::max()) {
isc_throw(BadValue, "invalid option code value specified '"
<< option_str << "', the option code must not be"
" greater than '" << std::numeric_limits<uint16_t>::max()
<< "'");
}
} catch (const boost::bad_lexical_cast &) {
// Oh well, it's not a number
}
// By default, there's only one RSOO option defined: 65
// http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml
CfgMgr::instance().getStagingCfg()->getCfgOption()->clearRSOO();
CfgMgr::instance().getStagingCfg()->getCfgOption()->addRSOO(D6O_ERP_LOCAL_DOMAIN_NAME);
BOOST_FOREACH(ConstElementPtr source_elem, value->listValue()) {
std::string option_str = source_elem->stringValue();
// This option can be either code (integer) or name. Let's try code first
uint16_t code = 0;
try {
code = boost::lexical_cast<uint16_t>(option_str);
} catch (const boost::bad_lexical_cast &) {
// Oh well, it's not a number
}
if (!code) {
OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, option_str);
if (def) {
code = def->getCode();
} else {
isc_throw(BadValue, "Unable to convert '" << option_str
<< "' to option code while parsing allowed"
<< "relay-supplied-options");
if (!code) {
OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, option_str);
if (def) {
code = def->getCode();
} else {
isc_throw(BadValue, "unable to find option code for the "
" specified option name '" << option_str << "'"
" while parsing the list of enabled"
" relay-supplied-options");
}
}
CfgMgr::instance().getStagingCfg()->getCfgRSOO()->enable(code);
}
CfgMgr::instance().getStagingCfg()->getCfgOption()->addRSOO(code);
} catch (const std::exception& ex) {
// Rethrow exception with the appended position of the parsed
// element.
isc_throw(DhcpConfigError, ex.what() << " (" << value->getPosition() << ")");
}
}
......
......@@ -3798,18 +3798,18 @@ TEST_F(Dhcp6ParserTest, rsooNumbers) {
checkResult(status, 0);
// The following codes should be enabled now
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(10));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(20));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(30));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()->enabled(10));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()->enabled(20));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()->enabled(30));
// This option is on the IANA list, so it should be allowed all the time
// (http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml)
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(D6O_ERP_LOCAL_DOMAIN_NAME));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(D6O_ERP_LOCAL_DOMAIN_NAME));
// Those options are not enabled
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(25));
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(1));
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()->enabled(25));
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()->enabled(1));
}
/// The goal of this test is to verify that configuration can include
......@@ -3831,39 +3831,68 @@ TEST_F(Dhcp6ParserTest, rsooNames) {
checkResult(status, 0);
for (uint16_t code = 0; code < D6O_NAME_SERVERS; ++code) {
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(code)) << " for option code " << code;
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(code)) << " for option code " << code;
}
// The following codes should be enabled now
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(D6O_NAME_SERVERS));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(D6O_NAME_SERVERS));
for (uint16_t code = D6O_NAME_SERVERS + 1; code < D6O_REMOTE_ID; ++code) {
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(code)) << " for option code " << code;
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(code)) << " for option code " << code;
}
// Check remote-id. It should be enabled.
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(D6O_REMOTE_ID));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(D6O_REMOTE_ID));
for (uint16_t code = D6O_REMOTE_ID + 1; code < D6O_ERP_LOCAL_DOMAIN_NAME; ++code) {
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(code)) << " for option code " << code;
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(code)) << " for option code " << code;
}
// This option is on the IANA list, so it should be allowed all the time
// (http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml)
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(D6O_ERP_LOCAL_DOMAIN_NAME));
EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(D6O_ERP_LOCAL_DOMAIN_NAME));
for (uint16_t code = D6O_ERP_LOCAL_DOMAIN_NAME + 1; code < 300; ++code) {
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
->isRSOOEnabled(code)) << " for option code " << code;
EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgRSOO()
->enabled(code)) << " for option code " << code;
}
}
TEST_F(Dhcp6ParserTest, rsooNegativeNumber) {
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
Element::fromJSON("{ " + genIfaceConfig() + ","
"\"relay-supplied-options\": [ \"80\", \"-2\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ ], "
"\"valid-lifetime\": 4000 }")));
// returned value should be 0 (success)
checkResult(status, 1);
EXPECT_TRUE(errorContainsPosition(status, "<string>"));
}
TEST_F(Dhcp6ParserTest, rsooBogusName) {
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
Element::fromJSON("{ " + genIfaceConfig() + ","
"\"relay-supplied-options\": [ \"bogus\", \"dns-servers\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ ], "
"\"valid-lifetime\": 4000 }")));
// returned value should be 0 (success)
checkResult(status, 1);
EXPECT_TRUE(errorContainsPosition(status, "<string>"));
}
};
......@@ -110,6 +110,21 @@ public:
status_code_ = 0;
received_status_code_ = false;
}
/// @brief Finds an option with the specific code in the received
/// configuration.
///
/// @param code Option code.
///
/// @return Pointer to the option if the option exists, or NULL if
/// the option doesn't exist.
OptionPtr findOption(const uint16_t code) const {
std::multimap<unsigned int, OptionPtr>::const_iterator it = options_.find(code);
if (it != options_.end()) {
return (it->second);
}
return (OptionPtr());
}
};
/// @brief Holds the DHCPv6 messages taking part in transaction between
......
......@@ -2277,6 +2277,80 @@ TEST_F(Dhcpv6SrvTest, rsoo2relays) {
EXPECT_EQ(expected, opt120->getData());
}
// This test verifies that the server will send the option for which it
// has a candidate, rather than the option sent by the relay in the RSOO.
TEST_F(Dhcpv6SrvTest, rsooOverride) {
Dhcp6Client client;
// The client will be requesting specific options.
client.useORO(true);
// The following configuration enables RSOO options: 110 and 120.
// It also configures the server with option 120 which should
// "override" the option 120 sent in the RSOO by the relay.
string config =
"{"
" \"relay-supplied-options\": [ \"110\", \"120\" ],"
" \"option-def\": [ {"
" \"name\": \"foo\","
" \"code\": 120,"
" \"type\": \"binary\","
" \"array\": False,"
" \"record-types\": \"\","
" \"space\": \"dhcp6\","
" \"encapsulate\": \"\""
" } ],"
" \"option-data\": [ {"
" \"code\": 120,"
" \"data\": \"05\""
" } ],"
" \"preferred-lifetime\": 3000,"
" \"rebind-timer\": 2000, "
" \"renew-timer\": 1000, "
" \"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
" \"subnet\": \"2001:db8::/48\" "
" } ],"
" \"valid-lifetime\": 4000"
"}";
EXPECT_NO_THROW(configure(config, *client.getServer()));
// Fabricate the relay.
Pkt6::RelayInfo relay;
relay.msg_type_ = DHCPV6_RELAY_FORW;
relay.hop_count_ = 1;
relay.linkaddr_ = IOAddress("2001:db8::1");
relay.peeraddr_ = IOAddress("fe80::1");
vector<uint16_t> rsoo;
// The relay will send 2 options: 110, 120
rsoo.push_back(110);
rsoo.push_back(120);
// Use 0x1 as payload
OptionPtr opt = createRSOO(rsoo, 1);
relay.options_.insert(make_pair(opt->getType(), opt));
client.relay_info_.push_back(relay);
// Client should request option 120 in the ORO so as the server
// sends the configured option 120 to the client.
client.requestOption(120);
client.doSARR();
// The option 110 should be the one injected by the relay.
opt = client.config_.findOption(110);
ASSERT_TRUE(opt);
// We check that this is the option injected by the relay by
// checking option length. It should has 10 bytes long payload.
ASSERT_EQ(10, opt->getData().size());
// The second option should be the one configured on the server,
// rather than the one injected by the relay.
opt = client.config_.findOption(120);
ASSERT_TRUE(opt);
// It should have the size of 1.
ASSERT_EQ(1, opt->getData().size());
}
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
/// to call processX() methods.
......
......@@ -327,7 +327,7 @@ const OptionDefParams OPTION_DEF_PARAMS6[] = {
RECORD_DEF(LQ_RELAY_DATA_RECORDS), "" },
{ "lq-client-link", D6O_LQ_CLIENT_LINK, OPT_IPV6_ADDRESS_TYPE, true,
NO_RECORD_DEF, "" },
{ "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "dhcp4" },
{ "rsoo", D6O_RSOO, OPT_EMPTY_TYPE, false, NO_RECORD_DEF, "rsoo-opts" },
{ "client-linklayer-addr", D6O_CLIENT_LINKLAYER_ADDR, OPT_BINARY_TYPE, false,
NO_RECORD_DEF, "" }
......
......@@ -351,6 +351,7 @@ Pkt6Ptr isc::test::PktCaptures::captureCableLabsShortVendorClass() {
/// - rsoo (66)
/// - option 255 (len 4)
/// - option 256 (len 9)
/// - remote-id option (37)
/// - RELAY-FORW
/// - SOLICIT
/// - client-id option
......
......@@ -70,6 +70,7 @@ libkea_dhcpsrv_la_SOURCES += cfg_hosts.cc cfg_hosts.h
libkea_dhcpsrv_la_SOURCES += cfg_iface.cc cfg_iface.h
libkea_dhcpsrv_la_SOURCES += cfg_option.cc cfg_option.h
libkea_dhcpsrv_la_SOURCES += cfg_option_def.cc cfg_option_def.h
libkea_dhcpsrv_la_SOURCES += cfg_rsoo.cc cfg_rsoo.h
libkea_dhcpsrv_la_SOURCES += cfg_subnets4.cc cfg_subnets4.h
libkea_dhcpsrv_la_SOURCES += cfg_subnets6.cc cfg_subnets6.h
libkea_dhcpsrv_la_SOURCES += cfg_mac_source.cc cfg_mac_source.h
......
......@@ -29,10 +29,6 @@ OptionDescriptor::equals(const OptionDescriptor& other) const {
}
CfgOption::CfgOption() {
// By default, the only allowed Relay-Supplied Options option is
// ERP local domain name. Other options may be added in configuration.
rsoo_options_.insert(D6O_ERP_LOCAL_DOMAIN_NAME);
}
bool
......@@ -198,20 +194,5 @@ CfgOption::optionSpaceToVendorId(const std::string& option_space) {
return (static_cast<uint32_t>(check));
}
void CfgOption::clearRSOO() {
rsoo_options_.clear();
}
bool CfgOption::isRSOOEnabled(uint16_t code) const {
return (rsoo_options_.find(code) != rsoo_options_.end());
}
void CfgOption::addRSOO(uint16_t code) {
if (rsoo_options_.find(code) == rsoo_options_.end()) {
// If there's no such code added yet, let's add it
rsoo_options_.insert(code);
}
}
} // end of namespace isc::dhcp
} // end of namespace isc
......@@ -195,11 +195,6 @@ typedef OptionContainer::nth_index<2>::type OptionContainerPersistIndex;
/// options is useful when the client requests stateless configuration from
/// the DHCP server and no subnet is selected for this client. This client
/// will only receive global options.
///
/// isRSSOEnabled(), addRSOO(), clearRSOO() are methods related to
/// Relay-Supplied Options option. This information does not provide any values
/// about the options themselves, but rather contain a list of options that
/// are allowed in RSOO ("RSOO-enabled").
class CfgOption {
public:
......@@ -357,23 +352,6 @@ public:
/// @return vendor id.
static uint32_t optionSpaceToVendorId(const std::string& option_space);
/// @brief Removes designation of all options as RSOO-enabled.
///
/// This method removes all designations of all options as being RSOO-enabled.
/// Note that the list is maintained by IANA and option 65 is officially
/// RSOO-enabled. This list may be extended in the future. Also, the user may
/// add extra options here.
void clearRSOO();
/// @brief Returns whether specific option code is RSOO-enabled.
/// @param code option code to check
/// @return true, if it is allowed in Relay-Supplied Options option
bool isRSOOEnabled(uint16_t code) const;
/// @brief Marks specified option code as RSOO-enabled.
/// @param code option to be enabled in RSOO
void addRSOO(uint16_t code);
private:
/// @brief Appends encapsulated options to the options in an option space.
......@@ -419,15 +397,6 @@ private:
uint32_t> VendorOptionSpaceCollection;
/// @brief Container holding options grouped by vendor id.
VendorOptionSpaceCollection vendor_options_;
/// @brief Contains a list of options that are allowed in RSOO option
///
/// RSOO stands for Relay-Supplied Options option. This is an option that
/// is inserted by the relay agent with the intention that the server will
/// echo those options back to the client. Only those options marked as
/// RSOO-enabled may appear in the RSOO. Currently only option 65 is marked
/// as such, but more options may be added in the future. See RFC6422 for details.
std::set<uint16_t> rsoo_options_;
};
/// @name Pointers to the @c CfgOption objects.
......
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <dhcp/dhcp6.h>
#include <dhcpsrv/cfg_rsoo.h>
namespace isc {
namespace dhcp {
CfgRSOO::CfgRSOO()
: rsoo_options_() {
rsoo_options_.insert(D6O_ERP_LOCAL_DOMAIN_NAME);
}
void
CfgRSOO::clear() {
rsoo_options_.clear();
}
bool
CfgRSOO::enabled(const uint16_t code) const {
return (rsoo_options_.find(code) != rsoo_options_.end());
}
void
CfgRSOO::enable(const uint16_t code) {
if (rsoo_options_.find(code) == rsoo_options_.end()) {
// If there's no such code added yet, let's add it
rsoo_options_.insert(code);
}
}
}
}
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef CFG_RSOO_H
#define CFG_RSOO_H
#include <boost/shared_ptr.hpp>
#include <set>
namespace isc {
namespace dhcp {
/// @brief Represents configuration of the RSOO options for the DHCP server.
///
/// This class holds the set of RSOO-enabled options (see RFC6422). The list
/// of RSOO-enabled options is maintained by IANA and currently the option
/// 65 is officially RSSO-enabled. The list may be extended in the future
/// and this class allows for specifying any future RSOO-enabled options.
/// The administrator may also use existing options as RSOO-enabled.
class CfgRSOO {
public:
/// @brief Constructor.
///
/// It adds the default (officially) RSOO-enabled options:
/// - OPTION_ERP_LOCAL_DOMAIN_NAME
CfgRSOO();
/// @brief Removes designation of all options as RSOO_enabled.
///
/// This method removes all designations of all options as being RSOO-enabled.
void clear();
/// @brief Returns whether specific option code is RSOO-enabled.
///
/// @param code Option code to check
/// @return true, if it is allowed in Relay-Supplied Options option
bool enabled(const uint16_t code) const;
/// @brief Marks specified option code as RSOO-enabled.
///
/// @param code option to be enabled in RSOO
void enable(const uint16_t code);
private:
/// @brief Contains a set of options that are allowed in RSOO option
///
/// RSOO stands for Relay-Supplied Options option. This is an option that
/// is inserted by the relay agent with the intention that the server will
/// echo those options back to the client. Only those options marked as
/// RSOO-enabled may appear in the RSOO. Currently only option 65 is marked
/// as such, but more options may be added in the future. See RFC6422 for details.
std::set<uint16_t> rsoo_options_;
};
/// @name Pointers to the @c CfgRSOO objects.