Kea 2.7.0
client_class_def.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <eval/dependency.h>
10#include <eval/evaluate.h>
11#include <eval/eval_log.h>
13#include <dhcpsrv/cfgmgr.h>
14#include <dhcpsrv/dhcpsrv_log.h>
16
17#include <queue>
18
19using namespace isc::data;
20
21namespace isc {
22namespace dhcp {
23
24//********** ClientClassDef ******************//
25
26ClientClassDef::ClientClassDef(const std::string& name,
27 const ExpressionPtr& match_expr,
28 const CfgOptionPtr& cfg_option)
30 match_expr_(match_expr), required_(false), depend_on_known_(false),
31 cfg_option_(cfg_option), next_server_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
32 valid_(), preferred_() {
33
34 // Name can't be blank
35 if (name_.empty()) {
36 isc_throw(BadValue, "Client Class name cannot be blank");
37 }
38
39 // We permit an empty expression for now. This will likely be useful
40 // for automatic classes such as vendor class.
41 // For classes without options, make sure we have an empty collection
42 if (!cfg_option_) {
43 cfg_option_.reset(new CfgOption());
44 }
45}
46
48 : UserContext(rhs), CfgToElement(rhs), StampedElement(rhs), name_(rhs.name_),
49 match_expr_(ExpressionPtr()), test_(rhs.test_), required_(rhs.required_),
50 depend_on_known_(rhs.depend_on_known_), cfg_option_(new CfgOption()),
51 next_server_(rhs.next_server_), sname_(rhs.sname_),
52 filename_(rhs.filename_), valid_(rhs.valid_), preferred_(rhs.preferred_),
53 offer_lft_(rhs.offer_lft_) {
54
55 if (rhs.match_expr_) {
56 match_expr_.reset(new Expression());
57 *match_expr_ = *rhs.match_expr_;
58 }
59
60 if (rhs.cfg_option_def_) {
61 cfg_option_def_.reset(new CfgOptionDef());
62 rhs.cfg_option_def_->copyTo(*cfg_option_def_);
63 }
64
65 if (rhs.cfg_option_) {
66 rhs.cfg_option_->copyTo(*cfg_option_);
67 }
68}
69
72
73std::string
75 return (name_);
76}
77
78void
79ClientClassDef::setName(const std::string& name) {
80 name_ = name;
81}
82
83const ExpressionPtr&
85 return (match_expr_);
86}
87
88void
90 match_expr_ = match_expr;
91}
92
93std::string
95 return (test_);
96}
97
98void
99ClientClassDef::setTest(const std::string& test) {
100 test_ = test;
101}
102
103bool
105 return (required_);
106}
107
108void
110 required_ = required;
111}
112
113bool
115 return (depend_on_known_);
116}
117
118void
119ClientClassDef::setDependOnKnown(bool depend_on_known) {
120 depend_on_known_ = depend_on_known;
121}
122
123const CfgOptionDefPtr&
125 return (cfg_option_def_);
126}
127
128void
130 cfg_option_def_ = cfg_option_def;
131}
132
133const CfgOptionPtr&
135 return (cfg_option_);
136}
137
138void
140 cfg_option_ = cfg_option;
141}
142
143void
145 // Evaluate the expression which can return false (no match),
146 // true (match) or raise an exception (error)
147 try {
148 bool status = evaluateBool(*expr_ptr, *pkt);
149 if (status) {
151 .arg(pkt->getLabel())
152 .arg(getName())
153 .arg("true");
154 // Matching: add the class
155 pkt->addClass(getName());
156 } else {
158 .arg(pkt->getLabel())
159 .arg(getName())
160 .arg("false");
161 }
162 } catch (const Exception& ex) {
164 .arg(pkt->getLabel())
165 .arg(getName())
166 .arg(ex.what());
167 } catch (...) {
169 .arg(pkt->getLabel())
170 .arg(getName())
171 .arg("get exception?");
172 }
173}
174
175const std::string TemplateClientClassDef::SPAWN_CLASS_PREFIX("SPAWN_");
176
178 const ExpressionPtr& match_expr,
179 const CfgOptionPtr& options) :
180 ClientClassDef(name, match_expr, options) {
181}
182
183void
185 // Evaluate the expression which can return false (no match),
186 // true (match) or raise an exception (error)
187 try {
188 std::string subclass = evaluateString(*expr_ptr, *pkt);
189 if (!subclass.empty()) {
191 .arg(pkt->getLabel())
192 .arg(getName())
193 .arg(subclass);
194 // Matching: add the subclass
196 value += getName();
197 value += "_";
198 value += subclass;
199 pkt->addSubClass(getName(), value);
200 }
201 } catch (const Exception& ex) {
203 .arg(pkt->getLabel())
204 .arg(getName())
205 .arg(ex.what());
206 } catch (...) {
208 .arg(pkt->getLabel())
209 .arg(getName())
210 .arg("get exception?");
211 }
212}
213
214bool
215ClientClassDef::dependOnClass(const std::string& name) const {
216 return (isc::dhcp::dependOnClass(match_expr_, name));
217}
218
219bool
221 return ((name_ == other.name_) &&
222 ((!match_expr_ && !other.match_expr_) ||
223 (match_expr_ && other.match_expr_ &&
224 (*match_expr_ == *other.match_expr_))) &&
225 ((!cfg_option_ && !other.cfg_option_) ||
226 (cfg_option_ && other.cfg_option_ &&
227 (*cfg_option_ == *other.cfg_option_))) &&
228 ((!cfg_option_def_ && !other.cfg_option_def_) ||
229 (cfg_option_def_ && other.cfg_option_def_ &&
230 (*cfg_option_def_ == *other.cfg_option_def_))) &&
231 (required_ == other.required_) &&
232 (depend_on_known_ == other.depend_on_known_) &&
233 (next_server_ == other.next_server_) &&
234 (sname_ == other.sname_) &&
235 (filename_ == other.filename_));
236}
237
240 uint16_t family = CfgMgr::instance().getFamily();
242 // Set user-context
243 contextToElement(result);
244 // Set name
245 result->set("name", Element::create(name_));
246 // Set original match expression (empty string won't parse)
247 if (!test_.empty()) {
248 result->set("test", Element::create(test_));
249 }
250 // Set only-if-required
251 if (required_) {
252 result->set("only-if-required", Element::create(required_));
253 }
254 // Set option-def (used only by DHCPv4)
255 if (cfg_option_def_ && (family == AF_INET)) {
256 result->set("option-def", cfg_option_def_->toElement());
257 }
258 // Set option-data
259 result->set("option-data", cfg_option_->toElement());
260
261 if (family == AF_INET) {
262 // V4 only
263 // Set next-server
264 result->set("next-server", Element::create(next_server_.toText()));
265 // Set server-hostname
266 result->set("server-hostname", Element::create(sname_));
267 // Set boot-file-name
268 result->set("boot-file-name", Element::create(filename_));
269
270 // Set offer-lifetime
271 if (!offer_lft_.unspecified()) {
272 result->set("offer-lifetime",
273 Element::create(static_cast<long long>(offer_lft_.get())));
274 }
275 } else {
276 // V6 only
277 // Set preferred-lifetime
278 if (!preferred_.unspecified()) {
279 result->set("preferred-lifetime",
280 Element::create(static_cast<long long>(preferred_.get())));
281 }
282
283 if (preferred_.getMin() < preferred_.get()) {
284 result->set("min-preferred-lifetime",
285 Element::create(static_cast<long long>(preferred_.getMin())));
286 }
287
288 if (preferred_.getMax() > preferred_.get()) {
289 result->set("max-preferred-lifetime",
290 Element::create(static_cast<long long>(preferred_.getMax())));
291 }
292 }
293
294 // Set valid-lifetime
295 if (!valid_.unspecified()) {
296 result->set("valid-lifetime",
297 Element::create(static_cast<long long>(valid_.get())));
298
299 if (valid_.getMin() < valid_.get()) {
300 result->set("min-valid-lifetime",
301 Element::create(static_cast<long long>(valid_.getMin())));
302 }
303
304 if (valid_.getMax() > valid_.get()) {
305 result->set("max-valid-lifetime",
306 Element::create(static_cast<long long>(valid_.getMax())));
307 }
308 }
309
310 return (result);
311}
312
315 auto const& result = ClientClassDef::toElement();
316 auto const& test = result->get("test");
317 if (test) {
318 result->set("template-test", test);
319 result->remove("test");
320 } else {
321 result->set("template-test", Element::create(""));
322 }
323 return (result);
324}
325
326std::ostream& operator<<(std::ostream& os, const ClientClassDef& x) {
327 os << "ClientClassDef:" << x.getName();
328 return (os);
329}
330
331//********** ClientClassDictionary ******************//
332
336
338 : map_(new ClientClassDefMap()), list_(new ClientClassDefList()) {
339 for (auto const& cclass : *rhs.list_) {
341 addClass(copy);
342 }
343}
344
347
348void
349ClientClassDictionary::addClass(const std::string& name,
350 const ExpressionPtr& match_expr,
351 const std::string& test,
352 bool required,
353 bool depend_on_known,
354 const CfgOptionPtr& cfg_option,
355 CfgOptionDefPtr cfg_option_def,
356 ConstElementPtr user_context,
357 asiolink::IOAddress next_server,
358 const std::string& sname,
359 const std::string& filename,
360 const util::Triplet<uint32_t>& valid,
361 const util::Triplet<uint32_t>& preferred,
362 bool is_template,
363 const util::Optional<uint32_t>& offer_lft) {
364 ClientClassDefPtr cclass;
365 if (is_template) {
366 cclass.reset(new TemplateClientClassDef(name, match_expr, cfg_option));
367 } else {
368 cclass.reset(new ClientClassDef(name, match_expr, cfg_option));
369 }
370 cclass->setTest(test);
371 cclass->setRequired(required);
372 cclass->setDependOnKnown(depend_on_known);
373 cclass->setCfgOptionDef(cfg_option_def);
374 cclass->setContext(user_context),
375 cclass->setNextServer(next_server);
376 cclass->setSname(sname);
377 cclass->setFilename(filename);
378 cclass->setValid(valid);
379 cclass->setPreferred(preferred);
380 cclass->setOfferLft(offer_lft);
381 addClass(cclass);
382}
383
384void
386 if (!class_def) {
387 isc_throw(BadValue, "ClientClassDictionary::addClass "
388 " - class definition cannot be null");
389 }
390
391 if (findClass(class_def->getName())) {
392 isc_throw(DuplicateClientClassDef, "Client Class: "
393 << class_def->getName() << " has already been defined");
394 }
395
396 list_->push_back(class_def);
397 (*map_)[class_def->getName()] = class_def;
398}
399
401ClientClassDictionary::findClass(const std::string& name) const {
402 ClientClassDefMap::iterator it = map_->find(name);
403 if (it != map_->end()) {
404 return (*it).second;
405 }
406
407 return (ClientClassDefPtr());
408}
409
410void
411ClientClassDictionary::removeClass(const std::string& name) {
412 for (ClientClassDefList::iterator this_class = list_->begin();
413 this_class != list_->end(); ++this_class) {
414 if ((*this_class)->getName() == name) {
415 list_->erase(this_class);
416 break;
417 }
418 }
419 map_->erase(name);
420}
421
422void
424 // Class id equal to 0 means it wasn't set.
425 if (id == 0) {
426 return;
427 }
428 for (ClientClassDefList::iterator this_class = list_->begin();
429 this_class != list_->end(); ++this_class) {
430 if ((*this_class)->getId() == id) {
431 map_->erase((*this_class)->getName());
432 list_->erase(this_class);
433 break;
434 }
435 }
436}
437
440 return (list_);
441}
442
443bool
445 return (list_->empty());
446}
447
448bool
450 std::string& dependent_class) const {
451 // Skip previous classes as they should not depend on name.
452 bool found = false;
453 for (auto const& this_class : *list_) {
454 if (found) {
455 if (this_class->dependOnClass(name)) {
456 dependent_class = this_class->getName();
457 return (true);
458 }
459 } else {
460 if (this_class->getName() == name) {
461 found = true;
462 }
463 }
464 }
465 return (false);
466}
467
468bool
470 if (list_->size() != other.list_->size()) {
471 return (false);
472 }
473
474 ClientClassDefList::const_iterator this_class = list_->cbegin();
475 ClientClassDefList::const_iterator other_class = other.list_->cbegin();
476 while (this_class != list_->cend() &&
477 other_class != other.list_->cend()) {
478 if (!*this_class || !*other_class ||
479 **this_class != **other_class) {
480 return false;
481 }
482
483 ++this_class;
484 ++other_class;
485 }
486
487 return (true);
488}
489
490void
492 std::queue<ExpressionPtr> expressions;
493 for (auto const& c : *list_) {
494 if (!c->getTest().empty()) {
495 ExpressionPtr match_expr = boost::make_shared<Expression>();
496 ExpressionParser parser;
498 if (dynamic_cast<TemplateClientClassDef*>(c.get())) {
499 parser_type = EvalContext::PARSER_STRING;
500 }
501 parser.parse(match_expr, Element::create(c->getTest()), family,
502 EvalContext::acceptAll, parser_type);
503 expressions.push(match_expr);
504 }
505 }
506 // All expressions successfully initialized. Let's set them for the
507 // client classes in the dictionary.
508 for (auto const& c : *list_) {
509 if (!c->getTest().empty()) {
510 c->setMatchExpr(expressions.front());
511 expressions.pop();
512 }
513 }
514}
515
516void
518 for (auto const& c : *list_) {
519 // If the class has no options, skip it.
520 CfgOptionPtr class_options = c->getCfgOption();
521 if (!class_options || class_options->empty()) {
522 continue;
523 }
524
525 // If the class has no option definitions, use the set
526 // of definitions we were given as is to create its
527 // options.
528 if (!c->getCfgOptionDef()) {
529 class_options->createOptions(external_defs);
530 } else {
531 // Class has its own option definitions, we need a
532 // composite set of definitions to recreate its options.
533 // We make copies of both sets of definitions, then merge
534 // the external defs copy into the class defs copy.
535 // We do this because merging actually effects both sets
536 // of definitions and we cannot alter either set.
537 // Seed the composite set with the class's definitions.
538 CfgOptionDefPtr composite_defs(new CfgOptionDef());
539 c->getCfgOptionDef()->copyTo(*composite_defs);
540
541 // Make a copy of the external definitions and
542 // merge those into the composite set. This should give
543 // us a set of options with class definitions taking
544 // precedence.
545 CfgOptionDefPtr external_defs_copy(new CfgOptionDef());
546 external_defs->copyTo(*external_defs_copy);
547 composite_defs->merge(*external_defs_copy);
548
549 // Now create the class options using the composite
550 // set of definitions.
551 class_options->createOptions(composite_defs);
552 }
553 }
554}
555
559 // Iterate on the map
560 for (auto const& this_class : *list_) {
561 result->add(this_class->toElement());
562 }
563 return (result);
564}
565
568 if (this != &rhs) {
569 list_->clear();
570 map_->clear();
571 for (auto const& cclass : *rhs.list_) {
573 addClass(copy);
574 }
575 }
576 return (*this);
577}
578
580std::list<std::string>
582 // DROP is not in this list because it is special but not built-in.
583 // In fact DROP is set from an expression as callouts can drop
584 // directly the incoming packet. The expression must not depend on
585 // KNOWN/UNKNOWN which are set far after the drop point.
586 // SKIP_DDNS, used by DDNS-tuning is also omitted from this list
587 // so users may assign it a test expression.
588 "ALL", "KNOWN", "UNKNOWN", "BOOTP"
589};
590
597std::list<std::string>
599 "VENDOR_CLASS_", "HA_", "AFTER_", "EXTERNAL_"
600};
601
602bool
603isClientClassBuiltIn(const ClientClass& client_class) {
604 for (auto const& bn : builtinNames) {
605 if (client_class == bn) {
606 return true;
607 }
608 }
609
610 for (auto const& bt : builtinPrefixes) {
611 if (client_class.size() <= bt.size()) {
612 continue;
613 }
614 auto mis = std::mismatch(bt.cbegin(), bt.cend(), client_class.cbegin());
615 if (mis.first == bt.cend()) {
616 return true;
617 }
618 }
619
620 return false;
621}
622
623bool
625 bool& depend_on_known,
626 const ClientClass& client_class) {
627 // First check built-in classes
628 if (isClientClassBuiltIn(client_class)) {
629 // Check direct dependency on [UN]KNOWN
630 if ((client_class == "KNOWN") || (client_class == "UNKNOWN")) {
631 depend_on_known = true;
632 }
633 return (true);
634 }
635
636 // Second check already defined, i.e. in the dictionary
637 ClientClassDefPtr def = class_dictionary->findClass(client_class);
638 if (def) {
639 // Check indirect dependency on [UN]KNOWN
640 if (def->getDependOnKnown()) {
641 depend_on_known = true;
642 }
643 return (true);
644 }
645
646 // Not defined...
647 return (false);
648}
649
650} // namespace isc::dhcp
651} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
This class represents configuration element which is associated with database identifier,...
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:25
Represents option definitions used by the DHCP server.
Represents option data configuration for the DHCP server.
Definition cfg_option.h:352
Embodies a single client class definition.
bool equals(const ClientClassDef &other) const
Compares two ClientClassDef objects for equality.
bool getRequired() const
Fetches the only if required flag.
void setCfgOption(const CfgOptionPtr &cfg_option)
Sets the class's option collection.
void setName(const std::string &name)
Sets the class's name.
bool dependOnClass(const std::string &name) const
Checks direct dependency.
bool getDependOnKnown() const
Fetches the depend on known flag aka use host flag.
void setRequired(bool required)
Sets the only if required flag.
virtual void test(PktPtr pkt, const ExpressionPtr &expr_ptr)
Test method which checks if the packet belongs to the class.
const CfgOptionDefPtr & getCfgOptionDef() const
Fetches the class's option definitions.
ClientClassDef(const std::string &name, const ExpressionPtr &match_expr, const CfgOptionPtr &options=CfgOptionPtr())
Constructor.
const ExpressionPtr & getMatchExpr() const
Fetches the class's match expression.
void setCfgOptionDef(const CfgOptionDefPtr &cfg_option_def)
Sets the class's option definition collection.
virtual ~ClientClassDef()
Destructor.
std::string getName() const
Fetches the class's name.
const CfgOptionPtr & getCfgOption() const
Fetches the class's option collection.
void setMatchExpr(const ExpressionPtr &match_expr)
Sets the class's match expression.
void setTest(const std::string &test)
Sets the class's original match expression.
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
std::string getTest() const
Fetches the class's original match expression.
void setDependOnKnown(bool depend_on_known)
Sets the depend on known flag aka use host flag.
Maintains a list of ClientClassDef's.
ClientClassDefPtr findClass(const std::string &name) const
Fetches the class definition for a given class name.
bool equals(const ClientClassDictionary &other) const
Compares two ClientClassDictionary objects for equality.
void removeClass(const std::string &name)
Removes a given class definition from the dictionary.
bool empty() const
Checks if the class dictionary is empty.
bool dependOnClass(const std::string &name, std::string &dependent_class) const
Checks direct dependency.
const ClientClassDefListPtr & getClasses() const
Fetches the dictionary's list of classes.
ClientClassDictionary & operator=(const ClientClassDictionary &rhs)
Copy assignment operator.
void createOptions(const CfgOptionDefPtr &cfg_option_def)
Iterates over the classes in the dictionary and recreates the options.
void addClass(const std::string &name, const ExpressionPtr &match_expr, const std::string &test, bool required, bool depend_on_known, const CfgOptionPtr &options, CfgOptionDefPtr defs=CfgOptionDefPtr(), isc::data::ConstElementPtr user_context=isc::data::ConstElementPtr(), asiolink::IOAddress next_server=asiolink::IOAddress("0.0.0.0"), const std::string &sname=std::string(), const std::string &filename=std::string(), const util::Triplet< uint32_t > &valid=util::Triplet< uint32_t >(), const util::Triplet< uint32_t > &preferred=util::Triplet< uint32_t >(), bool is_template=false, const util::Optional< uint32_t > &offer_lft=util::Optional< uint32_t >())
Adds a new class to the list.
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
void initMatchExpr(uint16_t family)
Iterates over the classes in the dictionary and ensures that that match expressions are initialized.
Error that occurs when an attempt is made to add a duplicate class to a class dictionary.
Parser for a logical expression.
void parse(ExpressionPtr &expression, isc::data::ConstElementPtr expression_cfg, uint16_t family, isc::eval::EvalContext::CheckDefined check_defined=isc::eval::EvalContext::acceptAll, isc::eval::EvalContext::ParserType parser_type=isc::eval::EvalContext::PARSER_BOOL)
Parses an expression configuration element into an Expression.
static const std::string SPAWN_CLASS_PREFIX
This is a prefix added to the spawned class name.
TemplateClientClassDef(const std::string &name, const ExpressionPtr &match_expr, const CfgOptionPtr &options=CfgOptionPtr())
Constructor.
virtual void test(PktPtr pkt, const ExpressionPtr &expr_ptr) override
Test method which checks if the packet belongs to the class.
virtual isc::data::ElementPtr toElement() const override
Unparse a configuration object.
ParserType
Specifies what type of expression the parser is expected to see.
@ PARSER_BOOL
expression is expected to evaluate to bool
@ PARSER_STRING
expression is expected to evaluate to string
static bool acceptAll(const ClientClass &client_class)
Accept all client class names.
A template representing an optional value.
Definition optional.h:36
T get() const
Retrieves the encapsulated value.
Definition optional.h:114
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition optional.h:136
This template specifies a parameter value.
Definition triplet.h:37
T get(T hint) const
Returns value with a hint.
Definition triplet.h:99
T getMax() const
Returns a maximum allowed value.
Definition triplet.h:112
T getMin() const
Returns a minimum allowed value.
Definition triplet.h:85
Defines classes for storing client class definitions.
Parsers for client class definitions.
const Name & name_
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition data.cc:1420
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition pkt.h:982
std::string ClientClass
Defines a single class name.
Definition classify.h:42
std::vector< ClientClassDefPtr > ClientClassDefList
Defines a list of ClientClassDefPtr's, using insert order.
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition cfg_option.h:803
const isc::log::MessageID EVAL_RESULT
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
std::string evaluateString(const Expression &expr, Pkt &pkt)
Definition evaluate.cc:27
std::list< std::string > builtinPrefixes
The prefixes used to check if a class is BuiltIn class.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition dhcpsrv_log.h:38
boost::shared_ptr< Expression > ExpressionPtr
Definition token.h:31
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
boost::shared_ptr< ClientClassDefList > ClientClassDefListPtr
Defines a pointer to a ClientClassDefList.
bool evaluateBool(const Expression &expr, Pkt &pkt)
Evaluate a RPN expression for a v4 or v6 packet and return a true or false decision.
Definition evaluate.cc:14
bool isClientClassDefined(ClientClassDictionaryPtr &class_dictionary, bool &depend_on_known, const ClientClass &client_class)
Check if a client class name is already defined, i.e.
std::vector< TokenPtr > Expression
This is a structure that holds an expression converted to RPN.
Definition token.h:29
bool isClientClassBuiltIn(const ClientClass &client_class)
Check if a client class name is builtin.
bool dependOnClass(const TokenPtr &token, const std::string &name)
Checks dependency on a token.
Definition dependency.cc:15
std::list< std::string > builtinNames
List of classes for which test expressions cannot be defined.
std::unordered_map< std::string, ClientClassDefPtr > ClientClassDefMap
Defines a map of ClientClassDef's, keyed by the class name.
Defines the logger used by the top-level component of kea-lfc.
Abstract class for configuration Cfg_* classes.
Base class for user context.
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.