20 #include <boost/foreach.hpp>
44 << expression_cfg->str() <<
"] must be a string, at ("
45 << expression_cfg->getPosition() <<
")");
51 expression_cfg->getValue(value);
53 EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6,
58 }
catch (
const std::exception& ex) {
61 "expression: [" << value
62 <<
"] error: " << ex.
what() <<
" at ("
63 << expression_cfg->getPosition() <<
")");
73 bool append_error_position) {
75 std::string name = getString(class_def_cfg,
"name");
78 "not empty parameter 'name' is required "
79 << getPosition(
"name", class_def_cfg) <<
")");
86 bool depend_on_known =
false;
89 using std::placeholders::_1;
91 [&class_dictionary, &depend_on_known]
97 parser.
parse(match_expr, test_cfg, family, check_defined);
98 test = test_cfg->stringValue();
108 SimpleParser4::OPTION4_DEF_DEFAULTS :
109 SimpleParser6::OPTION6_DEF_DEFAULTS);
115 def = parser.
parse(option_def);
118 if (!LibDHCP::shouldDeferOptionUnpack(def.second,
119 def.first->getCode())) {
121 "Not allowed option definition for code '"
122 << def.first->getCode() <<
"' in space '"
123 << def.second <<
"' at ("
124 << option_def->getPosition() <<
")");
127 defs->add(def.first, def.second);
128 }
catch (
const std::exception& ex) {
131 << option_def->getPosition() <<
")");
141 opts_parser.
parse(options, option_data);
148 bool required =
false;
149 if (class_def_cfg->contains(
"only-if-required")) {
150 required = getBoolean(class_def_cfg,
"only-if-required");
155 if (class_def_cfg->contains(
"next-server")) {
156 std::string next_server_txt = getString(class_def_cfg,
"next-server");
158 next_server =
IOAddress(next_server_txt);
161 "Invalid next-server value specified: '"
162 << next_server_txt <<
"' ("
163 << getPosition(
"next-server", class_def_cfg) <<
")");
166 if (next_server.
getFamily() != AF_INET) {
168 << next_server_txt <<
"', must be IPv4 address ("
169 << getPosition(
"next-server", class_def_cfg) <<
")");
174 << next_server_txt <<
"', must not be a broadcast ("
175 << getPosition(
"next-server", class_def_cfg) <<
")");
181 if (class_def_cfg->contains(
"server-hostname")) {
182 sname = getString(class_def_cfg,
"server-hostname");
184 if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
186 << Pkt4::MAX_SNAME_LEN - 1 <<
" bytes long, it is "
187 << sname.length() <<
" ("
188 << getPosition(
"server-hostname", class_def_cfg) <<
")");
193 std::string filename;
194 if (class_def_cfg->contains(
"boot-file-name")) {
195 filename = getString(class_def_cfg,
"boot-file-name");
197 if (filename.length() > Pkt4::MAX_FILE_LEN) {
199 << Pkt4::MAX_FILE_LEN - 1 <<
" bytes long, it is "
200 << filename.length() <<
" ("
201 << getPosition(
"boot-file-name", class_def_cfg) <<
")");
208 class_dictionary->addClass(name, match_expr, test, required,
209 depend_on_known, options, defs,
210 user_context, next_server, sname, filename);
211 }
catch (
const std::exception& ex) {
212 std::ostringstream s;
213 s <<
"Can't add class: " << ex.what();
215 if (append_error_position) {
216 s <<
" (" << class_def_cfg->getPosition() <<
")";
224 const uint16_t family) {
226 if (!class_def_cfg || (class_def_cfg->getType() !=
Element::map)) {
231 static std::set<std::string> supported_params = {
"name",
235 "only-if-required" };
238 static std::set<std::string> supported_params_v4 = {
"option-def",
244 for (
auto name_value_pair : class_def_cfg->mapValue()) {
245 if ((supported_params.count(name_value_pair.first) > 0) ||
246 ((family == AF_INET) && (supported_params_v4.count(name_value_pair.first) > 0))) {
251 << name_value_pair.first <<
"'");
264 client_class_def_list->listValue()) {
266 parser.
parse(dictionary, client_class_def, family);