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