Kea  2.5.2
token.cc
Go to the documentation of this file.
1 // Copyright (C) 2015-2023 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/token.h>
10 #include <eval/eval_log.h>
11 #include <eval/eval_context.h>
12 #include <util/encode/hex.h>
13 #include <util/io_utilities.h>
14 #include <asiolink/io_address.h>
15 #include <dhcp/pkt4.h>
16 #include <dhcp/pkt6.h>
17 #include <boost/lexical_cast.hpp>
18 #include <dhcp/dhcp4.h>
19 #include <dhcp/dhcp6.h>
20 #include <dhcp/option_vendor.h>
22 
23 #include <boost/algorithm/string.hpp>
24 #include <boost/algorithm/string/classification.hpp>
25 #include <boost/algorithm/string/split.hpp>
26 
27 #include <cstring>
28 #include <string>
29 #include <iomanip>
30 #include <sstream>
31 
32 using namespace isc::asiolink;
33 using namespace isc::dhcp;
34 using namespace isc::util;
35 using namespace std;
36 
38 
39 void
40 TokenString::evaluate(Pkt& /*pkt*/, ValueStack& values) {
41  // Literals only push, nothing to pop
42  values.push(value_);
43 
44  // Log what we pushed
46  .arg('\'' + value_ + '\'');
47 }
48 
49 TokenHexString::TokenHexString(const string& str) : value_("") {
50  // Check string starts "0x" or "0x" and has at least one additional character.
51  if ((str.size() < 3) ||
52  (str[0] != '0') ||
53  ((str[1] != 'x') && (str[1] != 'X'))) {
54  return;
55  }
56  string digits = str.substr(2);
57 
58  // Transform string of hexadecimal digits into binary format
59  vector<uint8_t> binary;
60  try {
61  // The decodeHex function expects that the string contains an
62  // even number of digits. If we don't meet this requirement,
63  // we have to insert a leading 0.
64  if ((digits.length() % 2) != 0) {
65  digits = digits.insert(0, "0");
66  }
67  util::encode::decodeHex(digits, binary);
68  } catch (...) {
69  return;
70  }
71 
72  // Convert to a string (note that binary.size() cannot be 0)
73  value_.resize(binary.size());
74  memmove(&value_[0], &binary[0], binary.size());
75 }
76 
77 void
79  // Literals only push, nothing to pop
80  values.push(value_);
81 
82  // Log what we pushed
84  .arg(toHex(value_));
85 }
86 
87 void
89  if (values.size() == 0) {
90  isc_throw(EvalBadStack, "Incorrect empty stack.");
91  }
92 
93  string op = values.top();
94 
95  values.pop();
96  string result(boost::algorithm::to_lower_copy(op));
97  values.push(result);
98 
99  // Log what we pushed
101  .arg('\'' + op + '\'')
102  .arg('\'' + result + '\'');
103 }
104 
105 void
107  if (values.size() == 0) {
108  isc_throw(EvalBadStack, "Incorrect empty stack.");
109  }
110 
111  string op = values.top();
112 
113  values.pop();
114  string result(boost::algorithm::to_upper_copy(op));
115  values.push(result);
116 
117  // Log what we pushed
119  .arg('\'' + op + '\'')
120  .arg('\'' + result + '\'');
121 }
122 
123 TokenIpAddress::TokenIpAddress(const string& addr) : value_("") {
124  // Transform IP address into binary format
125  vector<uint8_t> binary;
126  try {
127  asiolink::IOAddress ip(addr);
128  binary = ip.toBytes();
129  } catch (...) {
130  return;
131  }
132 
133  // Convert to a string (note that binary.size() is 4 or 16, so not 0)
134  value_.resize(binary.size());
135  memmove(&value_[0], &binary[0], binary.size());
136 }
137 
138 void
140  // Literals only push, nothing to pop
141  values.push(value_);
142 
143  // Log what we pushed
145  .arg(toHex(value_));
146 }
147 
148 void
150  if (values.size() == 0) {
151  isc_throw(EvalBadStack, "Incorrect empty stack.");
152  }
153 
154  string op = values.top();
155  size_t size = op.size();
156 
157  if (!size) {
158  return;
159  }
160 
161  values.pop();
162 
163  if ((size != V4ADDRESS_LEN) && (size != V6ADDRESS_LEN)) {
164  isc_throw(EvalTypeError, "Can not convert to valid address.");
165  }
166 
167  std::vector<uint8_t> binary(op.begin(), op.end());
168 
169  if (size == V4ADDRESS_LEN) {
170  op = asiolink::IOAddress::fromBytes(AF_INET, binary.data()).toText();
171  } else {
172  op = asiolink::IOAddress::fromBytes(AF_INET6, binary.data()).toText();
173  }
174 
175  values.push(op);
176 
177  // Log what we pushed
179  .arg(op);
180 }
181 
182 void
184  if (values.size() == 0) {
185  isc_throw(EvalBadStack, "Incorrect empty stack.");
186  }
187 
188  string op = values.top();
189  size_t size = op.size();
190 
191  if (!size) {
192  return;
193  }
194 
195  values.pop();
196 
197  if (size != sizeof(int8_t)) {
198  isc_throw(EvalTypeError, "Can not convert to valid int8.");
199  }
200 
201  stringstream tmp;
202  tmp << static_cast<int32_t>(*(reinterpret_cast<const int8_t*>(op.data())));
203  op = tmp.str();
204  values.push(op);
205 
206  // Log what we pushed
208  .arg(op);
209 }
210 
211 void
213  if (values.size() == 0) {
214  isc_throw(EvalBadStack, "Incorrect empty stack.");
215  }
216 
217  string op = values.top();
218  size_t size = op.size();
219 
220  if (!size) {
221  return;
222  }
223 
224  values.pop();
225 
226  if (size != sizeof(int16_t)) {
227  isc_throw(EvalTypeError, "Can not convert to valid int16.");
228  }
229 
230  stringstream tmp;
231  int16_t value = static_cast<int16_t>(readUint16(const_cast<const char*>(op.data()), size));
232  tmp << value;
233  op = tmp.str();
234  values.push(op);
235 
236  // Log what we pushed
238  .arg(op);
239 }
240 
241 void
243  if (values.size() == 0) {
244  isc_throw(EvalBadStack, "Incorrect empty stack.");
245  }
246 
247  string op = values.top();
248  size_t size = op.size();
249 
250  if (!size) {
251  return;
252  }
253 
254  values.pop();
255 
256  if (size != sizeof(int32_t)) {
257  isc_throw(EvalTypeError, "Can not convert to valid int32.");
258  }
259 
260  stringstream tmp;
261  int32_t value = static_cast<int32_t>(readUint32(const_cast<const char*>(op.data()), size));
262  tmp << value;
263  op = tmp.str();
264  values.push(op);
265 
266  // Log what we pushed
268  .arg(op);
269 }
270 
271 void
273  if (values.size() == 0) {
274  isc_throw(EvalBadStack, "Incorrect empty stack.");
275  }
276 
277  string op = values.top();
278  size_t size = op.size();
279 
280  if (!size) {
281  return;
282  }
283 
284  values.pop();
285 
286  if (size != sizeof(uint8_t)) {
287  isc_throw(EvalTypeError, "Can not convert to valid uint8.");
288  }
289 
290  stringstream tmp;
291  tmp << static_cast<uint32_t>(*(reinterpret_cast<const uint8_t*>(op.data())));
292  op = tmp.str();
293  values.push(op);
294 
295  // Log what we pushed
297  .arg(op);
298 }
299 
300 void
302  if (values.size() == 0) {
303  isc_throw(EvalBadStack, "Incorrect empty stack.");
304  }
305 
306  string op = values.top();
307  size_t size = op.size();
308 
309  if (!size) {
310  return;
311  }
312 
313  values.pop();
314 
315  if (size != sizeof(uint16_t)) {
316  isc_throw(EvalTypeError, "Can not convert to valid uint16.");
317  }
318 
319  stringstream tmp;
320  uint16_t value = readUint16(const_cast<const char*>(op.data()), size);
321  tmp << value;
322  op = tmp.str();
323  values.push(op);
324 
325  // Log what we pushed
327  .arg(op);
328 }
329 
330 void
332  if (values.size() == 0) {
333  isc_throw(EvalBadStack, "Incorrect empty stack.");
334  }
335 
336  string op = values.top();
337  size_t size = op.size();
338 
339  if (!size) {
340  return;
341  }
342 
343  values.pop();
344 
345  if (size != sizeof(uint32_t)) {
346  isc_throw(EvalTypeError, "Can not convert to valid uint32.");
347  }
348 
349  stringstream tmp;
350  uint32_t value = readUint32(const_cast<const char*>(op.data()), size);
351  tmp << value;
352  op = tmp.str();
353  values.push(op);
354 
355  // Log what we pushed
357  .arg(op);
358 }
359 
360 OptionPtr
362  return (pkt.getOption(option_code_));
363 }
364 
365 void
367  OptionPtr opt = getOption(pkt);
368  std::string opt_str;
369  if (opt) {
370  if (representation_type_ == TEXTUAL) {
371  opt_str = opt->toString();
372  } else if (representation_type_ == HEXADECIMAL) {
373  std::vector<uint8_t> binary = opt->toBinary();
374  opt_str.resize(binary.size());
375  if (!binary.empty()) {
376  memmove(&opt_str[0], &binary[0], binary.size());
377  }
378  } else {
379  opt_str = "true";
380  }
381  } else if (representation_type_ == EXISTS) {
382  opt_str = "false";
383  }
384 
385  // Push value of the option or empty string if there was no such option
386  // in the packet.
387  values.push(opt_str);
388 
389  // Log what we pushed, both exists and textual are simple text
390  // and can be output directly. We also include the code number
391  // of the requested option.
394  .arg(option_code_)
395  .arg(toHex(opt_str));
396  } else {
398  .arg(option_code_)
399  .arg('\'' + opt_str + '\'');
400  }
401 }
402 
403 std::string
405  std::string txt;
406  if (representation_type_ == EXISTS) {
407  txt = "false";
408  }
409  values.push(txt);
410  return (txt);
411 }
412 
413 TokenRelay4Option::TokenRelay4Option(const uint16_t option_code,
414  const RepresentationType& rep_type)
415  : TokenOption(option_code, rep_type) {
416 }
417 
419  // Check if there is Relay Agent Option.
421  if (!rai) {
422  return (OptionPtr());
423  }
424 
425  // If there is, try to return its suboption
426  return (rai->getOption(option_code_));
427 }
428 
430  try {
431  // Check if it's a Pkt6. If it's not the dynamic_cast will
432  // throw std::bad_cast.
433  Pkt6& pkt6 = dynamic_cast<Pkt6&>(pkt);
434 
435  try {
436  // Now that we have the right type of packet we can
437  // get the option and return it.
438  if (nest_level_ >= 0) {
439  uint8_t nesting_level = static_cast<uint8_t>(nest_level_);
440  return(pkt6.getRelayOption(option_code_, nesting_level));
441  } else {
442  int nesting_level = pkt6.relay_info_.size() + nest_level_;
443  if (nesting_level < 0) {
444  return (OptionPtr());
445  }
446  return(pkt6.getRelayOption(option_code_,
447  static_cast<uint8_t>(nesting_level)));
448  }
449  }
450  catch (const isc::OutOfRange&) {
451  // The only exception we expect is OutOfRange if the nest
452  // level is out of range of the encapsulations, for example
453  // if nest_level_ is 4 and there are only 2 encapsulations.
454  // We return a NULL in that case.
455  return (OptionPtr());
456  }
457 
458  } catch (const std::bad_cast&) {
459  isc_throw(EvalTypeError, "Specified packet is not Pkt6");
460  }
461 
462 }
463 
464 void
466  string value;
467  vector<uint8_t> binary;
468  string type_str;
469  bool is_binary = true;
470  bool print_hex = true;
471  switch (type_) {
472  case IFACE:
473  is_binary = false;
474  print_hex = false;
475  value = pkt.getIface();
476  type_str = "iface";
477  break;
478  case SRC:
479  binary = pkt.getRemoteAddr().toBytes();
480  type_str = "src";
481  break;
482  case DST:
483  binary = pkt.getLocalAddr().toBytes();
484  type_str = "dst";
485  break;
486  case LEN:
487  // len() returns a size_t but in fact it can't be very large
488  // (with UDP transport it fits in 16 bits)
489  // the len() method is not const because of DHCPv6 relays.
490  // We assume here it has no bad side effects...
491  value = EvalContext::fromUint32(static_cast<uint32_t>(const_cast<Pkt&>(pkt).len()));
492  is_binary = false;
493  type_str = "len";
494  break;
495 
496  default:
497  isc_throw(EvalTypeError, "Bad meta data specified: " << static_cast<int>(type_));
498  }
499 
500  if (is_binary) {
501  value.resize(binary.size());
502  if (!binary.empty()) {
503  memmove(&value[0], &binary[0], binary.size());
504  }
505  }
506  values.push(value);
507 
508  // Log what we pushed
510  .arg(type_str)
511  .arg(print_hex ? toHex(value) : value);
512 }
513 
514 void
516  vector<uint8_t> binary;
517  string value;
518  string type_str;
519  try {
520  // Check if it's a Pkt4. If it's not, the dynamic_cast will throw
521  // std::bad_cast (failed dynamic_cast returns NULL for pointers and
522  // throws for references).
523  const Pkt4& pkt4 = dynamic_cast<const Pkt4&>(pkt);
524 
525  switch (type_) {
526  case CHADDR: {
527  HWAddrPtr hwaddr = pkt4.getHWAddr();
528  if (!hwaddr) {
529  // This should never happen. Every Pkt4 should always have
530  // a hardware address.
532  "Packet does not have hardware address");
533  }
534  binary = hwaddr->hwaddr_;
535  type_str = "mac";
536  break;
537  }
538  case GIADDR:
539  binary = pkt4.getGiaddr().toBytes();
540  type_str = "giaddr";
541  break;
542  case CIADDR:
543  binary = pkt4.getCiaddr().toBytes();
544  type_str = "ciaddr";
545  break;
546  case YIADDR:
547  binary = pkt4.getYiaddr().toBytes();
548  type_str = "yiaddr";
549  break;
550  case SIADDR:
551  binary = pkt4.getSiaddr().toBytes();
552  type_str = "siaddr";
553  break;
554  case HLEN:
555  // Pad the uint8_t field to 4 bytes.
556  value = EvalContext::fromUint32(pkt4.getHlen());
557  type_str = "hlen";
558  break;
559  case HTYPE:
560  // Pad the uint8_t field to 4 bytes.
561  value = EvalContext::fromUint32(pkt4.getHtype());
562  type_str = "htype";
563  break;
564  case MSGTYPE:
565  value = EvalContext::fromUint32(pkt4.getType());
566  type_str = "msgtype";
567  break;
568  case TRANSID:
569  value = EvalContext::fromUint32(pkt4.getTransid());
570  type_str = "transid";
571  break;
572  default:
573  isc_throw(EvalTypeError, "Bad field specified: " << static_cast<int>(type_));
574  }
575 
576  } catch (const std::bad_cast&) {
577  isc_throw(EvalTypeError, "Specified packet is not a Pkt4");
578  }
579 
580  if (!binary.empty()) {
581  value.resize(binary.size());
582  memmove(&value[0], &binary[0], binary.size());
583  }
584  values.push(value);
585 
586  // Log what we pushed
588  .arg(type_str)
589  .arg(toHex(value));
590 }
591 
592 void
594  string value;
595  string type_str;
596  try {
597  // Check if it's a Pkt6. If it's not the dynamic_cast will throw
598  // std::bad_cast (failed dynamic_cast returns NULL for pointers and
599  // throws for references).
600  const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
601 
602  switch (type_) {
603  case MSGTYPE: {
604  // msg type is an uint8_t integer. We want a 4 byte string so 0 pad.
605  value = EvalContext::fromUint32(pkt6.getType());
606  type_str = "msgtype";
607  break;
608  }
609  case TRANSID: {
610  // transaction id is an uint32_t integer. We want a 4 byte string so copy
611  value = EvalContext::fromUint32(pkt6.getTransid());
612  type_str = "transid";
613  break;
614  }
615  default:
616  isc_throw(EvalTypeError, "Bad field specified: " << static_cast<int>(type_));
617  }
618 
619  } catch (const std::bad_cast&) {
620  isc_throw(EvalTypeError, "Specified packet is not Pkt6");
621  }
622 
623  values.push(value);
624 
625  // Log what we pushed
627  .arg(type_str)
628  .arg(toHex(value));
629 }
630 
631 void
633  vector<uint8_t> binary;
634  string type_str;
635  try {
636  // Check if it's a Pkt6. If it's not the dynamic_cast will
637  // throw std::bad_cast.
638  const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
639  uint8_t relay_level;
640 
641  try {
642  if (nest_level_ >= 0) {
643  relay_level = static_cast<uint8_t>(nest_level_);
644  } else {
645  int nesting_level = pkt6.relay_info_.size() + nest_level_;
646  if (nesting_level < 0) {
647  // Don't throw OutOfRange here
648  nesting_level = 32;
649  }
650  relay_level = static_cast<uint8_t>(nesting_level);
651  }
652  switch (type_) {
653  // Now that we have the right type of packet we can
654  // get the option and return it.
655  case LINKADDR:
656  type_str = "linkaddr";
657  binary = pkt6.getRelay6LinkAddress(relay_level).toBytes();
658  break;
659  case PEERADDR:
660  type_str = "peeraddr";
661  binary = pkt6.getRelay6PeerAddress(relay_level).toBytes();
662  break;
663  }
664  } catch (const isc::OutOfRange&) {
665  // The only exception we expect is OutOfRange if the nest
666  // level is invalid. We push "" in that case.
667  values.push("");
668  // Log what we pushed
670  .arg(type_str)
671  .arg(int(nest_level_))
672  .arg("0x");
673  return;
674  }
675  } catch (const std::bad_cast&) {
676  isc_throw(EvalTypeError, "Specified packet is not Pkt6");
677  }
678 
679  string value;
680  value.resize(binary.size());
681  if (!binary.empty()) {
682  memmove(&value[0], &binary[0], binary.size());
683  }
684  values.push(value);
685 
686  // Log what we pushed
688  .arg(type_str)
689  .arg(int(nest_level_))
690  .arg(toHex(value));
691 }
692 
693 void
694 TokenEqual::evaluate(Pkt& /*pkt*/, ValueStack& values) {
695  if (values.size() < 2) {
696  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
697  "2 values for == operator, got " << values.size());
698  }
699 
700  string op1 = values.top();
701  values.pop();
702  string op2 = values.top();
703  values.pop(); // Dammit, std::stack interface is awkward.
704 
705  if (op1 == op2)
706  values.push("true");
707  else
708  values.push("false");
709 
710  // Log what we popped and pushed
712  .arg(toHex(op1))
713  .arg(toHex(op2))
714  .arg('\'' + values.top() + '\'');
715 }
716 
717 void
719  if (values.size() < 3) {
720  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
721  "3 values for substring operator, got " << values.size());
722  }
723 
724  string len_str = values.top();
725  values.pop();
726  string start_str = values.top();
727  values.pop();
728  string string_str = values.top();
729  values.pop();
730 
731  // If we have no string to start with we push an empty string and leave
732  if (string_str.empty()) {
733  values.push("");
734 
735  // Log what we popped and pushed
737  .arg(len_str)
738  .arg(start_str)
739  .arg("0x")
740  .arg("0x");
741  return;
742  }
743 
744  // Convert the starting position and length from strings to numbers
745  // the length may also be "all" in which case simply make it the
746  // length of the string.
747  // If we have a problem push an empty string and leave
748  int start_pos;
749  int length;
750  try {
751  start_pos = boost::lexical_cast<int>(start_str);
752  } catch (const boost::bad_lexical_cast&) {
753  isc_throw(EvalTypeError, "the parameter '" << start_str
754  << "' for the starting position of the substring "
755  << "couldn't be converted to an integer.");
756  }
757  try {
758  if (len_str == "all") {
759  length = string_str.length();
760  } else {
761  length = boost::lexical_cast<int>(len_str);
762  }
763  } catch (const boost::bad_lexical_cast&) {
764  isc_throw(EvalTypeError, "the parameter '" << len_str
765  << "' for the length of the substring "
766  << "couldn't be converted to an integer.");
767  }
768 
769  const int string_length = string_str.length();
770  // If the starting position is outside of the string push an
771  // empty string and leave
772  if ((start_pos < -string_length) || (start_pos >= string_length)) {
773  values.push("");
774 
775  // Log what we popped and pushed
777  .arg(len_str)
778  .arg(start_str)
779  .arg(toHex(string_str))
780  .arg("0x");
781  return;
782  }
783 
784  // Adjust the values to be something for substr. We first figure out
785  // the starting position, then update it and the length to get the
786  // characters before or after it depending on the sign of length
787  if (start_pos < 0) {
788  start_pos = string_length + start_pos;
789  }
790 
791  if (length < 0) {
792  length = -length;
793  if (length <= start_pos){
794  start_pos -= length;
795  } else {
796  length = start_pos;
797  start_pos = 0;
798  }
799  }
800 
801  // and finally get the substring
802  values.push(string_str.substr(start_pos, length));
803 
804  // Log what we popped and pushed
806  .arg(len_str)
807  .arg(start_str)
808  .arg(toHex(string_str))
809  .arg(toHex(values.top()));
810 }
811 
812 void
813 TokenSplit::evaluate(Pkt& /*pkt*/, ValueStack& values) {
814  if (values.size() < 3) {
815  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
816  "3 values for split operator, got " << values.size());
817  }
818 
819  // Pop the parameters.
820  string field_str = values.top();
821  values.pop();
822  string delim_str = values.top();
823  values.pop();
824  string string_str = values.top();
825  values.pop();
826 
827  // If we have no string to start with we push an empty string and leave
828  if (string_str.empty()) {
829  values.push("");
830 
831  // Log what we popped and pushed
833  .arg(field_str)
834  .arg(delim_str)
835  .arg(string_str)
836  .arg("0x");
837  return;
838  }
839 
840  // Convert the field position from string to number
841  // If we have a problem push an empty string and leave
842  int field;
843  try {
844  field = boost::lexical_cast<int>(field_str);
845  } catch (const boost::bad_lexical_cast&) {
846  isc_throw(EvalTypeError, "the parameter '" << field_str
847  << "' for the field field for split "
848  << "couldn't be converted to an integer.");
849  }
850 
851  // If we have no delimiter to start with we push the input string and leave
852  if (delim_str.empty()) {
853  values.push(string_str);
854 
855  // Log what we popped and pushed
857  .arg(field_str)
858  .arg(delim_str)
859  .arg(string_str)
860  .arg(toHex(values.top()));
861  return;
862  }
863 
864  // Split the string into fields.
865  std::vector<std::string> fields;
866  boost::split(fields, string_str, boost::is_any_of(delim_str),
867  boost::algorithm::token_compress_off);
868 
869  // Range check the field.
870  if (field < 1 || field > fields.size()) {
871  // Push an empty string if field is out of range.
872  values.push("");
873 
874  // Log what we popped and pushed
876  .arg(field_str)
877  .arg(delim_str)
878  .arg(string_str)
879  .arg("0x");
880  return;
881  }
882 
883  // Push the desired field.
884  values.push(fields[field - 1]);
885 
886  // Log what we popped and pushed
888  .arg(field_str)
889  .arg(delim_str)
890  .arg(string_str)
891  .arg(toHex(values.top()));
892 }
893 
894 void
896  if (values.size() < 2) {
897  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
898  "2 values for concat, got " << values.size());
899  }
900 
901  string op1 = values.top();
902  values.pop();
903  string op2 = values.top();
904  values.pop(); // Dammit, std::stack interface is awkward.
905 
906  // The top of the stack was evaluated last so this is the right order
907  values.push(op2 + op1);
908 
909  // Log what we popped and pushed
911  .arg(toHex(op1))
912  .arg(toHex(op2))
913  .arg(toHex(values.top()));
914 }
915 
916 void
918  if (values.size() < 3) {
919  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
920  "3 values for ifelse, got " << values.size());
921  }
922 
923  string iffalse = values.top();
924  values.pop();
925  string iftrue = values.top();
926  values.pop();
927  string cond = values.top();
928  values.pop();
929  bool val = toBool(cond);
930 
931  if (val) {
932  values.push(iftrue);
933  } else {
934  values.push(iffalse);
935  }
936 
937  // Log what we popped and pushed
938  if (val) {
940  .arg('\'' + cond + '\'')
941  .arg(toHex(iffalse))
942  .arg(toHex(iftrue));
943  } else {
945  .arg('\'' +cond + '\'')
946  .arg(toHex(iftrue))
947  .arg(toHex(iffalse));
948  }
949 }
950 
951 void
953  if (values.size() < 2) {
954  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
955  "2 values for hexstring, got " << values.size());
956  }
957 
958  string separator = values.top();
959  values.pop();
960  string binary = values.top();
961  values.pop();
962 
963  bool first = true;
964  stringstream tmp;
965  tmp << hex;
966  for (size_t i = 0; i < binary.size(); ++i) {
967  if (!first) {
968  tmp << separator;
969  } else {
970  first = false;
971  }
972  tmp << setw(2) << setfill('0')
973  << (static_cast<unsigned>(binary[i]) & 0xff);
974  }
975  values.push(tmp.str());
976 
977  // Log what we popped and pushed
979  .arg(toHex(binary))
980  .arg(separator)
981  .arg(tmp.str());
982 }
983 
984 void
985 TokenNot::evaluate(Pkt& /*pkt*/, ValueStack& values) {
986  if (values.size() == 0) {
987  isc_throw(EvalBadStack, "Incorrect empty stack.");
988  }
989 
990  string op = values.top();
991  values.pop();
992  bool val = toBool(op);
993 
994  if (!val) {
995  values.push("true");
996  } else {
997  values.push("false");
998  }
999 
1000  // Log what we popped and pushed
1002  .arg('\'' + op + '\'')
1003  .arg('\'' + values.top() + '\'');
1004 }
1005 
1006 void
1007 TokenAnd::evaluate(Pkt& /*pkt*/, ValueStack& values) {
1008  if (values.size() < 2) {
1009  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1010  "2 values for and operator, got " << values.size());
1011  }
1012 
1013  string op1 = values.top();
1014  values.pop();
1015  bool val1 = toBool(op1);
1016  string op2 = values.top();
1017  values.pop(); // Dammit, std::stack interface is awkward.
1018  bool val2 = toBool(op2);
1019 
1020  if (val1 && val2) {
1021  values.push("true");
1022  } else {
1023  values.push("false");
1024  }
1025 
1026  // Log what we popped and pushed
1028  .arg('\'' + op1 + '\'')
1029  .arg('\'' + op2 + '\'')
1030  .arg('\'' + values.top() + '\'');
1031 }
1032 
1033 void
1034 TokenOr::evaluate(Pkt& /*pkt*/, ValueStack& values) {
1035  if (values.size() < 2) {
1036  isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1037  "2 values for or operator, got " << values.size());
1038  }
1039 
1040  string op1 = values.top();
1041  values.pop();
1042  bool val1 = toBool(op1);
1043  string op2 = values.top();
1044  values.pop(); // Dammit, std::stack interface is awkward.
1045  bool val2 = toBool(op2);
1046 
1047  if (val1 || val2) {
1048  values.push("true");
1049  } else {
1050  values.push("false");
1051  }
1052 
1053  // Log what we popped and pushed
1055  .arg('\'' + op1 + '\'')
1056  .arg('\'' + op2 + '\'')
1057  .arg('\'' + values.top() + '\'');
1058 }
1059 
1060 void
1062  if (pkt.inClass(client_class_)) {
1063  values.push("true");
1064  } else {
1065  values.push("false");
1066  }
1067 
1068  // Log what we pushed
1070  .arg(client_class_)
1071  .arg('\'' + values.top() + '\'');
1072 }
1073 
1075  uint16_t option_code)
1076  : TokenOption(option_code, repr), universe_(u), vendor_id_(vendor_id),
1077  field_(option_code ? SUBOPTION : EXISTS) {
1078 }
1079 
1081  : TokenOption(0, TokenOption::HEXADECIMAL), universe_(u), vendor_id_(vendor_id),
1082  field_(field) {
1083  if (field_ == EXISTS) {
1085  }
1086 }
1087 
1088 uint32_t TokenVendor::getVendorId() const {
1089  return (vendor_id_);
1090 }
1091 
1093  return (field_);
1094 }
1095 
1096 void TokenVendor::evaluate(Pkt& pkt, ValueStack& values) {
1097  // Get the option first.
1098  uint16_t code = 0;
1099  switch (universe_) {
1100  case Option::V4:
1101  code = DHO_VIVSO_SUBOPTIONS;
1102  break;
1103  case Option::V6:
1104  code = D6O_VENDOR_OPTS;
1105  break;
1106  }
1107 
1108  OptionPtr opt = pkt.getOption(code);
1109  OptionVendorPtr vendor = boost::dynamic_pointer_cast<OptionVendor>(opt);
1110  if (!vendor) {
1111  // There's no vendor option, give up.
1112  std::string txt = pushFailure(values);
1114  .arg(code)
1115  .arg(txt);
1116  return;
1117  }
1118 
1119  if (vendor_id_ && (vendor_id_ != vendor->getVendorId())) {
1120  // There is vendor option, but it has other vendor-id value
1121  // than we're looking for. (0 means accept any vendor-id)
1122  std::string txt = pushFailure(values);
1124  .arg(vendor_id_)
1125  .arg(vendor->getVendorId())
1126  .arg(txt);
1127  return;
1128  }
1129 
1130  switch (field_) {
1131  case ENTERPRISE_ID:
1132  {
1133  // Extract enterprise-id
1134  string txt(sizeof(uint32_t), 0);
1135  uint32_t value = htonl(vendor->getVendorId());
1136  memcpy(&txt[0], &value, sizeof(uint32_t));
1137  values.push(txt);
1139  .arg(vendor->getVendorId())
1140  .arg(util::encode::encodeHex(std::vector<uint8_t>(txt.begin(),
1141  txt.end())));
1142  return;
1143  }
1144  case SUBOPTION:
1147  TokenOption::evaluate(pkt, values);
1148  return;
1149  case EXISTS:
1150  // We already passed all the checks: the option is there and has specified
1151  // enterprise-id.
1153  .arg(vendor->getVendorId())
1154  .arg("true");
1155  values.push("true");
1156  return;
1157  case DATA:
1158  // This is for vendor-class option, we can skip it here.
1159  isc_throw(EvalTypeError, "Field None is not valid for vendor-class");
1160  return;
1161  }
1162 }
1163 
1165  uint16_t code = 0;
1166  switch (universe_) {
1167  case Option::V4:
1168  code = DHO_VIVSO_SUBOPTIONS;
1169  break;
1170  case Option::V6:
1171  code = D6O_VENDOR_OPTS;
1172  break;
1173  }
1174 
1175  OptionPtr opt = pkt.getOption(code);
1176  if (!opt) {
1177  // If vendor option is not found, return NULL
1178  return (opt);
1179  }
1180 
1181  // If vendor option is found, try to return its
1182  // encapsulated option.
1183  return (opt->getOption(option_code_));
1184 }
1185 
1187  RepresentationType repr)
1188  : TokenVendor(u, vendor_id, repr, 0), index_(0) {
1189 }
1190 
1192  FieldType field, uint16_t index)
1193  : TokenVendor(u, vendor_id, TokenOption::HEXADECIMAL, 0), index_(index) {
1194  field_ = field;
1195 }
1196 
1198  return (index_);
1199 }
1200 
1202  // Get the option first.
1203  uint16_t code = 0;
1204  switch (universe_) {
1205  case Option::V4:
1206  code = DHO_VIVCO_SUBOPTIONS;
1207  break;
1208  case Option::V6:
1209  code = D6O_VENDOR_CLASS;
1210  break;
1211  }
1212 
1213  OptionPtr opt = pkt.getOption(code);
1214  OptionVendorClassPtr vendor = boost::dynamic_pointer_cast<OptionVendorClass>(opt);
1215  if (!vendor) {
1216  // There's no vendor class option, give up.
1217  std::string txt = pushFailure(values);
1219  .arg(code)
1220  .arg(txt);
1221  return;
1222  }
1223 
1224  if (vendor_id_ && (vendor_id_ != vendor->getVendorId())) {
1225  // There is vendor option, but it has other vendor-id value
1226  // than we're looking for. (0 means accept any vendor-id)
1227  std::string txt = pushFailure(values);
1229  .arg(vendor_id_)
1230  .arg(vendor->getVendorId())
1231  .arg(txt);
1232  return;
1233  }
1234 
1235  switch (field_) {
1236  case ENTERPRISE_ID:
1237  {
1238  // Extract enterprise-id
1239  string txt(sizeof(uint32_t), 0);
1240  uint32_t value = htonl(vendor->getVendorId());
1241  memcpy(&txt[0], &value, sizeof(uint32_t));
1242  values.push(txt);
1244  .arg(vendor->getVendorId())
1245  .arg(util::encode::encodeHex(std::vector<uint8_t>(txt.begin(),
1246  txt.end())));
1247  return;
1248  }
1249  case SUBOPTION:
1250  // Extract sub-options
1251  isc_throw(EvalTypeError, "Field None is not valid for vendor-class");
1252  return;
1253  case EXISTS:
1254  // We already passed all the checks: the option is there and has specified
1255  // enterprise-id.
1257  .arg(vendor->getVendorId())
1258  .arg("true");
1259  values.push("true");
1260  return;
1261  case DATA:
1262  {
1263  size_t max = vendor->getTuplesNum();
1264  if (index_ + 1 > max) {
1265  // The index specified is out of bounds, e.g. there are only
1266  // 2 tuples and index specified is 5.
1268  .arg(index_)
1269  .arg(vendor->getVendorId())
1270  .arg(max)
1271  .arg("");
1272  values.push("");
1273  return;
1274  }
1275 
1276  OpaqueDataTuple tuple = vendor->getTuple(index_);
1277  OpaqueDataTuple::Buffer buf = tuple.getData();
1278  string txt(buf.begin(), buf.end());
1279 
1281  .arg(index_)
1282  .arg(max)
1283  .arg(txt);
1284 
1285  values.push(txt);
1286  return;
1287  }
1288  default:
1289  isc_throw(EvalTypeError, "Invalid field specified." << field_);
1290  }
1291 }
1292 
1293 TokenInteger::TokenInteger(const uint32_t value)
1294  : TokenString(EvalContext::fromUint32(value)), int_value_(value) {
1295 }
1296 
1297 OptionPtr
1299  if (!parent) {
1300  return (OptionPtr());
1301  }
1302  return (parent->getOption(sub_option_code_));
1303 }
1304 
1305 void
1307  OptionPtr parent = getOption(pkt);
1308  std::string txt;
1310  if (!parent) {
1311  // There's no parent option, notify that.
1313  if (representation_type_ == EXISTS) {
1314  txt = "false";
1315  }
1316  } else {
1317  OptionPtr sub = getSubOption(parent);
1318  if (!sub) {
1319  // Failed to find the sub-option
1320  if (representation_type_ == EXISTS) {
1321  txt = "false";
1322  }
1323  } else {
1324  if (representation_type_ == TEXTUAL) {
1325  txt = sub->toString();
1326  } else if (representation_type_ == HEXADECIMAL) {
1327  std::vector<uint8_t> binary = sub->toBinary();
1328  txt.resize(binary.size());
1329  if (!binary.empty()) {
1330  memmove(&txt[0], &binary[0], binary.size());
1331  }
1332  } else {
1333  txt = "true";
1334  }
1335  }
1336  }
1337 
1338  // Push value of the sub-option or empty string if there was no
1339  // such parent option in the packet or sub-option in the parent.
1340  values.push(txt);
1341 
1342  // Log what we pushed, both exists and textual are simple text
1343  // and can be output directly. We also include the code numbers
1344  // of the requested parent option and sub-option.
1347  .arg(option_code_)
1348  .arg(sub_option_code_)
1349  .arg(toHex(txt));
1350  } else {
1352  .arg(option_code_)
1353  .arg(sub_option_code_)
1354  .arg('\'' + txt + '\'');
1355  }
1356 }
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
EvalBadStack is thrown when more or less parameters are on the stack than expected.
Definition: token.h:37
EvalTypeError is thrown when a value on the stack has a content with an unexpected type.
Definition: token.h:45
Represents a single instance of the opaque data preceded by length.
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
std::vector< uint8_t > Buffer
Defines a type of the data buffer used to hold the opaque data.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
Represents DHCPv4 packet.
Definition: pkt4.h:37
const isc::asiolink::IOAddress & getCiaddr() const
Returns ciaddr field.
Definition: pkt4.h:182
const isc::asiolink::IOAddress & getSiaddr() const
Returns siaddr field.
Definition: pkt4.h:194
const isc::asiolink::IOAddress & getGiaddr() const
Returns giaddr field.
Definition: pkt4.h:218
HWAddrPtr getHWAddr() const
returns hardware address information
Definition: pkt4.h:324
uint8_t getHlen() const
Returns hlen field.
Definition: pkt4.cc:585
const isc::asiolink::IOAddress & getYiaddr() const
Returns yiaddr field.
Definition: pkt4.h:206
uint8_t getType() const
Returns DHCP message type (e.g.
Definition: pkt4.cc:243
uint8_t getHtype() const
Returns htype field.
Definition: pkt4.cc:577
Represents a DHCPv6 packet.
Definition: pkt6.h:44
OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level)
Returns option inserted by relay.
Definition: pkt6.cc:260
const isc::asiolink::IOAddress & getRelay6PeerAddress(uint8_t relay_level) const
return the peer address field from a relay option
Definition: pkt6.cc:336
const isc::asiolink::IOAddress & getRelay6LinkAddress(uint8_t relay_level) const
return the link address field from a relay option
Definition: pkt6.cc:326
std::vector< RelayInfo > relay_info_
Relay information.
Definition: pkt6.h:473
virtual uint8_t getType() const
Returns message type (e.g.
Definition: pkt6.h:220
Base class for classes representing DHCP messages.
Definition: pkt.h:96
const isc::asiolink::IOAddress & getLocalAddr() const
Returns local IP address.
Definition: pkt.h:494
uint32_t getTransid() const
Returns value of transaction-id field.
Definition: pkt.h:276
std::string getIface() const
Returns interface name.
Definition: pkt.h:567
OptionPtr getOption(const uint16_t type)
Returns the first option of specified type.
Definition: pkt.cc:64
bool inClass(const isc::dhcp::ClientClass &client_class)
Checks whether a client belongs to a given class.
Definition: pkt.cc:115
const isc::asiolink::IOAddress & getRemoteAddr() const
Returns remote IP address.
Definition: pkt.h:480
void evaluate(Pkt &pkt, ValueStack &values)
Logical and.
Definition: token.cc:1007
void evaluate(Pkt &pkt, ValueStack &values)
Concatenate two values.
Definition: token.cc:895
void evaluate(Pkt &pkt, ValueStack &values)
Compare two values.
Definition: token.cc:694
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack after decoding or an empty string if...
Definition: token.cc:78
std::string value_
Constant value.
Definition: token.h:152
void evaluate(Pkt &pkt, ValueStack &values)
Alternative.
Definition: token.cc:917
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:212
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:242
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:183
TokenInteger(const uint32_t value)
Integer value set during construction.
Definition: token.cc:1293
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:149
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack after decoding)
Definition: token.cc:139
std::string value_
< Constant value (empty string if the IP address cannot be converted)
Definition: token.h:238
TokenIpAddress(const std::string &addr)
Value is set during token construction.
Definition: token.cc:123
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the evaluated string expression converted to lower case on the stack)
Definition: token.cc:88
ClientClass client_class_
The client class name.
Definition: token.h:1072
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (check if client_class_ was added to packet client classes)
Definition: token.cc:1061
void evaluate(Pkt &pkt, ValueStack &values)
Logical negation.
Definition: token.cc:985
Token that represents a value of an option.
Definition: token.h:375
virtual OptionPtr getOption(Pkt &pkt)
Attempts to retrieve an option.
Definition: token.cc:361
void evaluate(Pkt &pkt, ValueStack &values)
Evaluates the values of the option.
Definition: token.cc:366
RepresentationType representation_type_
Representation type.
Definition: token.h:452
uint16_t option_code_
Code of the option to be extracted.
Definition: token.h:451
RepresentationType
Token representation type.
Definition: token.h:385
virtual std::string pushFailure(ValueStack &values)
Auxiliary method that puts string representing a failure.
Definition: token.cc:404
void evaluate(Pkt &pkt, ValueStack &values)
Logical or.
Definition: token.cc:1034
@ CIADDR
ciaddr (IPv4 address)
Definition: token.h:596
@ HLEN
hlen (hardware address length)
Definition: token.h:599
@ HTYPE
htype (hardware address type)
Definition: token.h:600
@ GIADDR
giaddr (IPv4 address)
Definition: token.h:595
@ CHADDR
chaddr field (up to 16 bytes link-layer address)
Definition: token.h:594
@ YIADDR
yiaddr (IPv4 address)
Definition: token.h:597
@ SIADDR
siaddr (IPv4 address)
Definition: token.h:598
@ TRANSID
transaction-id (xid)
Definition: token.h:602
@ MSGTYPE
message type (not really a field, content of option 53)
Definition: token.h:601
void evaluate(Pkt &pkt, ValueStack &values)
Gets a value from the specified packet.
Definition: token.cc:515
void evaluate(Pkt &pkt, ValueStack &values)
Gets a value of the specified packet.
Definition: token.cc:593
@ TRANSID
transaction id (integer but manipulated as a string)
Definition: token.h:648
@ MSGTYPE
msg type
Definition: token.h:647
@ LEN
length (4 octets)
Definition: token.h:548
@ DST
destination (IP address)
Definition: token.h:547
@ IFACE
interface name (string)
Definition: token.h:545
@ SRC
source (IP address)
Definition: token.h:546
void evaluate(Pkt &pkt, ValueStack &values)
Gets a value from the specified packet.
Definition: token.cc:465
virtual OptionPtr getOption(Pkt &pkt)
Attempts to obtain specified sub-option of option 82 from the packet.
Definition: token.cc:418
TokenRelay4Option(const uint16_t option_code, const RepresentationType &rep_type)
Constructor for extracting sub-option from RAI (option 82)
Definition: token.cc:413
FieldType type_
field to get
Definition: token.h:744
void evaluate(Pkt &pkt, ValueStack &values)
Extracts the specified field from the requested relay.
Definition: token.cc:632
@ LINKADDR
Link address field (IPv6 address)
Definition: token.h:700
@ PEERADDR
Peer address field (IPv6 address)
Definition: token.h:699
int8_t nest_level_
Specifies field of the DHCPv6 relay option to get.
Definition: token.h:743
int8_t nest_level_
nesting level of the relay block to use
Definition: token.h:527
virtual OptionPtr getOption(Pkt &pkt)
Attempts to obtain specified option from the specified relay block.
Definition: token.cc:429
void evaluate(Pkt &pkt, ValueStack &values)
Extract a field from a delimited string.
Definition: token.cc:813
The order where Token subtypes are declared should be:
Definition: token.h:113
virtual void evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
Definition: token.cc:1306
uint16_t sub_option_code_
Code of the sub-option to be extracted.
Definition: token.h:1323
virtual OptionPtr getSubOption(const OptionPtr &parent)
Attempts to retrieve a sub-option.
Definition: token.cc:1298
void evaluate(Pkt &pkt, ValueStack &values)
Extract a substring from a string.
Definition: token.cc:718
void evaluate(Pkt &pkt, ValueStack &values)
Convert a binary value to its hexadecimal string representation.
Definition: token.cc:952
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:301
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:331
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
Definition: token.cc:272
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the evaluated string expression converted to upper case on the stack)
Definition: token.cc:106
TokenVendorClass(Option::Universe u, uint32_t vendor_id, RepresentationType repr)
This constructor is used to access fields.
Definition: token.cc:1186
uint16_t getDataIndex() const
Returns data index.
Definition: token.cc:1197
uint16_t index_
Data chunk index.
Definition: token.h:1256
void evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
Definition: token.cc:1201
Token that represents vendor options in DHCPv4 and DHCPv6.
Definition: token.h:1089
FieldType
Specifies a field of the vendor option.
Definition: token.h:1093
@ DATA
data chunk, used in derived vendor-class only
Definition: token.h:1097
@ EXISTS
vendor[123].exists
Definition: token.h:1096
@ ENTERPRISE_ID
enterprise-id field (vendor-info, vendor-class)
Definition: token.h:1095
@ SUBOPTION
If this token fetches a suboption, not a field.
Definition: token.h:1094
Option::Universe universe_
Universe (V4 or V6)
Definition: token.h:1174
uint32_t vendor_id_
Enterprise-id value.
Definition: token.h:1180
FieldType field_
Specifies which field should be accessed.
Definition: token.h:1183
uint32_t getVendorId() const
Returns enterprise-id.
Definition: token.cc:1088
TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field)
Constructor used for accessing a field.
Definition: token.cc:1080
virtual OptionPtr getOption(Pkt &pkt)
Attempts to get a suboption.
Definition: token.cc:1164
virtual void evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
Definition: token.cc:1096
FieldType getField() const
Returns field.
Definition: token.cc:1092
static bool toBool(std::string value)
Coverts a (string) value to a boolean.
Definition: token.h:89
Evaluation context, an interface to the expression evaluation.
Definition: eval_context.h:34
@ D6O_VENDOR_OPTS
Definition: dhcp6.h:37
@ D6O_VENDOR_CLASS
Definition: dhcp6.h:36
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
const isc::log::MessageID EVAL_DEBUG_RELAY6_RANGE
Definition: eval_messages.h:31
const isc::log::MessageID EVAL_DEBUG_UCASE
Definition: eval_messages.h:43
const isc::log::MessageID EVAL_DEBUG_UINT32TOTEXT
Definition: eval_messages.h:45
const isc::log::MessageID EVAL_DEBUG_UINT16TOTEXT
Definition: eval_messages.h:44
const isc::log::MessageID EVAL_DEBUG_SPLIT_EMPTY
Definition: eval_messages.h:34
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_EXISTS
Definition: eval_messages.h:51
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND
Definition: eval_messages.h:48
const isc::log::MessageID EVAL_DEBUG_PKT
Definition: eval_messages.h:27
@ DHO_VIVCO_SUBOPTIONS
Definition: dhcp4.h:189
@ DHO_DHCP_AGENT_OPTIONS
Definition: dhcp4.h:151
@ DHO_VIVSO_SUBOPTIONS
Definition: dhcp4.h:190
const isc::log::MessageID EVAL_DEBUG_HEXSTRING
Definition: eval_messages.h:14
const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING
Definition: eval_messages.h:42
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA
Definition: eval_messages.h:47
const isc::log::MessageID EVAL_DEBUG_SPLIT_FIELD_OUT_OF_RANGE
Definition: eval_messages.h:35
const isc::log::MessageID EVAL_DEBUG_INT32TOTEXT
Definition: eval_messages.h:18
const isc::log::MessageID EVAL_DEBUG_OPTION
Definition: eval_messages.h:25
const int EVAL_DBG_STACK
Definition: eval_log.h:26
const isc::log::MessageID EVAL_DEBUG_SUBSTRING
Definition: eval_messages.h:37
const isc::log::MessageID EVAL_DEBUG_PKT6
Definition: eval_messages.h:29
const isc::log::MessageID EVAL_DEBUG_RELAY6
Definition: eval_messages.h:30
const isc::log::MessageID EVAL_DEBUG_OR
Definition: eval_messages.h:26
const isc::log::MessageID EVAL_DEBUG_SUB_OPTION_NO_OPTION
Definition: eval_messages.h:41
const isc::log::MessageID EVAL_DEBUG_INT8TOTEXT
Definition: eval_messages.h:19
const isc::log::MessageID EVAL_DEBUG_VENDOR_ENTERPRISE_ID
Definition: eval_messages.h:53
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
const isc::log::MessageID EVAL_DEBUG_STRING
Definition: eval_messages.h:36
const isc::log::MessageID EVAL_DEBUG_VENDOR_ENTERPRISE_ID_MISMATCH
Definition: eval_messages.h:54
const isc::log::MessageID EVAL_DEBUG_SUB_OPTION
Definition: eval_messages.h:40
const isc::log::MessageID EVAL_DEBUG_SPLIT
Definition: eval_messages.h:32
const isc::log::MessageID EVAL_DEBUG_PKT4
Definition: eval_messages.h:28
const isc::log::MessageID EVAL_DEBUG_INT16TOTEXT
Definition: eval_messages.h:17
isc::log::Logger eval_logger("eval")
Eval Logger.
Definition: eval_log.h:33
const isc::log::MessageID EVAL_DEBUG_CONCAT
Definition: eval_messages.h:12
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID_MISMATCH
Definition: eval_messages.h:50
const isc::log::MessageID EVAL_DEBUG_VENDOR_EXISTS
Definition: eval_messages.h:55
const isc::log::MessageID EVAL_DEBUG_VENDOR_NO_OPTION
Definition: eval_messages.h:56
const isc::log::MessageID EVAL_DEBUG_LCASE
Definition: eval_messages.h:22
boost::shared_ptr< OptionVendorClass > OptionVendorClassPtr
Defines a pointer to the OptionVendorClass.
const isc::log::MessageID EVAL_DEBUG_IPADDRESS
Definition: eval_messages.h:20
const isc::log::MessageID EVAL_DEBUG_AND
Definition: eval_messages.h:11
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_NO_OPTION
Definition: eval_messages.h:52
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID
Definition: eval_messages.h:49
const isc::log::MessageID EVAL_DEBUG_UINT8TOTEXT
Definition: eval_messages.h:46
const isc::log::MessageID EVAL_DEBUG_EQUAL
Definition: eval_messages.h:13
const isc::log::MessageID EVAL_DEBUG_IPADDRESSTOTEXT
Definition: eval_messages.h:21
const isc::log::MessageID EVAL_DEBUG_SPLIT_DELIM_EMPTY
Definition: eval_messages.h:33
const isc::log::MessageID EVAL_DEBUG_MEMBER
Definition: eval_messages.h:23
const isc::log::MessageID EVAL_DEBUG_IFELSE_TRUE
Definition: eval_messages.h:16
const isc::log::MessageID EVAL_DEBUG_NOT
Definition: eval_messages.h:24
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE
Definition: eval_messages.h:39
std::stack< std::string > ValueStack
Evaluated values are stored as a stack of strings.
Definition: token.h:33
const isc::log::MessageID EVAL_DEBUG_IFELSE_FALSE
Definition: eval_messages.h:15
const isc::log::MessageID EVAL_DEBUG_SUBSTRING_EMPTY
Definition: eval_messages.h:38
const char * MessageID
Definition: message_types.h:15
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:483
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
Definition: base_n.cc:488
std::string toHex(std::string value)
Encode in hexadecimal inline.
Definition: hex.h:53
Definition: edns.h:19
uint32_t readUint32(const void *buffer, size_t length)
Read Unsigned 32-Bit Integer from Buffer.
Definition: io_utilities.h:79
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28