void
ClientClassDictionary::addClass(const std::string& name,
const ExpressionPtr& match_expr,
- const CfgOptionPtr& cfg_option) {
+ const CfgOptionPtr& cfg_option,
+ asiolink::IOAddress next_server,
+ const std::vector<uint8_t>& sname,
+ const std::vector<uint8_t>& filename) {
ClientClassDefPtr cclass(new ClientClassDef(name, match_expr, cfg_option));
+ cclass->setNextServer(next_server);
+ cclass->setSname(sname);
+ cclass->setFilename(filename);
addClass(cclass);
}
return (next_server_);
}
+ /// @brief sets the next-server value
+ ///
+ /// @param addr the value to be set
+ void setNextServer(const asiolink::IOAddress& addr) {
+ next_server_ = addr;
+ }
+
+ /// @brief sets the server-name value
+ ///
+ /// @param sname the value to be set
+ void setSname(const std::vector<uint8_t>& 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) {
+ 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 {
/// @param name Name to assign to this class
/// @param match_expr Expression the class will use to determine membership
/// @param options Collection of options members should be given
+ /// @param next_server next-server value for this class (optional)
+ /// @param sname server-name value for this class (optional)
+ /// @param filename boot-file-name value for this class (optional)
///
/// @throw DuplicateClientClassDef if class already exists within the
/// dictionary. See @ref dhcp::ClientClassDef::ClientClassDef() for
/// others.
void addClass(const std::string& name, const ExpressionPtr& match_expr,
- const CfgOptionPtr& options);
+ 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>());
/// @brief Adds a new class to the list
///
#include <dhcpsrv/client_class_def.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
#include <eval/eval_context.h>
+#include <asiolink/io_address.h>
+#include <asiolink/io_error.h>
#include <boost/foreach.hpp>
using namespace isc::data;
+using namespace isc::asiolink;
+using namespace std;
/// @file client_class_def.cc
///
void
ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
+
+ IOAddress next_server("0.0.0.0");
+ std::vector<uint8_t> sname;
+ std::vector<uint8_t> filename;
+
// Parse the elements that make up the option definition.
BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
std::string entry(param.first);
opts_parser.reset(new OptionDataListParser(entry, options_, family));
parser = opts_parser;
+ } else if (entry == "next-server") {
+ // Let's parse the next-server field
+ try {
+ next_server = IOAddress(param.second->stringValue());
+ } catch (const IOError& ex) {
+ isc_throw(DhcpConfigError, "Invalid next-server value specified: '"
+ << param.second << "'");
+ }
+ if (next_server.getFamily() != AF_INET) {
+ isc_throw(DhcpConfigError, "Invalid next-server value: '"
+ << param.second << "', must be IPv4 address");
+ }
+ } else if (entry == "server-hostname") {
+ string tmp = param.second->stringValue();
+ if (tmp.length() > Pkt4::MAX_SNAME_LEN) {
+ isc_throw(DhcpConfigError, "server-hostname must be at most "
+ << Pkt4::MAX_SNAME_LEN << " bytes long, it is "
+ << tmp.length());
+ }
+ sname = vector<uint8_t>(tmp.begin(), tmp.end());
+
+ } else if (entry == "boot-file-name") {
+ string tmp = param.second->stringValue();
+ if (tmp.length() > Pkt4::MAX_FILE_LEN) {
+ isc_throw(DhcpConfigError, "boot-file-name must be at most "
+ << Pkt4::MAX_FILE_LEN << " bytes long, it is "
+ << tmp.length());
+ }
+ filename = vector<uint8_t>(tmp.begin(), tmp.end());
+
} else {
isc_throw(DhcpConfigError, "invalid parameter '" << entry
<< "' (" << param.second->getPosition() << ")");