Commit ada652ba authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[4626] Changes after review

 - Dhcp4Srv::vendorClassSpecificProcessing removed
 - User's Guide updated
 - disabled obsolete test (will need to be rewritten to take advantage
   of new classification code)
 - classes definitions now use strings for server-name and filename
 - unused configuration removed from unit-tests
 - textFixedFields is now documented
 - Unit-tests now have short descriptions
parent 07e080c8
......@@ -1745,12 +1745,11 @@ It is merely echoed by the server
</para>
<para>
For clients that belong to the VENDOR_CLASS_docsis3.0 class, the siaddr
field is set to the value of next-server (if specified in a subnet). If
there is a boot-file-name option specified, its value is also set in the
file field in the DHCPv4 packet. For eRouter1.0 class, the siaddr is
always set to 0.0.0.0. That capability is expected to be moved to
an external hook library that will be dedicated to cable modems.
Note: Kea 1.0 and earlier versions performed special actions for
clients that were in VENDOR_CLASS_docsis3.0. This is no longer the
case in Kea 1.1 and newer. In those newer versions the old behavior
can be achieved by defining VENDOR_CLASS_docsis3.0 and setting
its next-server and boot-file-name values appropriately.
</para>
<para>
......
......@@ -233,11 +233,6 @@ information. The second and third argument contains the packet name
and type respectively. The fourth argument contains detailed packet
information.
% DHCP4_DISCOVER_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPDISCOVER
This debug message means that the server processing that is unique for each
client class has reported a failure. The response packet will not be sent.
The argument holds the client and transaction identification information.
% DHCP4_DYNAMIC_RECONFIGURATION initiate server reconfiguration using file: %1, after receiving SIGHUP signal
This is the info message logged when the DHCPv4 server starts reconfiguration
as a result of receiving SIGHUP signal.
......@@ -314,12 +309,6 @@ will be only able to offer global options - no addresses will be assigned.
The argument specifies the client and transaction identification
information.
% DHCP4_INFORM_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPINFORM
This debug message means that the server processing that is unique for each
client class has reported a failure. The response packet will not be sent.
The argument specifies the client and the transaction identification
information.
% DHCP4_INFORM_DIRECT_REPLY %1: DHCPACK in reply to the DHCPINFORM will be sent directly to %2 over %3
This debug message is issued when the DHCPACK will be sent directly to the
client, rather than via a relay. The first argument contains the client
......@@ -615,12 +604,6 @@ and the lease. The first argument includes the client and the
transaction identification information. The second argument specifies
the leased address.
% DHCP4_REQUEST_CLASS_PROCESSING_FAILED %1: client class specific processing failed for DHCPREQUEST
This debug message means that the server processing that is unique for each
client class has reported a failure. The response packet will not be sent.
The argument contains the client and transaction identification
information.
% DHCP4_RESPONSE_DATA %1: responding with packet %2 (type %3), packet details: %4
A debug message including the detailed data about the packet being sent
to the client. The first argument contains the client and the transaction
......
......@@ -1964,14 +1964,26 @@ Dhcpv4Srv::setFixedFields(Dhcpv4Exchange& ex) {
response->setSiaddr(next_server);
}
const vector<uint8_t>& sname = cl->second->getSname();
const string& sname = cl->second->getSname();
if (!sname.empty()) {
response->setSname(&sname[0], sname.size());
// Converting string to (const uint8_t*, size_t len) format is
// tricky. reineterpret_cast is not the most elegant solution,
// but it does avoid us making unnecessary copy. We will convert
// sname and file fields in Pkt4 to string one day and live
// will be easier.
response->setSname(reinterpret_cast<const uint8_t*>(sname.c_str()),
sname.size());
}
const vector<uint8_t>& filename = cl->second->getFilename();
const string& filename = cl->second->getFilename();
if (!filename.empty()) {
response->setFile(&filename[0], filename.size());
// Converting string to (const uint8_t*, size_t len) format is
// tricky. reineterpret_cast is not the most elegant solution,
// but it does avoid us making unnecessary copy. We will convert
// sname and file fields in Pkt4 to string one day and live
// will be easier.
response->setFile(reinterpret_cast<const uint8_t*>(filename.c_str()),
filename.size());
}
}
......@@ -2021,8 +2033,8 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
// them we append them for him.
appendBasicOptions(ex);
// See if the class mandates setting any fixed fields (siaddr, sname,
// filename).
// Set fixed fields (siaddr, sname, filename) if defined in
// the reservation, class or subnet specific configuration.
setFixedFields(ex);
} else {
......@@ -2037,14 +2049,6 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
appendServerID(ex);
/// @todo: decide whether we want to add a new hook point for
/// doing class specific processing.
if (!vendorClassSpecificProcessing(ex)) {
/// @todo add more verbosity here
LOG_DEBUG(options4_logger, DBG_DHCP4_DETAIL, DHCP4_DISCOVER_CLASS_PROCESSING_FAILED)
.arg(discover->getLabel());
}
return (ex.getResponse());
}
......@@ -2081,8 +2085,8 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
// them we append them for him.
appendBasicOptions(ex);
// See if the class mandates setting any fixed fields (siaddr, sname,
// filename).
// Set fixed fields (siaddr, sname, filename) if defined in
// the reservation, class or subnet specific configuration.
setFixedFields(ex);
}
......@@ -2092,14 +2096,6 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
appendServerID(ex);
/// @todo: decide whether we want to add a new hook point for
/// doing class specific processing.
if (!vendorClassSpecificProcessing(ex)) {
/// @todo add more verbosity here
LOG_DEBUG(options4_logger, DBG_DHCP4_DETAIL, DHCP4_REQUEST_CLASS_PROCESSING_FAILED)
.arg(ex.getQuery()->getLabel());
}
return (ex.getResponse());
}
......@@ -2369,8 +2365,8 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
appendBasicOptions(ex);
adjustIfaceData(ex);
// See if the class mandates setting any fixed fields (siaddr, sname,
// filename).
// Set fixed fields (siaddr, sname, filename) if defined in
// the reservation, class or subnet specific configuration.
setFixedFields(ex);
// There are cases for the DHCPINFORM that the server receives it via
......@@ -2391,14 +2387,6 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
// The DHCPACK must contain server id.
appendServerID(ex);
/// @todo: decide whether we want to add a new hook point for
/// doing class specific processing.
if (!vendorClassSpecificProcessing(ex)) {
LOG_DEBUG(options4_logger, DBG_DHCP4_DETAIL,
DHCP4_INFORM_CLASS_PROCESSING_FAILED)
.arg(inform->getLabel());
}
return (ex.getResponse());
}
......@@ -2622,17 +2610,8 @@ void Dhcpv4Srv::classifyByVendor(const Pkt4Ptr& pkt, std::string& classes) {
// is indeed a modem, John B. suggested to check whether chaddr field
// quals subscriber-id option that was inserted by the relay (CMTS).
// This kind of logic will appear here soon.
if (vendor_class->getValue().find(DOCSIS3_CLASS_MODEM) != std::string::npos) {
pkt->addClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_MODEM);
classes += string(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_MODEM) + " ";
} else
if (vendor_class->getValue().find(DOCSIS3_CLASS_EROUTER) != std::string::npos) {
pkt->addClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER);
classes += string(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER) + " ";
} else {
pkt->addClass(VENDOR_CLASS_PREFIX + vendor_class->getValue());
classes += VENDOR_CLASS_PREFIX + vendor_class->getValue();
}
pkt->addClass(VENDOR_CLASS_PREFIX + vendor_class->getValue());
classes += VENDOR_CLASS_PREFIX + vendor_class->getValue();
}
void Dhcpv4Srv::classifyPacket(const Pkt4Ptr& pkt) {
......@@ -2687,52 +2666,6 @@ void Dhcpv4Srv::classifyPacket(const Pkt4Ptr& pkt) {
}
}
bool
Dhcpv4Srv::vendorClassSpecificProcessing(const Dhcpv4Exchange& ex) {
Subnet4Ptr subnet = ex.getContext()->subnet_;
Pkt4Ptr query = ex.getQuery();
Pkt4Ptr rsp = ex.getResponse();
// If any of those is missing, there is nothing to do.
if (!subnet || !query || !rsp) {
return (true);
}
if (query->inClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_MODEM)) {
// Set next-server. This is TFTP server address. Cable modems will
// download their configuration from that server.
rsp->setSiaddr(subnet->getSiaddr());
// Now try to set up file field in DHCPv4 packet. We will just copy
// content of the boot-file option, which contains the same information.
const CfgOptionList& co_list = ex.getCfgOptionList();
for (CfgOptionList::const_iterator copts = co_list.begin();
copts != co_list.end(); ++copts) {
OptionDescriptor desc = (*copts)->get("dhcp4", DHO_BOOT_FILE_NAME);
if (desc.option_) {
boost::shared_ptr<OptionString> boot =
boost::dynamic_pointer_cast<OptionString>(desc.option_);
if (boot) {
std::string filename = boot->getValue();
rsp->setFile((const uint8_t*)filename.c_str(), filename.size());
break;
}
}
}
}
if (query->inClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER)) {
// Do not set TFTP server address for eRouter devices.
rsp->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS());
}
return (true);
}
void
Dhcpv4Srv::startD2() {
D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
......
......@@ -517,8 +517,10 @@ protected:
///
/// If the incoming packets belongs to a class and that class defines
/// next-server, server-hostname or boot-file-name, we need to set the
/// siaddr, sname or filename fields in the outgoing packet. This
/// is what this method does.
/// siaddr, sname or filename fields in the outgoing packet. Also, those
/// values can be defined for subnet or in reservations. The values
/// defined in reservation takes precedence over class values, which
/// in turn take precedence over subnet values.
///
/// @param ex DHCPv4 exchange holding the client's message and the server's
/// response to be adjusted.
......@@ -763,18 +765,6 @@ protected:
/// @param pkt packet to be classified
void classifyPacket(const Pkt4Ptr& pkt);
/// @brief Performs packet processing specific to a vendor class
///
/// If the selected subnet, query or response in the @c ex object is NULL
/// this method returns immediately and returns true.
///
/// @note This processing is a likely candidate to be pushed into hooks.
///
/// @param ex The exchange holding both the client's message and the
/// server's response.
/// @return true if successful, false otherwise (will prevent sending response)
bool vendorClassSpecificProcessing(const Dhcpv4Exchange& ex);
/// @brief Allocation Engine.
/// Pointer to the allocation engine that we are currently using
/// It must be a pointer, because we will support changing engines
......
......@@ -20,54 +20,19 @@ using namespace std;
namespace {
/// @brief Set of JSON configurations used throughout the DORA tests.
/// @brief Set of JSON configurations used throughout the classify tests.
///
/// - Configuration 0:
/// - Used for testing direct traffic
/// - 1 subnet: 10.0.0.0/24
/// - 1 pool: 10.0.0.10-10.0.0.100
/// - Router option present: 10.0.0.200 and 10.0.0.201
/// - Domain Name Server option present: 10.0.0.202, 10.0.0.203.
/// - Log Servers option present: 192.0.2.200 and 192.0.2.201
/// - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
/// - no classes
///
/// - Configuration 1:
/// - The same as configuration 0, but has the following classes defined:
/// - the following classes defined:
/// option[93].hex == 0x0009, next-server set to 1.2.3.4
/// option[93].hex == 0x0007, set server-hostname to deneb
/// option[93].hex == 0x0006, set boot-file-name to pxelinux.0
/// option[93].hex == 0x0001, set boot-file-name to ipxe.efi
const char* CONFIGS[] = {
// Configuration 0
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 600,"
"\"subnet4\": [ { "
" \"subnet\": \"10.0.0.0/24\", "
" \"id\": 1,"
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
" \"option-data\": [ {"
" \"name\": \"routers\","
" \"data\": \"10.0.0.200,10.0.0.201\""
" },"
" {"
" \"name\": \"domain-name-servers\","
" \"data\": \"10.0.0.202,10.0.0.203\""
" },"
" {"
" \"name\": \"log-servers\","
" \"data\": \"10.0.0.200,10.0.0.201\""
" },"
" {"
" \"name\": \"cookie-servers\","
" \"data\": \"10.0.0.202,10.0.0.203\""
" } ]"
" } ]"
"}",
// Configuration 6
// Configuration 0
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
......@@ -124,6 +89,19 @@ public:
~ClassifyTest() {
}
/// @brief Does client exchanges and checks if fixed fields have expected values.
///
/// Depending on the value of msgtype (allowed types: DHCPDISCOVER, DHCPREQUEST or
/// DHCPINFORM), this method sets up the server, then conducts specified exchange
/// and then checks if the response contains expected values of next-server, sname
/// and filename fields.
///
/// @param config server configuration to be used
/// @param msgtype DHCPDISCOVER, DHCPREQUEST or DHCPINFORM
/// @param extra_opt option to include in client messages (optional)
/// @param exp_next_server expected value of the next-server field
/// @param exp_sname expected value of the sname field
/// @param exp_filename expected value of the filename field
void
testFixedFields(const char* config, uint8_t msgtype, const OptionPtr& extra_opt,
const std::string& exp_next_server, const std::string& exp_sname,
......@@ -181,17 +159,17 @@ public:
// This test checks that an incoming DISCOVER that does not match any classes
// will get the fixed fields empty.
TEST_F(ClassifyTest, fixedFieldsDiscoverNoClasses) {
testFixedFields(CONFIGS[1], DHCPDISCOVER, OptionPtr(), "0.0.0.0", "", "");
testFixedFields(CONFIGS[0], DHCPDISCOVER, OptionPtr(), "0.0.0.0", "", "");
}
// This test checks that an incoming REQUEST that does not match any classes
// will get the fixed fields empty.
TEST_F(ClassifyTest, fixedFieldsRequestNoClasses) {
testFixedFields(CONFIGS[1], DHCPREQUEST, OptionPtr(), "0.0.0.0", "", "");
testFixedFields(CONFIGS[0], DHCPREQUEST, OptionPtr(), "0.0.0.0", "", "");
}
// This test checks that an incoming INFORM that does not match any classes
// will get the fixed fields empty.
TEST_F(ClassifyTest, fixedFieldsInformNoClasses) {
testFixedFields(CONFIGS[1], DHCPINFORM, OptionPtr(), "0.0.0.0", "", "");
testFixedFields(CONFIGS[0], DHCPINFORM, OptionPtr(), "0.0.0.0", "", "");
}
......@@ -200,21 +178,21 @@ TEST_F(ClassifyTest, fixedFieldsInformNoClasses) {
TEST_F(ClassifyTest, fixedFieldsDiscoverNextServer) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0009));
testFixedFields(CONFIGS[1], DHCPDISCOVER, pxe, "1.2.3.4", "", "");
testFixedFields(CONFIGS[0], DHCPDISCOVER, pxe, "1.2.3.4", "", "");
}
// This test checks that an incoming REQUEST that does match a class that has
// next-server specified will result in a response that has the next-server set.
TEST_F(ClassifyTest, fixedFieldsRequestNextServer) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0009));
testFixedFields(CONFIGS[1], DHCPREQUEST, pxe, "1.2.3.4", "", "");
testFixedFields(CONFIGS[0], DHCPREQUEST, pxe, "1.2.3.4", "", "");
}
// This test checks that an incoming INFORM that does match a class that has
// next-server specified will result in a response that has the next-server set.
TEST_F(ClassifyTest, fixedFieldsInformNextServer) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0009));
testFixedFields(CONFIGS[1], DHCPINFORM, pxe, "1.2.3.4", "", "");
testFixedFields(CONFIGS[0], DHCPINFORM, pxe, "1.2.3.4", "", "");
}
......@@ -223,21 +201,21 @@ TEST_F(ClassifyTest, fixedFieldsInformNextServer) {
TEST_F(ClassifyTest, fixedFieldsDiscoverHostname) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0007));
testFixedFields(CONFIGS[1], DHCPDISCOVER, pxe, "0.0.0.0", "deneb", "");
testFixedFields(CONFIGS[0], DHCPDISCOVER, pxe, "0.0.0.0", "deneb", "");
}
// This test checks that an incoming REQUEST that does match a class that has
// server-hostname specified will result in a response that has the sname field set.
TEST_F(ClassifyTest, fixedFieldsRequestHostname) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0007));
testFixedFields(CONFIGS[1], DHCPREQUEST, pxe, "0.0.0.0", "deneb", "");
testFixedFields(CONFIGS[0], DHCPREQUEST, pxe, "0.0.0.0", "deneb", "");
}
// This test checks that an incoming INFORM that does match a class that has
// server-hostname specified will result in a response that has the sname field set.
TEST_F(ClassifyTest, fixedFieldsInformHostname) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0007));
testFixedFields(CONFIGS[1], DHCPINFORM, pxe, "0.0.0.0", "deneb", "");
testFixedFields(CONFIGS[0], DHCPINFORM, pxe, "0.0.0.0", "deneb", "");
}
......@@ -246,21 +224,21 @@ TEST_F(ClassifyTest, fixedFieldsInformHostname) {
TEST_F(ClassifyTest, fixedFieldsDiscoverFile1) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0006));
testFixedFields(CONFIGS[1], DHCPDISCOVER, pxe, "0.0.0.0", "", "pxelinux.0");
testFixedFields(CONFIGS[0], DHCPDISCOVER, pxe, "0.0.0.0", "", "pxelinux.0");
}
// This test checks that an incoming REQUEST that does match a class that has
// boot-file-name specified will result in a response that has the filename field set.
TEST_F(ClassifyTest, fixedFieldsRequestFile1) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0006));
testFixedFields(CONFIGS[1], DHCPREQUEST, pxe, "0.0.0.0", "", "pxelinux.0");
testFixedFields(CONFIGS[0], DHCPREQUEST, pxe, "0.0.0.0", "", "pxelinux.0");
}
// This test checks that an incoming INFORM that does match a class that has
// boot-file-name specified will result in a response that has the filename field set.
TEST_F(ClassifyTest, fixedFieldsInformFile1) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0006));
testFixedFields(CONFIGS[1], DHCPDISCOVER, pxe, "0.0.0.0", "", "pxelinux.0");
testFixedFields(CONFIGS[0], DHCPDISCOVER, pxe, "0.0.0.0", "", "pxelinux.0");
}
......@@ -269,21 +247,21 @@ TEST_F(ClassifyTest, fixedFieldsInformFile1) {
TEST_F(ClassifyTest, fixedFieldsDiscoverFile2) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0001));
testFixedFields(CONFIGS[1], DHCPDISCOVER, pxe, "0.0.0.0", "", "ipxe.efi");
testFixedFields(CONFIGS[0], DHCPDISCOVER, pxe, "0.0.0.0", "", "ipxe.efi");
}
// This test checks that an incoming REQUEST that does match a different class that has
// boot-file-name specified will result in a response that has the filename field set.
TEST_F(ClassifyTest, fixedFieldsRequestFile2) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0001));
testFixedFields(CONFIGS[1], DHCPREQUEST, pxe, "0.0.0.0", "", "ipxe.efi");
testFixedFields(CONFIGS[0], DHCPREQUEST, pxe, "0.0.0.0", "", "ipxe.efi");
}
// This test checks that an incoming INFORM that does match a different class that has
// boot-file-name specified will result in a response that has the filename field set.
TEST_F(ClassifyTest, fixedFieldsInformFile2) {
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0001));
testFixedFields(CONFIGS[1], DHCPINFORM, pxe, "0.0.0.0", "", "ipxe.efi");
testFixedFields(CONFIGS[0], DHCPINFORM, pxe, "0.0.0.0", "", "ipxe.efi");
}
......
......@@ -1486,8 +1486,13 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsDocsisDefinitions) {
ASSERT_EQ(0, rcode_);
}
// Checks if DOCSIS client packets are classified properly
TEST_F(Dhcpv4SrvTest, docsisClientClassification) {
/// Checks if DOCSIS client packets are classified properly
///
/// @todo: With the change in #4626 the vendorClassSpecificProcessing
/// code was removed and replaced with generic classification. One day
/// we should rewrite this test to use classes. It would check that the
/// classification system can be used for docsis packets.
TEST_F(Dhcpv4SrvTest, DISABLED_docsisClientClassification) {
NakedDhcpv4Srv srv(0);
......
// 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
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -16,7 +16,7 @@ ClientClassDef::ClientClassDef(const std::string& name,
const ExpressionPtr& match_expr,
const CfgOptionPtr& cfg_option)
: name_(name), match_expr_(match_expr), cfg_option_(cfg_option),
next_server_(asiolink::IOAddress("0.0.0.0")) {
next_server_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()) {
// Name can't be blank
if (name_.empty()) {
......@@ -34,7 +34,8 @@ ClientClassDef::ClientClassDef(const std::string& name,
ClientClassDef::ClientClassDef(const ClientClassDef& rhs)
: name_(rhs.name_), match_expr_(ExpressionPtr()),
cfg_option_(new CfgOption()), next_server_(asiolink::IOAddress("0.0.0.0")) {
cfg_option_(new CfgOption()),
next_server_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()) {
if (rhs.match_expr_) {
match_expr_.reset(new Expression());
......@@ -124,8 +125,8 @@ ClientClassDictionary::addClass(const std::string& name,
const ExpressionPtr& match_expr,
const CfgOptionPtr& cfg_option,
asiolink::IOAddress next_server,
const std::vector<uint8_t>& sname,
const std::vector<uint8_t>& filename) {
const std::string& sname,
const std::string& filename) {
ClientClassDefPtr cclass(new ClientClassDef(name, match_expr, cfg_option));
cclass->setNextServer(next_server);
cclass->setSname(sname);
......
// 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
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -108,7 +108,7 @@ public:
/// @brief returns next-server value
/// @return next-server value
asiolink::IOAddress getNextServer() const {
const asiolink::IOAddress& getNextServer() const {
return (next_server_);
}
......@@ -122,26 +122,26 @@ public:
/// @brief sets the server-name value
///
/// @param sname the value to be set
void setSname(const std::vector<uint8_t>& sname) {
void setSname(const std::string& sname) {
sname_ = sname;
}
/// @brief sets the boot-file-name value
///
/// @param filename the value to be set
void setFilename(const std::vector<uint8_t>& filename) {
void setFilename(const std::string& filename) {
filename_ = filename;
}
/// @brief returns server-hostname value
/// @return the vector that contains server-hostname (may be empty if not defined)
const std::vector<uint8_t>& getSname() const {
const std::string& getSname() const {
return (sname_);
}
/// @brief returns boot-file-name value
/// @return the vector that contains boot-file-name (may be empty if not defined)
const std::vector<uint8_t>& getFilename() const {
const std::string& getFilename() const {
return (filename_);
}
......@@ -165,13 +165,13 @@ private:
/// If set by the server-hostname parameter, this value will be
/// set in the sname field of the DHCPv4 packet.
/// This can be up to 64 octets long.
std::vector<uint8_t> sname_;
std::string sname_;
/// @brief boot-file-name
/// If set by the boot-file-name parameter, this value will be
/// set in the file field of the DHCPv4 packet.
/// This can be up to 128 octets long.
std::vector<uint8_t> filename_;
std::string filename_;
};
......@@ -214,8 +214,8 @@ public:
void addClass(const std::string& name, const ExpressionPtr& match_expr,
const CfgOptionPtr& options,
asiolink::IOAddress next_server = asiolink::IOAddress("0.0.0.0"),
const std::vector<uint8_t>& sname = std::vector<uint8_t>(),
const std::vector<uint8_t>& filename = std::vector<uint8_t>());
const std::string& sname = std::string(),
const std::string& filename = std::string());
/// @brief Adds a new class to the list
///
......
......@@ -119,43 +119,42 @@ ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
std::string name;
try {
name = string_values_->getParam("name");
} catch (const std::exception& ex) {
isc_throw(DhcpConfigError, ex.what() << " ("
<< class_def_cfg->getPosition() << ")");
}
// Let's parse the next-server field
IOAddress next_server("0.0.0.0");
string next_server_txt = string_values_->getOptionalParam("next-server", "0.0.0.0");
try {
next_server = IOAddress(next_server_txt);
} catch (const IOError& ex) {
isc_throw(DhcpConfigError, "Invalid next-server value specified: '"
<< next_server_txt << "'");
}
if (next_server.getFamily() != AF_INET) {
isc_throw(DhcpConfigError, "Invalid next-server value: '"
<< next_server_txt << "', must be IPv4 address");
}