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