|
@@ -62,86 +62,89 @@ void
|
|
|
ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
|
|
|
ConstElementPtr class_def_cfg,
|
|
|
uint16_t family) {
|
|
|
+ // name is now mandatory
|
|
|
+ std::string name = getString(class_def_cfg, "name");
|
|
|
+ if (name.empty()) {
|
|
|
+ isc_throw(DhcpConfigError,
|
|
|
+ "not empty parameter 'name' is required "
|
|
|
+ << getPosition("name", class_def_cfg) << ")");
|
|
|
+ }
|
|
|
|
|
|
- try {
|
|
|
- std::string name;
|
|
|
- std::string next_server_txt = "0.0.0.0";
|
|
|
- std::string sname;
|
|
|
- std::string filename;
|
|
|
- ExpressionPtr match_expr;
|
|
|
- CfgOptionPtr options(new CfgOption());
|
|
|
-
|
|
|
- // Parse the elements that make up the client class definition.
|
|
|
- BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
|
|
|
- std::string entry(param.first);
|
|
|
- ConstElementPtr value(param.second);
|
|
|
-
|
|
|
- if (entry == "name") {
|
|
|
- name = value->stringValue();
|
|
|
-
|
|
|
- } else if (entry == "test") {
|
|
|
- ExpressionParser parser;
|
|
|
- parser.parse(match_expr, value, family);
|
|
|
-
|
|
|
- } else if (entry == "option-data") {
|
|
|
- OptionDataListParser opts_parser(family);
|
|
|
- opts_parser.parse(options, value);
|
|
|
-
|
|
|
- } else if (entry == "next-server") {
|
|
|
- next_server_txt = value->stringValue();
|
|
|
-
|
|
|
- } else if (entry == "server-hostname") {
|
|
|
- sname = value->stringValue();
|
|
|
-
|
|
|
- } else if (entry == "boot-file-name") {
|
|
|
- filename = value->stringValue();
|
|
|
-
|
|
|
- } else {
|
|
|
- isc_throw(DhcpConfigError, "invalid parameter '" << entry
|
|
|
- << "' (" << value->getPosition() << ")");
|
|
|
- }
|
|
|
- }
|
|
|
+ // Parse matching expression
|
|
|
+ ExpressionPtr match_expr;
|
|
|
+ ConstElementPtr test_cfg = class_def_cfg->get("test");
|
|
|
+ if (test_cfg) {
|
|
|
+ ExpressionParser parser;
|
|
|
+ parser.parse(match_expr, test_cfg, family);
|
|
|
+ }
|
|
|
|
|
|
- // name is now mandatory
|
|
|
- if (name.empty()) {
|
|
|
- isc_throw(DhcpConfigError,
|
|
|
- "not empty parameter 'name' is required");
|
|
|
- }
|
|
|
+ // Parse option data
|
|
|
+ CfgOptionPtr options(new CfgOption());
|
|
|
+ ConstElementPtr options_cfg = class_def_cfg->get("option-data");
|
|
|
+ if (options_cfg) {
|
|
|
+ OptionDataListParser opts_parser(family);
|
|
|
+ opts_parser.parse(options, options_cfg);
|
|
|
+ }
|
|
|
|
|
|
- // Let's parse the next-server field
|
|
|
- IOAddress next_server("0.0.0.0");
|
|
|
+ // Let's try to parse the next-server field
|
|
|
+ IOAddress next_server("0.0.0.0");
|
|
|
+ ConstElementPtr next_server_cfg = class_def_cfg->get("next-server");
|
|
|
+ if (next_server_cfg) {
|
|
|
try {
|
|
|
- next_server = IOAddress(next_server_txt);
|
|
|
+ next_server = IOAddress(getString(class_def_cfg, "next-server"));
|
|
|
} catch (const IOError& ex) {
|
|
|
- isc_throw(DhcpConfigError, "Invalid next-server value specified: '"
|
|
|
- << next_server_txt);
|
|
|
+ isc_throw(DhcpConfigError,
|
|
|
+ "Invalid next-server value specified: '"
|
|
|
+ << next_server_cfg->stringValue() << "' ("
|
|
|
+ << next_server_cfg->getPosition() << ")");
|
|
|
}
|
|
|
|
|
|
if (next_server.getFamily() != AF_INET) {
|
|
|
isc_throw(DhcpConfigError, "Invalid next-server value: '"
|
|
|
- << next_server_txt << "', must be IPv4 address");
|
|
|
+ << next_server_cfg->stringValue()
|
|
|
+ << "', must be IPv4 address ("
|
|
|
+ << next_server_cfg->getPosition() << ")");
|
|
|
}
|
|
|
|
|
|
if (next_server.isV4Bcast()) {
|
|
|
isc_throw(DhcpConfigError, "Invalid next-server value: '"
|
|
|
- << next_server_txt << "', must not be a broadcast");
|
|
|
+ << next_server_cfg->stringValue()
|
|
|
+ << "', must not be a broadcast ("
|
|
|
+ << next_server_cfg->getPosition() << ")");
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ // Let's try to parse server-hostname
|
|
|
+ std::string sname;
|
|
|
+ ConstElementPtr sname_cfg = class_def_cfg->get("server-hostname");
|
|
|
+ if (sname_cfg) {
|
|
|
+ sname = getString(class_def_cfg, "server-hostname");
|
|
|
|
|
|
- // Let's try to parse server-hostname
|
|
|
if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
|
|
|
isc_throw(DhcpConfigError, "server-hostname must be at most "
|
|
|
<< Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
|
|
|
- << sname.length());
|
|
|
+ << sname.length() << " ("
|
|
|
+ << sname_cfg->getPosition() << ")");
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ // Let's try to parse boot-file-name
|
|
|
+ std::string filename;
|
|
|
+ ConstElementPtr filename_cfg = class_def_cfg->get("boot-file-name");
|
|
|
+ if (filename_cfg) {
|
|
|
+ filename = getString(class_def_cfg, "boot-file-name");
|
|
|
|
|
|
- // Let's try to parse boot-file-name
|
|
|
if (filename.length() > Pkt4::MAX_FILE_LEN) {
|
|
|
isc_throw(DhcpConfigError, "boot-file-name must be at most "
|
|
|
<< Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
|
|
|
- << filename.length());
|
|
|
+ << filename.length() << " ("
|
|
|
+ << filename_cfg->getPosition() << ")");
|
|
|
}
|
|
|
|
|
|
- // Add the client class definition
|
|
|
+ }
|
|
|
+
|
|
|
+ // Add the client class definition
|
|
|
+ try {
|
|
|
class_dictionary->addClass(name, match_expr, options, next_server,
|
|
|
sname, filename);
|
|
|
} catch (const std::exception& ex) {
|