Kea 2.5.8
token.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <eval/token.h>
10#include <eval/eval_log.h>
11#include <eval/eval_context.h>
12#include <util/encode/encode.h>
13#include <util/io.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
32using namespace isc::asiolink;
33using namespace isc::dhcp;
34using namespace isc::util;
35using namespace std;
36
38
39void
41 // Literals only push, nothing to pop
42 values.push(value_);
43
44 // Log what we pushed
46 .arg('\'' + value_ + '\'');
47}
48
49TokenHexString::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
77void
79 // Literals only push, nothing to pop
80 values.push(value_);
81
82 // Log what we pushed
84 .arg(toHex(value_));
85}
86
87void
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
105void
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
123TokenIpAddress::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
138void
140 // Literals only push, nothing to pop
141 values.push(value_);
142
143 // Log what we pushed
145 .arg(toHex(value_));
146}
147
148void
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
182void
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
211void
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
241void
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
271void
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
300void
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
330void
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
362 return (pkt.getOption(option_code_));
363}
364
365void
367 OptionPtr opt = getOption(pkt);
368 std::string opt_str;
369 if (opt) {
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
403std::string
405 std::string txt;
407 txt = "false";
408 }
409 values.push(txt);
410 return (txt);
411}
412
413TokenRelay4Option::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
464void
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
514void
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
592void
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
631void
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
693void
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
717void
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
812void
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
894void
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
916void
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
951void
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
984void
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
1006void
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
1033void
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
1060void
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
1089 return (vendor_id_);
1090}
1091
1093 return (field_);
1094}
1095
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
1293TokenInteger::TokenInteger(const uint32_t value)
1294 : TokenString(EvalContext::fromUint32(value)), int_value_(value) {
1295}
1296
1299 if (!parent) {
1300 return (OptionPtr());
1301 }
1302 return (parent->getOption(sub_option_code_));
1303}
1304
1305void
1307 OptionPtr parent = getOption(pkt);
1308 std::string txt;
1310 if (!parent) {
1311 // There's no parent option, notify that.
1314 txt = "false";
1315 }
1316 } else {
1317 OptionPtr sub = getSubOption(parent);
1318 if (!sub) {
1319 // Failed to find the sub-option
1321 txt = "false";
1322 }
1323 } else {
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 & 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:588
uint8_t getType() const
Returns DHCP message type (e.g.
Definition: pkt4.cc:242
uint8_t getHtype() const
Returns htype field.
Definition: pkt4.cc:580
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:259
const isc::asiolink::IOAddress & getRelay6PeerAddress(uint8_t relay_level) const
return the peer address field from a relay option
Definition: pkt6.cc:334
const isc::asiolink::IOAddress & getRelay6LinkAddress(uint8_t relay_level) const
return the link address field from a relay option
Definition: pkt6.cc:324
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:161
const isc::asiolink::IOAddress & getLocalAddr() const
Returns local IP address.
Definition: pkt.h:609
const isc::asiolink::IOAddress & getRemoteAddr() const
Returns remote IP address.
Definition: pkt.h:595
uint32_t getTransid() const
Returns value of transaction-id field.
Definition: pkt.h:341
std::string getIface() const
Returns interface name.
Definition: pkt.h:682
OptionPtr getOption(const uint16_t type)
Returns the first option of specified type.
Definition: pkt.cc:71
bool inClass(const isc::dhcp::ClientClass &client_class)
Checks whether a client belongs to a given class.
Definition: pkt.cc:121
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
TokenHexString(const std::string &str)
Value is set during token construction.
Definition: token.cc:49
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
std::string value_
Constant value.
Definition: token.h:127
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack)
Definition: token.cc:40
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
static std::string fromUint32(const uint32_t integer)
Converts unsigned 32bit integer to string representation.
@ 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:37
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
void decodeHex(const string &encoded_str, vector< uint8_t > &output)
Decode a base16 encoded string into binary data.
Definition: encode.cc:367
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
Definition: encode.cc:361
std::string toHex(std::string value)
Encode in hexadecimal inline.
Definition: encode.h:293
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
Definition: io.h:76
uint32_t readUint32(void const *const buffer, size_t const length)
uint32_t wrapper over readUint.
Definition: io.h:82