Kea 3.3.1
client_class_def.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2026 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)
29 : UserContext(), CfgToElement(), StampedElement(), name_(name),
30 match_expr_(match_expr), additional_(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_), additional_(rhs.additional_),
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 (additional_);
106}
107
108void
110 additional_ = additional;
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);
150 .arg(pkt->getLabel())
151 .arg(getName())
152 .arg(status ? "true" : "false");
153 if (status) {
154 // Matching: add the class
155 pkt->addClass(getName());
156 }
157 } catch (const Exception& ex) {
159 .arg(pkt->getLabel())
160 .arg(getName())
161 .arg(ex.what());
162 }
163}
164
165const std::string TemplateClientClassDef::SPAWN_CLASS_PREFIX("SPAWN_");
166
168 const ExpressionPtr& match_expr,
169 const CfgOptionPtr& options) :
170 ClientClassDef(name, match_expr, options) {
171}
172
173void
175 // Evaluate the expression which can return false (no match),
176 // true (match) or raise an exception (error)
177 try {
178 std::string subclass = evaluateString(*expr_ptr, *pkt);
179 if (!subclass.empty()) {
180 subclass = ClientClasses::escape(subclass);
182 .arg(pkt->getLabel())
183 .arg(getName())
184 .arg(subclass);
185 // Matching: add the subclass
187 value += getName();
188 value += "_";
189 value += subclass;
190 pkt->addSubClass(getName(), value);
191 }
192 } catch (const Exception& ex) {
194 .arg(pkt->getLabel())
195 .arg(getName())
196 .arg(ex.what());
197 }
198}
199
200bool
201ClientClassDef::dependOnClass(const std::string& name) const {
202 return (isc::dhcp::dependOnClass(match_expr_, name));
203}
204
205bool
207 return ((name_ == other.name_) &&
208 ((!match_expr_ && !other.match_expr_) ||
209 (match_expr_ && other.match_expr_ &&
210 (*match_expr_ == *other.match_expr_))) &&
211 ((!cfg_option_ && !other.cfg_option_) ||
212 (cfg_option_ && other.cfg_option_ &&
213 (*cfg_option_ == *other.cfg_option_))) &&
214 ((!cfg_option_def_ && !other.cfg_option_def_) ||
215 (cfg_option_def_ && other.cfg_option_def_ &&
216 (*cfg_option_def_ == *other.cfg_option_def_))) &&
217 (additional_ == other.additional_) &&
218 (depend_on_known_ == other.depend_on_known_) &&
219 (next_server_ == other.next_server_) &&
220 (sname_ == other.sname_) &&
221 (filename_ == other.filename_));
222}
223
226 uint16_t family = CfgMgr::instance().getFamily();
228 // Set user-context
229 contextToElement(result);
230 // Set name
231 result->set("name", Element::create(name_));
232 // Set original match expression (empty string won't parse)
233 if (!test_.empty()) {
234 result->set("test", Element::create(test_));
235 }
236 // Set only-in-additional-list
237 if (additional_) {
238 result->set("only-in-additional-list", Element::create(additional_));
239 }
240 // Set option-def (used only by DHCPv4)
241 if (cfg_option_def_ && (family == AF_INET)) {
242 result->set("option-def", cfg_option_def_->toElement());
243 result->set("option-data", cfg_option_->toElement(cfg_option_def_));
244 } else {
245 // Set option-data
246 result->set("option-data", cfg_option_->toElement());
247 }
248
249 if (family == AF_INET) {
250 // V4 only
251 // Set next-server
252 result->set("next-server", Element::create(next_server_.toText()));
253 // Set server-hostname
254 result->set("server-hostname", Element::create(sname_));
255 // Set boot-file-name
256 result->set("boot-file-name", Element::create(filename_));
257
258 // Set offer-lifetime
259 if (!offer_lft_.unspecified()) {
260 result->set("offer-lifetime",
261 Element::create(static_cast<long long>(offer_lft_.get())));
262 }
263 } else {
264 // V6 only
265 // Set preferred-lifetime
266 if (!preferred_.unspecified()) {
267 result->set("preferred-lifetime",
268 Element::create(static_cast<long long>(preferred_.get())));
269 }
270
271 if (preferred_.getMin() < preferred_.get()) {
272 result->set("min-preferred-lifetime",
273 Element::create(static_cast<long long>(preferred_.getMin())));
274 }
275
276 if (preferred_.getMax() > preferred_.get()) {
277 result->set("max-preferred-lifetime",
278 Element::create(static_cast<long long>(preferred_.getMax())));
279 }
280 }
281
282 // Set valid-lifetime
283 if (!valid_.unspecified()) {
284 result->set("valid-lifetime",
285 Element::create(static_cast<long long>(valid_.get())));
286
287 if (valid_.getMin() < valid_.get()) {
288 result->set("min-valid-lifetime",
289 Element::create(static_cast<long long>(valid_.getMin())));
290 }
291
292 if (valid_.getMax() > valid_.get()) {
293 result->set("max-valid-lifetime",
294 Element::create(static_cast<long long>(valid_.getMax())));
295 }
296 }
297
298 return (result);
299}
300
303 auto const& result = ClientClassDef::toElement();
304 auto const& test = result->get("test");
305 if (test) {
306 result->set("template-test", test);
307 result->remove("test");
308 } else {
309 result->set("template-test", Element::create(""));
310 }
311 return (result);
312}
313
314std::ostream& operator<<(std::ostream& os, const ClientClassDef& x) {
315 os << "ClientClassDef:" << x.getName();
316 return (os);
317}
318
319//********** ClientClassDictionary ******************//
320
324
326 : map_(new ClientClassDefMap()), list_(new ClientClassDefList()) {
327 for (auto const& cclass : *rhs.list_) {
328 ClientClassDefPtr copy(new ClientClassDef(*cclass));
329 addClass(copy);
330 }
331}
332
335
336void
337ClientClassDictionary::addClass(const std::string& name,
338 const ExpressionPtr& match_expr,
339 const std::string& test,
340 bool additional,
341 bool depend_on_known,
342 const CfgOptionPtr& cfg_option,
343 CfgOptionDefPtr cfg_option_def,
344 ConstElementPtr user_context,
345 asiolink::IOAddress next_server,
346 const std::string& sname,
347 const std::string& filename,
348 const util::Triplet<uint32_t>& valid,
349 const util::Triplet<uint32_t>& preferred,
350 bool is_template,
351 const util::Optional<uint32_t>& offer_lft) {
352 ClientClassDefPtr cclass;
353 if (is_template) {
354 cclass.reset(new TemplateClientClassDef(name, match_expr, cfg_option));
355 } else {
356 cclass.reset(new ClientClassDef(name, match_expr, cfg_option));
357 }
358 cclass->setTest(test);
359 cclass->setAdditional(additional);
360 cclass->setDependOnKnown(depend_on_known);
361 cclass->setCfgOptionDef(cfg_option_def);
362 cclass->setContext(user_context),
363 cclass->setNextServer(next_server);
364 cclass->setSname(sname);
365 cclass->setFilename(filename);
366 cclass->setValid(valid);
367 cclass->setPreferred(preferred);
368 cclass->setOfferLft(offer_lft);
369 addClass(cclass);
370}
371
372void
374 if (!class_def) {
375 isc_throw(BadValue, "ClientClassDictionary::addClass "
376 " - class definition cannot be null");
377 }
378
379 if (findClass(class_def->getName())) {
380 isc_throw(DuplicateClientClassDef, "Client Class: "
381 << class_def->getName() << " has already been defined");
382 }
383
384 list_->push_back(class_def);
385 (*map_)[class_def->getName()] = class_def;
386}
387
389ClientClassDictionary::findClass(const std::string& name) const {
390 ClientClassDefMap::iterator it = map_->find(name);
391 if (it != map_->end()) {
392 return (*it).second;
393 }
394
395 return (ClientClassDefPtr());
396}
397
398void
399ClientClassDictionary::removeClass(const std::string& name) {
400 for (ClientClassDefList::iterator this_class = list_->begin();
401 this_class != list_->end(); ++this_class) {
402 if ((*this_class)->getName() == name) {
403 list_->erase(this_class);
404 break;
405 }
406 }
407 map_->erase(name);
408}
409
410void
412 // Class id equal to 0 means it wasn't set.
413 if (id == 0) {
414 return;
415 }
416 for (ClientClassDefList::iterator this_class = list_->begin();
417 this_class != list_->end(); ++this_class) {
418 if ((*this_class)->getId() == id) {
419 map_->erase((*this_class)->getName());
420 list_->erase(this_class);
421 break;
422 }
423 }
424}
425
428 return (list_);
429}
430
431bool
433 return (list_->empty());
434}
435
436bool
438 std::string& dependent_class) const {
439 // Skip previous classes as they should not depend on name.
440 bool found = false;
441 for (auto const& this_class : *list_) {
442 if (found) {
443 if (this_class->dependOnClass(name)) {
444 dependent_class = this_class->getName();
445 return (true);
446 }
447 } else {
448 if (this_class->getName() == name) {
449 found = true;
450 }
451 }
452 }
453 return (false);
454}
455
456bool
458 if (list_->size() != other.list_->size()) {
459 return (false);
460 }
461
462 ClientClassDefList::const_iterator this_class = list_->cbegin();
463 ClientClassDefList::const_iterator other_class = other.list_->cbegin();
464 while (this_class != list_->cend() &&
465 other_class != other.list_->cend()) {
466 if (!*this_class || !*other_class ||
467 **this_class != **other_class) {
468 return false;
469 }
470
471 ++this_class;
472 ++other_class;
473 }
474
475 return (true);
476}
477
478void
480 std::queue<ExpressionPtr> expressions;
481 for (auto const& c : *list_) {
482 if (!c->getTest().empty()) {
483 ExpressionPtr match_expr = boost::make_shared<Expression>();
484 ExpressionParser parser;
486 if (dynamic_cast<TemplateClientClassDef*>(c.get())) {
487 parser_type = EvalContext::PARSER_STRING;
488 }
489 parser.parse(match_expr, Element::create(c->getTest()), family,
490 EvalContext::acceptAll, parser_type);
491 expressions.push(match_expr);
492 }
493 }
494 // All expressions successfully initialized. Let's set them for the
495 // client classes in the dictionary.
496 for (auto const& c : *list_) {
497 if (!c->getTest().empty()) {
498 c->setMatchExpr(expressions.front());
499 expressions.pop();
500 }
501 }
502}
503
504void
506 for (auto const& c : *list_) {
507 // If the class has no options, skip it.
508 CfgOptionPtr class_options = c->getCfgOption();
509 if (!class_options || class_options->empty()) {
510 continue;
511 }
512
513 // If the class has no option definitions, use the set
514 // of definitions we were given as is to create its
515 // options.
516 if (!c->getCfgOptionDef()) {
517 class_options->createOptions(external_defs);
518 } else {
519 // Class has its own option definitions, we need a
520 // composite set of definitions to recreate its options.
521 // We make copies of both sets of definitions, then merge
522 // the external defs copy into the class defs copy.
523 // We do this because merging actually effects both sets
524 // of definitions and we cannot alter either set.
525 // Seed the composite set with the class's definitions.
526 CfgOptionDefPtr composite_defs(new CfgOptionDef());
527 c->getCfgOptionDef()->copyTo(*composite_defs);
528
529 // Make a copy of the external definitions and
530 // merge those into the composite set. This should give
531 // us a set of options with class definitions taking
532 // precedence.
533 CfgOptionDefPtr external_defs_copy(new CfgOptionDef());
534 external_defs->copyTo(*external_defs_copy);
535 composite_defs->merge(*external_defs_copy);
536
537 // Now create the class options using the composite
538 // set of definitions.
539 class_options->createOptions(composite_defs);
540 }
541 }
542}
543
544void
546 for (auto const& c : *list_) {
547 CfgOptionPtr class_options = c->getCfgOption();
548 if (class_options) {
549 class_options->encapsulate();
550 }
551 }
552}
553
557 // Iterate on the map
558 for (auto const& this_class : *list_) {
559 result->add(this_class->toElement());
560 }
561 return (result);
562}
563
566 if (this != &rhs) {
567 list_->clear();
568 map_->clear();
569 for (auto const& cclass : *rhs.list_) {
571 addClass(copy);
572 }
573 }
574 return (*this);
575}
576
578std::list<std::string>
580
581 // DROP and REJECT are not in this list because they are special
582 // but not built-in. SKIP_DDNS, used by DDNS-tuning is also
583 // omitted from this list so users may assign it a test expression.
584 "ALL", "KNOWN", "UNKNOWN", "BOOTP"
585};
586
593std::list<std::string>
595 "VENDOR_CLASS_", "HA_", "AFTER_", "EXTERNAL_"
596};
597
598bool
599isClientClassBuiltIn(const ClientClass& client_class) {
600 for (auto const& bn : builtinNames) {
601 if (client_class == bn) {
602 return true;
603 }
604 }
605
606 for (auto const& bt : builtinPrefixes) {
607 if (client_class.size() <= bt.size()) {
608 continue;
609 }
610 auto mis = std::mismatch(bt.cbegin(), bt.cend(), client_class.cbegin());
611 if (mis.first == bt.cend()) {
612 return true;
613 }
614 }
615
616 return false;
617}
618
619bool
621 bool& depend_on_known,
622 const ClientClass& client_class) {
623 // First check built-in classes
624 if (isClientClassBuiltIn(client_class)) {
625 // Check direct dependency on [UN]KNOWN
626 if ((client_class == "KNOWN") || (client_class == "UNKNOWN")) {
627 depend_on_known = true;
628 }
629 return (true);
630 }
631
632 // Second check already defined, i.e. in the dictionary
633 ClientClassDefPtr def = class_dictionary->findClass(client_class);
634 if (def) {
635 // Check indirect dependency on [UN]KNOWN
636 if (def->getDependOnKnown()) {
637 depend_on_known = true;
638 }
639 return (true);
640 }
641
642 // Not defined...
643 return (false);
644}
645
646} // namespace isc::dhcp
647} // 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.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:300
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:355
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:350
uint16_t getFamily() const
Returns address family.
Definition cfgmgr.h:246
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
Represents option definitions used by the DHCP server.
Represents option data configuration for the DHCP server.
Definition cfg_option.h:405
Embodies a single client class definition.
void setAdditional(bool additional)
Sets the only if additional flag.
bool equals(const ClientClassDef &other) const
Compares two ClientClassDef objects for equality.
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.
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.
bool getAdditional() const
Fetches the only if additional flag.
void setDependOnKnown(bool depend_on_known)
Sets the depend on known flag aka use host flag.
Maintains a list of ClientClassDef's.
void addClass(const std::string &name, const ExpressionPtr &match_expr, const std::string &test, bool additional, 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.
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 encapsulateOptions() const
Iterates over the classes in the dictionary and encapsulates suboptions.
void createOptions(const CfgOptionDefPtr &cfg_option_def)
Iterates over the classes in the dictionary and recreates the options.
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.
static std::string escape(const std::string &name, bool escape_escape=true)
Escape a client class name.
Definition classify.cc:164
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:37
This template specifies a parameter value.
Definition triplet.h:37
Defines classes for storing client class definitions.
Parsers for client class definitions.
if(!(yy_init))
Definition d2_lexer.cc:1515
#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_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
Definition data.cc:1543
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
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:1005
std::string ClientClass
Defines a single class name.
Definition classify.h:45
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:983
const isc::log::MessageID DHCPSRV_EVAL_ERROR
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
const isc::log::MessageID DHCPSRV_TEMPLATE_EVAL_RESULT
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
std::string evaluateString(const Expression &expr, Pkt &pkt)
Evaluate a RPN expression for a v4 or v6 packet and return a string value.
Definition evaluate.cc:45
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
const isc::log::MessageID DHCPSRV_TEMPLATE_EVAL_ERROR
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:34
bool isClientClassDefined(ClientClassDictionaryPtr &class_dictionary, bool &depend_on_known, const ClientClass &client_class)
Check if a client class name is already defined, i.e.
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.
const isc::log::MessageID DHCPSRV_EVAL_RESULT
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.