123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- // Copyright (C) 2015-2017 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
- // file, You can obtain one at http://mozilla.org/MPL/2.0/.
- #include <config.h>
- #include <dhcpsrv/cfgmgr.h>
- #include <dhcpsrv/client_class_def.h>
- #include <dhcpsrv/parsers/dhcp_parsers.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_parser.cc
- ///
- /// @brief Method implementations for client class definition parsing
- namespace isc {
- namespace dhcp {
- // ********************** ExpressionParser ****************************
- void
- ExpressionParser::parse(ExpressionPtr& expression,
- ConstElementPtr expression_cfg,
- uint16_t family) {
- if (expression_cfg->getType() != Element::string) {
- isc_throw(DhcpConfigError, "expression ["
- << expression_cfg->str() << "] must be a string, at ("
- << expression_cfg->getPosition() << ")");
- }
- // Get the expression's text via getValue() as the text returned
- // by str() enclosed in quotes.
- std::string value;
- expression_cfg->getValue(value);
- try {
- EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6);
- eval_ctx.parseString(value);
- expression.reset(new Expression());
- *expression = eval_ctx.expression;
- } catch (const std::exception& ex) {
- // Append position if there is a failure.
- isc_throw(DhcpConfigError,
- "expression: [" << value
- << "] error: " << ex.what() << " at ("
- << expression_cfg->getPosition() << ")");
- }
- }
- // ********************** ClientClassDefParser ****************************
- void
- ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
- ConstElementPtr class_def_cfg,
- uint16_t family) {
- 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() << ")");
- }
- }
- // name is now mandatory
- if (name.empty()) {
- isc_throw(DhcpConfigError,
- "not empty parameter 'name' is required");
- }
- // Let's parse the next-server field
- IOAddress 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");
- }
- if (next_server.isV4Bcast()) {
- isc_throw(DhcpConfigError, "Invalid next-server value: '"
- << next_server_txt << "', must not be a broadcast");
- }
- // 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());
- }
- // 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());
- }
- // Add the client class definition
- class_dictionary->addClass(name, match_expr, options, next_server,
- sname, filename);
- } catch (const std::exception& ex) {
- isc_throw(DhcpConfigError, ex.what()
- << " (" << class_def_cfg->getPosition() << ")");
- }
- }
- // ****************** ClientClassDefListParser ************************
- ClientClassDictionaryPtr
- ClientClassDefListParser::parse(ConstElementPtr client_class_def_list,
- uint16_t family) {
- ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
- BOOST_FOREACH(ConstElementPtr client_class_def,
- client_class_def_list->listValue()) {
- ClientClassDefParser parser;
- parser.parse(dictionary, client_class_def, family);
- }
- return (dictionary);
- }
- } // end of namespace isc::dhcp
- } // end of namespace isc
|