Kea 3.3.1
token.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <eval/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 <util/str.h>
15#include <asiolink/io_address.h>
16#include <dhcp/pkt4.h>
17#include <dhcp/pkt6.h>
18#include <boost/lexical_cast.hpp>
19#include <dhcp/dhcp4.h>
20#include <dhcp/dhcp6.h>
21#include <dhcp/option_vendor.h>
23
24#include <boost/algorithm/string.hpp>
25#include <boost/algorithm/string/classification.hpp>
26#include <boost/algorithm/string/split.hpp>
27
28#include <cstring>
29#include <string>
30#include <iomanip>
31#include <sstream>
32
33using namespace isc::asiolink;
34using namespace isc::dhcp;
35using namespace isc::util;
36using namespace isc::util::str;
37using namespace std;
38
40
41unsigned
43 // Literals only push, nothing to pop
44 values.push(value_);
45
46 // Log what we pushed
48 .arg(pkt.getLabel())
49 .arg('\'' + value_ + '\'');
50
51 return (0);
52}
53
55 // Check string starts "0x" or "0x" and has at least one additional character.
56 if ((str.size() < 3) ||
57 (str[0] != '0') ||
58 ((str[1] != 'x') && (str[1] != 'X'))) {
59 return;
60 }
61 string digits = str.substr(2);
62
63 // Transform string of hexadecimal digits into binary format
64 vector<uint8_t> binary;
65 try {
66 // The decodeHex function expects that the string contains an
67 // even number of digits. If we don't meet this requirement,
68 // we have to insert a leading 0.
69 if ((digits.length() % 2) != 0) {
70 digits = digits.insert(0, "0");
71 }
72 util::encode::decodeHex(digits, binary);
73 } catch (...) {
74 return;
75 }
76
77 // Convert to a string (note that binary.size() cannot be 0)
78 value_.resize(binary.size());
79 memmove(&value_[0], &binary[0], binary.size());
80}
81
82unsigned
84 // Literals only push, nothing to pop
85 values.push(value_);
86
87 // Log what we pushed
89 .arg(pkt.getLabel())
90 .arg(toHex(value_));
91
92 return (0);
93}
94
95unsigned
97 if (values.size() == 0) {
98 isc_throw(EvalBadStack, "Incorrect empty stack.");
99 }
100
101 string op = values.top();
102
103 values.pop();
104 string result(boost::algorithm::to_lower_copy(op));
105 values.push(result);
106
107 // Log what we pushed
109 .arg(pkt.getLabel())
110 .arg('\'' + op + '\'')
111 .arg('\'' + result + '\'');
112
113 return (0);
114}
115
116unsigned
118 if (values.size() == 0) {
119 isc_throw(EvalBadStack, "Incorrect empty stack.");
120 }
121
122 string op = values.top();
123
124 values.pop();
125 string result(boost::algorithm::to_upper_copy(op));
126 values.push(result);
127
128 // Log what we pushed
130 .arg(pkt.getLabel())
131 .arg('\'' + op + '\'')
132 .arg('\'' + result + '\'');
133
134 return (0);
135}
136
137TokenIpAddress::TokenIpAddress(const string& addr) : value_("") {
138 // Transform IP address into binary format
139 vector<uint8_t> binary;
140 try {
141 asiolink::IOAddress ip(addr);
142 binary = ip.toBytes();
143 } catch (...) {
144 return;
145 }
146
147 // Convert to a string (note that binary.size() is 4 or 16, so not 0)
148 value_.resize(binary.size());
149 memmove(&value_[0], &binary[0], binary.size());
150}
151
152unsigned
154 // Literals only push, nothing to pop
155 values.push(value_);
156
157 // Log what we pushed
159 .arg(pkt.getLabel())
160 .arg(toHex(value_));
161
162 return (0);
163}
164
165unsigned
167 if (values.size() == 0) {
168 isc_throw(EvalBadStack, "Incorrect empty stack.");
169 }
170
171 string op = values.top();
172 size_t size = op.size();
173
174 if (!size) {
175 return (0);
176 }
177
178 values.pop();
179
180 if ((size != V4ADDRESS_LEN) && (size != V6ADDRESS_LEN)) {
181 isc_throw(EvalTypeError, "Can not convert to valid address.");
182 }
183
184 std::vector<uint8_t> binary(op.begin(), op.end());
185
186 if (size == V4ADDRESS_LEN) {
187 op = asiolink::IOAddress::fromBytes(AF_INET, binary.data()).toText();
188 } else {
189 op = asiolink::IOAddress::fromBytes(AF_INET6, binary.data()).toText();
190 }
191
192 values.push(op);
193
194 // Log what we pushed
196 .arg(pkt.getLabel())
197 .arg(op);
198
199 return (0);
200}
201
202unsigned
204 if (values.size() == 0) {
205 isc_throw(EvalBadStack, "Incorrect empty stack.");
206 }
207
208 string op = values.top();
209 size_t size = op.size();
210
211 if (!size) {
212 return (0);
213 }
214
215 values.pop();
216
217 if (size != sizeof(int8_t)) {
218 isc_throw(EvalTypeError, "Can not convert to valid int8.");
219 }
220
221 stringstream tmp;
222 tmp << static_cast<int32_t>(*(reinterpret_cast<const int8_t*>(op.data())));
223 op = tmp.str();
224 values.push(op);
225
226 // Log what we pushed
228 .arg(pkt.getLabel())
229 .arg(op);
230
231 return (0);
232}
233
234unsigned
236 if (values.size() == 0) {
237 isc_throw(EvalBadStack, "Incorrect empty stack.");
238 }
239
240 string op = values.top();
241 size_t size = op.size();
242
243 if (!size) {
244 return (0);
245 }
246
247 values.pop();
248
249 if (size != sizeof(int16_t)) {
250 isc_throw(EvalTypeError, "Can not convert to valid int16.");
251 }
252
253 stringstream tmp;
254 int16_t value = static_cast<int16_t>(readUint16(const_cast<const char*>(op.data()), size));
255 tmp << value;
256 op = tmp.str();
257 values.push(op);
258
259 // Log what we pushed
261 .arg(pkt.getLabel())
262 .arg(op);
263
264 return (0);
265}
266
267unsigned
269 if (values.size() == 0) {
270 isc_throw(EvalBadStack, "Incorrect empty stack.");
271 }
272
273 string op = values.top();
274 size_t size = op.size();
275
276 if (!size) {
277 return (0);
278 }
279
280 values.pop();
281
282 if (size != sizeof(int32_t)) {
283 isc_throw(EvalTypeError, "Can not convert to valid int32.");
284 }
285
286 stringstream tmp;
287 int32_t value = static_cast<int32_t>(readUint32(const_cast<const char*>(op.data()), size));
288 tmp << value;
289 op = tmp.str();
290 values.push(op);
291
292 // Log what we pushed
294 .arg(pkt.getLabel())
295 .arg(op);
296
297 return (0);
298}
299
300unsigned
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 (0);
311 }
312
313 values.pop();
314
315 if (size != sizeof(uint8_t)) {
316 isc_throw(EvalTypeError, "Can not convert to valid uint8.");
317 }
318
319 stringstream tmp;
320 tmp << static_cast<uint32_t>(*(reinterpret_cast<const uint8_t*>(op.data())));
321 op = tmp.str();
322 values.push(op);
323
324 // Log what we pushed
326 .arg(pkt.getLabel())
327 .arg(op);
328
329 return (0);
330}
331
332unsigned
334 if (values.size() == 0) {
335 isc_throw(EvalBadStack, "Incorrect empty stack.");
336 }
337
338 string op = values.top();
339 size_t size = op.size();
340
341 if (!size) {
342 return (0);
343 }
344
345 values.pop();
346
347 if (size != sizeof(uint16_t)) {
348 isc_throw(EvalTypeError, "Can not convert to valid uint16.");
349 }
350
351 stringstream tmp;
352 uint16_t value = readUint16(const_cast<const char*>(op.data()), size);
353 tmp << value;
354 op = tmp.str();
355 values.push(op);
356
357 // Log what we pushed
359 .arg(pkt.getLabel())
360 .arg(op);
361
362 return (0);
363}
364
365unsigned
367 if (values.size() == 0) {
368 isc_throw(EvalBadStack, "Incorrect empty stack.");
369 }
370
371 string op = values.top();
372 size_t size = op.size();
373
374 if (!size) {
375 return (0);
376 }
377
378 values.pop();
379
380 if (size != sizeof(uint32_t)) {
381 isc_throw(EvalTypeError, "Can not convert to valid uint32.");
382 }
383
384 stringstream tmp;
385 uint32_t value = readUint32(const_cast<const char*>(op.data()), size);
386 tmp << value;
387 op = tmp.str();
388 values.push(op);
389
390 // Log what we pushed
392 .arg(pkt.getLabel())
393 .arg(op);
394
395 return (0);
396}
397
400 OptionPtr option;
401 for (auto const& c : option_path_) {
402 if (!option) {
403 option = pkt.getOption(c);
404 if (!option) {
405 break;
406 }
407 } else {
408 option = option->getOption(c);
409 }
410 if (!option) {
411 break;
412 }
413 }
414 return (option);
415}
416
417unsigned
419 OptionPtr opt = getOption(pkt);
420 std::string opt_str;
421 if (opt) {
423 opt_str = opt->toString();
424 } else if (representation_type_ == HEXADECIMAL) {
425 std::vector<uint8_t> binary = opt->toBinary();
426 opt_str.resize(binary.size());
427 if (!binary.empty()) {
428 memmove(&opt_str[0], &binary[0], binary.size());
429 }
430 } else {
431 opt_str = "true";
432 }
433 } else if (representation_type_ == EXISTS) {
434 opt_str = "false";
435 }
436
437 // Push value of the option or empty string if there was no such option
438 // in the packet.
439 values.push(opt_str);
440
441 stringstream tmp;
442 for (auto const& c : option_path_) {
443 if (!tmp.str().empty()) {
444 tmp << ".";
445 }
446 tmp << "option[" << c << "]";
447 }
448
449 if (tmp.str().empty()) {
450 tmp << "(none)";
451 }
452
453 // Log what we pushed, both exists and textual are simple text
454 // and can be output directly. We also include the code number
455 // of the requested option.
458 .arg(pkt.getLabel())
459 .arg(tmp.str())
460 .arg(toHex(opt_str));
461 } else {
463 .arg(pkt.getLabel())
464 .arg(tmp.str())
465 .arg('\'' + opt_str + '\'');
466 }
467
468 return (0);
469}
470
471std::string
473 std::string txt;
475 txt = "false";
476 }
477 values.push(txt);
478 return (txt);
479}
480
483 // Check if there is Relay Agent Option.
485 if (!option) {
486 return (OptionPtr());
487 }
488
489 // If there is, try to return its suboption
490 for (auto const& c : option_path_) {
491 option = option->getOption(c);
492 if (!option) {
493 break;
494 }
495 }
496 return (option);
497}
498
501 try {
502 // Check if it's a Pkt6. If it's not the dynamic_cast will
503 // throw std::bad_cast.
504 Pkt6& pkt6 = dynamic_cast<Pkt6&>(pkt);
505 OptionPtr option;
506 for (auto const& c : option_path_) {
507 if (!option) {
508 try {
509 // Now that we have the right type of packet we can
510 // get the option and return it.
511 if (nest_level_ >= 0) {
512 uint8_t nesting_level = static_cast<uint8_t>(nest_level_);
513 option = pkt6.getRelayOption(c, nesting_level);
514 } else {
515 int nesting_level = pkt6.relay_info_.size() + nest_level_;
516 if (nesting_level < 0) {
517 return (OptionPtr());
518 }
519 option = pkt6.getRelayOption(c, static_cast<uint8_t>(nesting_level));
520 }
521 } catch (const isc::OutOfRange&) {
522 // The only exception we expect is OutOfRange if the nest
523 // level is out of range of the encapsulations, for example
524 // if nest_level_ is 4 and there are only 2 encapsulations.
525 // We return a NULL in that case.
526 return (OptionPtr());
527 }
528 if (!option) {
529 break;
530 }
531 } else {
532 option = option->getOption(c);
533 }
534 if (!option) {
535 break;
536 }
537 }
538 return (option);
539 } catch (const std::bad_cast&) {
540 isc_throw(EvalTypeError, "Specified packet is not Pkt6");
541 }
542}
543
544unsigned
546 string value;
547 vector<uint8_t> binary;
548 string type_str;
549 bool is_binary = true;
550 bool print_hex = true;
551 switch (type_) {
552 case IFACE:
553 is_binary = false;
554 print_hex = false;
555 value = pkt.getIface();
556 type_str = "iface";
557 break;
558 case SRC:
559 binary = pkt.getRemoteAddr().toBytes();
560 type_str = "src";
561 break;
562 case DST:
563 binary = pkt.getLocalAddr().toBytes();
564 type_str = "dst";
565 break;
566 case LEN:
567 // len() returns a size_t but in fact it can't be very large
568 // (with UDP transport it fits in 16 bits)
569 // the len() method is not const because of DHCPv6 relays.
570 // We assume here it has no bad side effects...
571 value = EvalContext::fromUint32(static_cast<uint32_t>(const_cast<Pkt&>(pkt).len()));
572 is_binary = false;
573 type_str = "len";
574 break;
575
576 default:
577 isc_throw(EvalTypeError, "Bad meta data specified: " << static_cast<int>(type_));
578 }
579
580 if (is_binary) {
581 value.resize(binary.size());
582 if (!binary.empty()) {
583 memmove(&value[0], &binary[0], binary.size());
584 }
585 }
586 values.push(value);
587
588 // Log what we pushed
590 .arg(pkt.getLabel())
591 .arg(type_str)
592 .arg(print_hex ? toHex(value) : value);
593
594 return (0);
595}
596
597unsigned
599 vector<uint8_t> binary;
600 string value;
601 string type_str;
602 try {
603 // Check if it's a Pkt4. If it's not, the dynamic_cast will throw
604 // std::bad_cast (failed dynamic_cast returns NULL for pointers and
605 // throws for references).
606 const Pkt4& pkt4 = dynamic_cast<const Pkt4&>(pkt);
607
608 switch (type_) {
609 case CHADDR: {
610 HWAddrPtr hwaddr = pkt4.getHWAddr();
611 if (!hwaddr) {
612 // This should never happen. Every Pkt4 should always have
613 // a hardware address.
615 "Packet does not have hardware address");
616 }
617 binary = hwaddr->hwaddr_;
618 type_str = "mac";
619 break;
620 }
621 case GIADDR:
622 binary = pkt4.getGiaddr().toBytes();
623 type_str = "giaddr";
624 break;
625 case CIADDR:
626 binary = pkt4.getCiaddr().toBytes();
627 type_str = "ciaddr";
628 break;
629 case YIADDR:
630 binary = pkt4.getYiaddr().toBytes();
631 type_str = "yiaddr";
632 break;
633 case SIADDR:
634 binary = pkt4.getSiaddr().toBytes();
635 type_str = "siaddr";
636 break;
637 case HLEN:
638 // Pad the uint8_t field to 4 bytes.
639 value = EvalContext::fromUint32(pkt4.getHlen());
640 type_str = "hlen";
641 break;
642 case HTYPE:
643 // Pad the uint8_t field to 4 bytes.
644 value = EvalContext::fromUint32(pkt4.getHtype());
645 type_str = "htype";
646 break;
647 case MSGTYPE:
648 value = EvalContext::fromUint32(pkt4.getType());
649 type_str = "msgtype";
650 break;
651 case TRANSID:
652 value = EvalContext::fromUint32(pkt4.getTransid());
653 type_str = "transid";
654 break;
655 default:
656 isc_throw(EvalTypeError, "Bad field specified: " << static_cast<int>(type_));
657 }
658
659 } catch (const std::bad_cast&) {
660 isc_throw(EvalTypeError, "Specified packet is not a Pkt4");
661 }
662
663 if (!binary.empty()) {
664 value.resize(binary.size());
665 memmove(&value[0], &binary[0], binary.size());
666 }
667 values.push(value);
668
669 // Log what we pushed
671 .arg(pkt.getLabel())
672 .arg(type_str)
673 .arg(toHex(value));
674
675 return (0);
676}
677
678unsigned
680 string value;
681 string type_str;
682 try {
683 // Check if it's a Pkt6. If it's not the dynamic_cast will throw
684 // std::bad_cast (failed dynamic_cast returns NULL for pointers and
685 // throws for references).
686 const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
687
688 switch (type_) {
689 case MSGTYPE: {
690 // msg type is an uint8_t integer. We want a 4 byte string so 0 pad.
691 value = EvalContext::fromUint32(pkt6.getType());
692 type_str = "msgtype";
693 break;
694 }
695 case TRANSID: {
696 // transaction id is an uint32_t integer. We want a 4 byte string so copy
697 value = EvalContext::fromUint32(pkt6.getTransid());
698 type_str = "transid";
699 break;
700 }
701 default:
702 isc_throw(EvalTypeError, "Bad field specified: " << static_cast<int>(type_));
703 }
704
705 } catch (const std::bad_cast&) {
706 isc_throw(EvalTypeError, "Specified packet is not Pkt6");
707 }
708
709 values.push(value);
710
711 // Log what we pushed
713 .arg(pkt.getLabel())
714 .arg(type_str)
715 .arg(toHex(value));
716
717 return (0);
718}
719
720unsigned
722 vector<uint8_t> binary;
723 string type_str;
724 try {
725 // Check if it's a Pkt6. If it's not the dynamic_cast will
726 // throw std::bad_cast.
727 const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
728 uint8_t relay_level;
729
730 try {
731 if (nest_level_ >= 0) {
732 relay_level = static_cast<uint8_t>(nest_level_);
733 } else {
734 int nesting_level = pkt6.relay_info_.size() + nest_level_;
735 if (nesting_level < 0) {
736 // Don't throw OutOfRange here
737 nesting_level = 32;
738 }
739 relay_level = static_cast<uint8_t>(nesting_level);
740 }
741 switch (type_) {
742 // Now that we have the right type of packet we can
743 // get the option and return it.
744 case LINKADDR:
745 type_str = "linkaddr";
746 binary = pkt6.getRelay6LinkAddress(relay_level).toBytes();
747 break;
748 case PEERADDR:
749 type_str = "peeraddr";
750 binary = pkt6.getRelay6PeerAddress(relay_level).toBytes();
751 break;
752 }
753 } catch (const isc::OutOfRange&) {
754 // The only exception we expect is OutOfRange if the nest
755 // level is invalid. We push "" in that case.
756 values.push("");
757 // Log what we pushed
759 .arg(pkt.getLabel())
760 .arg(type_str)
761 .arg(int(nest_level_))
762 .arg("0x");
763 return (0);
764 }
765 } catch (const std::bad_cast&) {
766 isc_throw(EvalTypeError, "Specified packet is not Pkt6");
767 }
768
769 string value;
770 value.resize(binary.size());
771 if (!binary.empty()) {
772 memmove(&value[0], &binary[0], binary.size());
773 }
774 values.push(value);
775
776 // Log what we pushed
778 .arg(pkt.getLabel())
779 .arg(type_str)
780 .arg(int(nest_level_))
781 .arg(toHex(value));
782
783 return (0);
784}
785
786unsigned
788 if (values.size() < 2) {
789 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
790 "2 values for == operator, got " << values.size());
791 }
792
793 string op1 = values.top();
794 values.pop();
795 string op2 = values.top();
796 values.pop(); // Dammit, std::stack interface is awkward.
797
798 if (op1 == op2)
799 values.push("true");
800 else
801 values.push("false");
802
803 // Log what we popped and pushed
805 .arg(pkt.getLabel())
806 .arg(toHex(op1))
807 .arg(toHex(op2))
808 .arg('\'' + values.top() + '\'');
809
810 return (0);
811}
812
813unsigned
815 if (values.size() < 3) {
816 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
817 "3 values for substring operator, got " << values.size());
818 }
819
820 string len_str = values.top();
821 values.pop();
822 string start_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(pkt.getLabel())
834 .arg(len_str)
835 .arg(start_str)
836 .arg("0x")
837 .arg("0x");
838 return (0);
839 }
840
841 // Convert the starting position and length from strings to numbers
842 // the length may also be "all" in which case simply make it the
843 // length of the string.
844 // If we have a problem push an empty string and leave
845 int start_pos;
846 int length;
847 try {
848 start_pos = boost::lexical_cast<int>(start_str);
849 } catch (const boost::bad_lexical_cast&) {
850 isc_throw(EvalTypeError, "the parameter '" << start_str
851 << "' for the starting position of the substring "
852 << "couldn't be converted to an integer.");
853 }
854 try {
855 if (len_str == "all") {
856 length = string_str.length();
857 } else {
858 length = boost::lexical_cast<int>(len_str);
859 }
860 } catch (const boost::bad_lexical_cast&) {
861 isc_throw(EvalTypeError, "the parameter '" << len_str
862 << "' for the length of the substring "
863 << "couldn't be converted to an integer.");
864 }
865
866 const int string_length = string_str.length();
867 // If the starting position is outside of the string push an
868 // empty string and leave
869 if ((start_pos < -string_length) || (start_pos >= string_length)) {
870 values.push("");
871
872 // Log what we popped and pushed
874 .arg(pkt.getLabel())
875 .arg(len_str)
876 .arg(start_str)
877 .arg(toHex(string_str))
878 .arg("0x");
879 return (0);
880 }
881
882 // Adjust the values to be something for substr. We first figure out
883 // the starting position, then update it and the length to get the
884 // characters before or after it depending on the sign of length
885 if (start_pos < 0) {
886 start_pos = string_length + start_pos;
887 }
888
889 if (length < 0) {
890 length = -length;
891 if (length <= start_pos){
892 start_pos -= length;
893 } else {
894 length = start_pos;
895 start_pos = 0;
896 }
897 }
898
899 // and finally get the substring
900 values.push(string_str.substr(start_pos, length));
901
902 // Log what we popped and pushed
904 .arg(pkt.getLabel())
905 .arg(len_str)
906 .arg(start_str)
907 .arg(toHex(string_str))
908 .arg(toHex(values.top()));
909
910 return (0);
911}
912
913unsigned
915 if (values.size() < 3) {
916 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
917 "3 values for split operator, got " << values.size());
918 }
919
920 // Pop the parameters.
921 string field_str = values.top();
922 values.pop();
923 string delim_str = values.top();
924 values.pop();
925 string string_str = values.top();
926 values.pop();
927
928 // If we have no string to start with we push an empty string and leave
929 if (string_str.empty()) {
930 values.push("");
931
932 // Log what we popped and pushed
934 .arg(pkt.getLabel())
935 .arg(field_str)
936 .arg(delim_str)
937 .arg(string_str)
938 .arg("0x");
939 return (0);
940 }
941
942 // Convert the field position from string to number
943 // If we have a problem push an empty string and leave
944 int field;
945 try {
946 field = boost::lexical_cast<int>(field_str);
947 } catch (const boost::bad_lexical_cast&) {
948 isc_throw(EvalTypeError, "the parameter '" << field_str
949 << "' for the field field for split "
950 << "couldn't be converted to an integer.");
951 }
952
953 // If we have no delimiter to start with we push the input string and leave
954 if (delim_str.empty()) {
955 values.push(string_str);
956
957 // Log what we popped and pushed
959 .arg(pkt.getLabel())
960 .arg(field_str)
961 .arg(delim_str)
962 .arg(string_str)
963 .arg(toHex(values.top()));
964 return (0);
965 }
966
967 // Split the string into fields.
968 std::vector<std::string> fields;
969 boost::split(fields, string_str, boost::is_any_of(delim_str),
970 boost::algorithm::token_compress_off);
971
972 // Range check the field.
973 if (field < 1 || static_cast<size_t>(field) > fields.size()) {
974 // Push an empty string if field is out of range.
975 values.push("");
976
977 // Log what we popped and pushed
979 .arg(pkt.getLabel())
980 .arg(field_str)
981 .arg(delim_str)
982 .arg(string_str)
983 .arg("0x");
984 return (0);
985 }
986
987 // Push the desired field.
988 values.push(fields[field - 1]);
989
990 // Log what we popped and pushed
992 .arg(pkt.getLabel())
993 .arg(field_str)
994 .arg(delim_str)
995 .arg(string_str)
996 .arg(toHex(values.top()));
997
998 return (0);
999}
1000
1001unsigned
1003 if (values.size() < 2) {
1004 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1005 "2 values for concat, got " << values.size());
1006 }
1007
1008 string op1 = values.top();
1009 values.pop();
1010 string op2 = values.top();
1011 values.pop(); // Dammit, std::stack interface is awkward.
1012
1013 // The top of the stack was evaluated last so this is the right order
1014 values.push(op2 + op1);
1015
1016 // Log what we popped and pushed
1018 .arg(pkt.getLabel())
1019 .arg(toHex(op1))
1020 .arg(toHex(op2))
1021 .arg(toHex(values.top()));
1022
1023 return (0);
1024}
1025
1026unsigned
1028 if (values.size() < 3) {
1029 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1030 "3 values for ifelse, got " << values.size());
1031 }
1032
1033 string iffalse = values.top();
1034 values.pop();
1035 string iftrue = values.top();
1036 values.pop();
1037 string cond = values.top();
1038 values.pop();
1039 bool val = toBool(cond);
1040
1041 if (val) {
1042 values.push(iftrue);
1043 } else {
1044 values.push(iffalse);
1045 }
1046
1047 // Log what we popped and pushed
1048 if (val) {
1050 .arg(pkt.getLabel())
1051 .arg('\'' + cond + '\'')
1052 .arg(toHex(iffalse))
1053 .arg(toHex(iftrue));
1054 } else {
1056 .arg(pkt.getLabel())
1057 .arg('\'' +cond + '\'')
1058 .arg(toHex(iftrue))
1059 .arg(toHex(iffalse));
1060 }
1061
1062 return (0);
1063}
1064
1065unsigned
1067 if (values.size() < 2) {
1068 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1069 "2 values for hexstring, got " << values.size());
1070 }
1071
1072 string separator = values.top();
1073 values.pop();
1074 string binary = values.top();
1075 values.pop();
1076
1077 bool first = true;
1078 stringstream tmp;
1079 tmp << hex;
1080 for (size_t i = 0; i < binary.size(); ++i) {
1081 if (!first) {
1082 tmp << separator;
1083 } else {
1084 first = false;
1085 }
1086 tmp << byteToHex(binary[i]);
1087 }
1088 values.push(tmp.str());
1089
1090 // Log what we popped and pushed
1092 .arg(pkt.getLabel())
1093 .arg(toHex(binary))
1094 .arg(separator)
1095 .arg(tmp.str());
1096
1097 return (0);
1098}
1099
1100unsigned
1102 if (values.size() == 0) {
1103 isc_throw(EvalBadStack, "Incorrect empty stack.");
1104 }
1105
1106 string op = values.top();
1107 values.pop();
1108 bool val = toBool(op);
1109
1110 if (!val) {
1111 values.push("true");
1112 } else {
1113 values.push("false");
1114 }
1115
1116 // Log what we popped and pushed
1118 .arg(pkt.getLabel())
1119 .arg('\'' + op + '\'')
1120 .arg('\'' + values.top() + '\'');
1121
1122 return (0);
1123}
1124
1125unsigned
1127 if (values.size() < 2) {
1128 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1129 "2 values for and operator, got " << values.size());
1130 }
1131
1132 string op1 = values.top();
1133 values.pop();
1134 bool val1 = toBool(op1);
1135 string op2 = values.top();
1136 values.pop(); // Dammit, std::stack interface is awkward.
1137 bool val2 = toBool(op2);
1138
1139 if (val1 && val2) {
1140 values.push("true");
1141 } else {
1142 values.push("false");
1143 }
1144
1145 // Log what we popped and pushed
1147 .arg(pkt.getLabel())
1148 .arg('\'' + op1 + '\'')
1149 .arg('\'' + op2 + '\'')
1150 .arg('\'' + values.top() + '\'');
1151
1152 return (0);
1153}
1154
1155unsigned
1157 if (values.size() < 2) {
1158 isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
1159 "2 values for or operator, got " << values.size());
1160 }
1161
1162 string op1 = values.top();
1163 values.pop();
1164 bool val1 = toBool(op1);
1165 string op2 = values.top();
1166 values.pop(); // Dammit, std::stack interface is awkward.
1167 bool val2 = toBool(op2);
1168
1169 if (val1 || val2) {
1170 values.push("true");
1171 } else {
1172 values.push("false");
1173 }
1174
1175 // Log what we popped and pushed
1177 .arg(pkt.getLabel())
1178 .arg('\'' + op1 + '\'')
1179 .arg('\'' + op2 + '\'')
1180 .arg('\'' + values.top() + '\'');
1181
1182 return (0);
1183}
1184
1185unsigned
1187 if (pkt.inClass(client_class_)) {
1188 values.push("true");
1189 } else {
1190 values.push("false");
1191 }
1192
1193 // Log what we pushed
1195 .arg(pkt.getLabel())
1196 .arg(client_class_)
1197 .arg('\'' + values.top() + '\'');
1198
1199 return (0);
1200}
1201
1203 const std::vector<uint16_t>& option_codes)
1204 : TokenOption(option_codes, repr), universe_(u), vendor_id_(vendor_id),
1205 field_(option_codes.size() ? SUBOPTION : EXISTS) {
1206}
1207
1209 : TokenOption(std::vector<uint16_t>{}, TokenOption::HEXADECIMAL), universe_(u),
1210 vendor_id_(vendor_id), field_(field) {
1211 if (field_ == EXISTS) {
1212 representation_type_ = TokenOption::EXISTS;
1213 }
1214}
1215
1216uint32_t
1218 return (vendor_id_);
1219}
1220
1223 return (field_);
1224}
1225
1226unsigned
1228 // Get the option first.
1229 uint16_t code = 0;
1230 switch (universe_) {
1231 case Option::V4:
1232 code = DHO_VIVSO_SUBOPTIONS;
1233 break;
1234 case Option::V6:
1235 code = D6O_VENDOR_OPTS;
1236 break;
1237 }
1238
1239 OptionPtr opt = pkt.getOption(code);
1240 OptionVendorPtr vendor = boost::dynamic_pointer_cast<OptionVendor>(opt);
1241 if (!vendor) {
1242 // There's no vendor option, give up.
1243 std::string txt = pushFailure(values);
1245 .arg(pkt.getLabel())
1246 .arg(code)
1247 .arg(txt);
1248 return (0);
1249 }
1250
1251 if (vendor_id_ && (vendor_id_ != vendor->getVendorId())) {
1252 // There is vendor option, but it has other vendor-id value
1253 // than we're looking for. (0 means accept any vendor-id)
1254 std::string txt = pushFailure(values);
1256 .arg(pkt.getLabel())
1257 .arg(vendor_id_)
1258 .arg(vendor->getVendorId())
1259 .arg(txt);
1260 return (0);
1261 }
1262
1263 switch (field_) {
1264 case ENTERPRISE_ID:
1265 {
1266 // Extract enterprise-id
1267 string txt(sizeof(uint32_t), 0);
1268 uint32_t value = htonl(vendor->getVendorId());
1269 memcpy(&txt[0], &value, sizeof(uint32_t));
1270 values.push(txt);
1272 .arg(pkt.getLabel())
1273 .arg(vendor->getVendorId())
1274 .arg(util::encode::encodeHex(std::vector<uint8_t>(txt.begin(),
1275 txt.end())));
1276 break;
1277 }
1278 case SUBOPTION:
1281 return (TokenOption::evaluate(pkt, values));
1282 case EXISTS:
1283 // We already passed all the checks: the option is there and has specified
1284 // enterprise-id.
1286 .arg(pkt.getLabel())
1287 .arg(vendor->getVendorId())
1288 .arg("true");
1289 values.push("true");
1290 break;
1291 case DATA:
1292 // This is for vendor-class option, we can skip it here.
1293 isc_throw(EvalTypeError, "Field None is not valid for vendor-class");
1294 break;
1295 }
1296
1297 return (0);
1298}
1299
1302 uint16_t code = 0;
1303 switch (universe_) {
1304 case Option::V4:
1305 code = DHO_VIVSO_SUBOPTIONS;
1306 break;
1307 case Option::V6:
1308 code = D6O_VENDOR_OPTS;
1309 break;
1310 }
1311
1312 OptionPtr option = pkt.getOption(code);
1313 if (!option) {
1314 // If vendor option is not found, return NULL
1315 return (OptionPtr());
1316 }
1317
1318 // If vendor option is found, try to return its
1319 // encapsulated option.
1320 for (auto const& c : option_path_) {
1321 option = option->getOption(c);
1322 if (!option) {
1323 break;
1324 }
1325 }
1326 return (option);
1327}
1328
1330 RepresentationType repr)
1331 : TokenVendor(u, vendor_id, repr, std::vector<uint16_t> {}), index_(0) {
1332}
1333
1335 FieldType field, uint16_t index)
1336 : TokenVendor(u, vendor_id, TokenOption::HEXADECIMAL, { }), index_(index) {
1337 field_ = field;
1338}
1339
1340uint16_t
1342 return (index_);
1343}
1344
1345unsigned
1347 // Get the option first.
1348 uint16_t code = 0;
1349 switch (universe_) {
1350 case Option::V4:
1351 code = DHO_VIVCO_SUBOPTIONS;
1352 break;
1353 case Option::V6:
1354 code = D6O_VENDOR_CLASS;
1355 break;
1356 }
1357
1358 OptionPtr opt = pkt.getOption(code);
1359 OptionVendorClassPtr vendor = boost::dynamic_pointer_cast<OptionVendorClass>(opt);
1360 if (!vendor) {
1361 // There's no vendor class option, give up.
1362 std::string txt = pushFailure(values);
1364 .arg(pkt.getLabel())
1365 .arg(code)
1366 .arg(txt);
1367 return (0);
1368 }
1369
1370 if (vendor_id_ && (vendor_id_ != vendor->getVendorId())) {
1371 // There is vendor option, but it has other vendor-id value
1372 // than we're looking for. (0 means accept any vendor-id)
1373 std::string txt = pushFailure(values);
1375 .arg(pkt.getLabel())
1376 .arg(vendor_id_)
1377 .arg(vendor->getVendorId())
1378 .arg(txt);
1379 return (0);
1380 }
1381
1382 switch (field_) {
1383 case ENTERPRISE_ID:
1384 {
1385 // Extract enterprise-id
1386 string txt(sizeof(uint32_t), 0);
1387 uint32_t value = htonl(vendor->getVendorId());
1388 memcpy(&txt[0], &value, sizeof(uint32_t));
1389 values.push(txt);
1391 .arg(pkt.getLabel())
1392 .arg(vendor->getVendorId())
1393 .arg(util::encode::encodeHex(std::vector<uint8_t>(txt.begin(),
1394 txt.end())));
1395 break;
1396 }
1397 case SUBOPTION:
1398 // Extract sub-options
1399 isc_throw(EvalTypeError, "Field None is not valid for vendor-class");
1400 break;
1401 case EXISTS:
1402 // We already passed all the checks: the option is there and has specified
1403 // enterprise-id.
1405 .arg(pkt.getLabel())
1406 .arg(vendor->getVendorId())
1407 .arg("true");
1408 values.push("true");
1409 break;
1410 case DATA:
1411 {
1412 size_t max = vendor->getTuplesNum();
1413 if (static_cast<size_t>(index_ + 1) > max) {
1414 // The index specified is out of bounds, e.g. there are only
1415 // 2 tuples and index specified is 5.
1417 .arg(pkt.getLabel())
1418 .arg(index_)
1419 .arg(vendor->getVendorId())
1420 .arg(max)
1421 .arg("");
1422 values.push("");
1423 break;
1424 }
1425
1426 OpaqueDataTuple tuple = vendor->getTuple(index_);
1427 OpaqueDataTuple::Buffer buf = tuple.getData();
1428 string txt(buf.begin(), buf.end());
1429
1431 .arg(pkt.getLabel())
1432 .arg(index_)
1433 .arg(max)
1434 .arg(txt);
1435
1436 values.push(txt);
1437 break;
1438 }
1439 default:
1440 isc_throw(EvalTypeError, "Invalid field specified." << field_);
1441 }
1442
1443 return (0);
1444}
1445
1446TokenInteger::TokenInteger(const uint32_t value)
1447 : TokenString(EvalContext::fromUint32(value)), int_value_(value) {
1448}
1449
1450TokenMatch::TokenMatch(const std::string& reg_exp) : reg_exp_str_(reg_exp) {
1451 try {
1452 reg_exp_ = regex(reg_exp);
1453 } catch (const exception& ex) {
1454 isc_throw(EvalParseError, "invalid regular expression '" << reg_exp
1455 << "': " << ex.what());
1456 }
1457}
1458
1459unsigned
1461 if (values.size() == 0) {
1462 isc_throw(EvalBadStack, "Incorrect empty stack.");
1463 }
1464
1465 string val = values.top();
1466 values.pop();
1467 string txt = "false";
1468 try {
1469 if (regex_match(val, reg_exp_)) {
1470 txt = "true";
1471 }
1473 .arg(reg_exp_str_)
1474 .arg(val)
1475 .arg(txt);
1476 } catch (const exception& ex) {
1478 .arg(reg_exp_str_)
1479 .arg(val)
1480 .arg(ex.what());
1481 }
1482 values.push(txt);
1483
1484 return (0);
1485}
1486
1487TokenLabel::TokenLabel(const unsigned label) : label_(label) {
1488 if (label == 0) {
1489 isc_throw(EvalParseError, "label must be not zero");
1490 }
1491}
1492
1493unsigned
1495 return (0);
1496}
1497
1498TokenBranch::TokenBranch(const unsigned target) : target_(target) {
1499 if (target == 0) {
1500 isc_throw(EvalParseError, "target must be not zero");
1501 }
1502}
1503
1504unsigned
1510
1512 : TokenBranch(target) {
1513}
1514
1515unsigned
1517 if (values.size() == 0) {
1518 isc_throw(EvalBadStack, "Incorrect empty stack.");
1519 }
1520
1521 string op = values.top();
1522 bool val = toBool(op);
1523
1524 if (!val) {
1525 values.pop();
1526 return (0);
1527 }
1528
1530 .arg(target_);
1531 return (target_);
1532}
1533
1535 : TokenBranch(target) {
1536}
1537
1538unsigned
1540 if (values.size() == 0) {
1541 isc_throw(EvalBadStack, "Incorrect empty stack.");
1542 }
1543
1544 string op = values.top();
1545 bool val = toBool(op);
1546
1547 if (val) {
1548 values.pop();
1549 return (0);
1550 }
1551
1553 .arg(target_);
1554 return (target_);
1555}
1556
1558 : TokenBranch(target) {
1559}
1560
1561unsigned
1563 if (values.size() == 0) {
1564 isc_throw(EvalBadStack, "Incorrect empty stack.");
1565 }
1566
1567 string op = values.top();
1568 values.pop();
1569 bool val = toBool(op);
1570
1571 if (val) {
1572 return (0);
1573 }
1574
1576 .arg(target_);
1577 return (target_);
1578}
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:38
EvalTypeError is thrown when a value on the stack has a content with an unexpected type.
Definition token.h:46
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:90
Represents DHCPv4 packet.
Definition pkt4.h:37
const isc::asiolink::IOAddress & getSiaddr() const
Returns siaddr field.
Definition pkt4.h:195
const isc::asiolink::IOAddress & getYiaddr() const
Returns yiaddr field.
Definition pkt4.h:207
const isc::asiolink::IOAddress & getGiaddr() const
Returns giaddr field.
Definition pkt4.h:219
const isc::asiolink::IOAddress & getCiaddr() const
Returns ciaddr field.
Definition pkt4.h:183
HWAddrPtr getHWAddr() const
returns hardware address information
Definition pkt4.h:325
uint8_t getHlen() const
Returns hlen field.
Definition pkt4.cc:612
uint8_t getType() const
Returns DHCP message type (e.g.
Definition pkt4.cc:236
uint8_t getHtype() const
Returns htype field.
Definition pkt4.cc:604
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:476
virtual uint8_t getType() const
Returns message type (e.g.
Definition pkt6.h:223
Base class for classes representing DHCP messages.
Definition pkt.h:161
const isc::asiolink::IOAddress & getLocalAddr() const
Returns local IP address.
Definition pkt.h:626
const isc::asiolink::IOAddress & getRemoteAddr() const
Returns remote IP address.
Definition pkt.h:612
uint32_t getTransid() const
Returns value of transaction-id field.
Definition pkt.h:342
std::string getIface() const
Returns interface name.
Definition pkt.h:699
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
virtual std::string getLabel() const
Returns text representation primary packet identifiers.
Definition pkt.h:275
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Logical and.
Definition token.cc:1126
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Only return the target.
Definition token.cc:1505
TokenBranch(const unsigned target)
Constructor.
Definition token.cc:1498
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Concatenate two values.
Definition token.cc:1002
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Compare two values.
Definition token.cc:787
std::string value_
Constant value.
Definition token.h:170
virtual unsigned 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:83
TokenHexString(const std::string &str)
Value is set during token construction.
Definition token.cc:54
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Alternative.
Definition token.cc:1027
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:235
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:268
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:203
TokenInteger(const uint32_t value)
Integer value set during construction.
Definition token.cc:1446
uint32_t int_value_
value as integer (stored for testing only)
Definition token.h:235
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:166
std::string value_
< Constant value (empty string if the IP address cannot be converted)
Definition token.h:259
TokenIpAddress(const std::string &addr)
Value is set during token construction.
Definition token.cc:137
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack after decoding).
Definition token.cc:153
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Does nothing.
Definition token.cc:1494
TokenLabel(const unsigned label)
Constructor.
Definition token.cc:1487
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the evaluated string expression converted to lower case on the stack)...
Definition token.cc:96
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Match regular expression.
Definition token.cc:1460
TokenMatch(const std::string &reg_exp)
Constructor.
Definition token.cc:1450
ClientClass client_class_
The client class name.
Definition token.h:1132
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (check if client_class_ was added to packet client classes).
Definition token.cc:1186
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Logical negation.
Definition token.cc:1101
Token that represents a value of an option.
Definition token.h:407
virtual OptionPtr getOption(Pkt &pkt)
Attempts to retrieve an option.
Definition token.cc:399
RepresentationType representation_type_
The representation type.
Definition token.h:487
std::vector< uint16_t > option_path_
The options hierarchy.
Definition token.h:484
RepresentationType
Token representation type.
Definition token.h:417
TokenOption(const std::vector< uint16_t > &option_codes, const RepresentationType &rep_type)
Constructor that takes an option code as a parameter.
Definition token.h:430
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Evaluates the values of the option.
Definition token.cc:418
virtual std::string pushFailure(ValueStack &values)
Auxiliary method that puts string representing a failure.
Definition token.cc:472
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Logical or.
Definition token.cc:1156
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Gets a value from the specified packet.
Definition token.cc:598
@ CIADDR
ciaddr (IPv4 address)
Definition token.h:639
@ HLEN
hlen (hardware address length)
Definition token.h:642
@ HTYPE
htype (hardware address type)
Definition token.h:643
@ GIADDR
giaddr (IPv4 address)
Definition token.h:638
@ CHADDR
chaddr field (up to 16 bytes link-layer address)
Definition token.h:637
@ YIADDR
yiaddr (IPv4 address)
Definition token.h:640
@ SIADDR
siaddr (IPv4 address)
Definition token.h:641
@ TRANSID
transaction-id (xid)
Definition token.h:645
@ MSGTYPE
message type (not really a field, content of option 53)
Definition token.h:644
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Gets a value of the specified packet.
Definition token.cc:679
@ TRANSID
transaction id (integer but manipulated as a string)
Definition token.h:692
@ MSGTYPE
msg type
Definition token.h:691
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Gets a value from the specified packet.
Definition token.cc:545
@ LEN
length (4 octets)
Definition token.h:590
@ DST
destination (IP address)
Definition token.h:589
@ IFACE
interface name (string)
Definition token.h:587
@ SRC
source (IP address)
Definition token.h:588
TokenPopAndBranchFalse(const unsigned target)
Constructor.
Definition token.cc:1557
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Pops the top of stack which must be "false" or "true".
Definition token.cc:1562
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Looks at the top of stack which must be "false" or "true".
Definition token.cc:1539
TokenPopOrBranchFalse(const unsigned target)
Constructor.
Definition token.cc:1534
TokenPopOrBranchTrue(const unsigned target)
Constructor.
Definition token.cc:1511
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Looks at the top of stack which must be "false" or "true".
Definition token.cc:1516
virtual OptionPtr getOption(Pkt &pkt)
Attempts to obtain specified sub-option of option 82 from the packet.
Definition token.cc:482
FieldType type_
field to get
Definition token.h:790
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Extracts the specified field from the requested relay.
Definition token.cc:721
int8_t nest_level_
Specifies field of the DHCPv6 relay option to get.
Definition token.h:789
@ LINKADDR
Link address field (IPv6 address).
Definition token.h:745
@ PEERADDR
Peer address field (IPv6 address).
Definition token.h:744
int8_t nest_level_
The nesting level of the relay block to use.
Definition token.h:569
virtual OptionPtr getOption(Pkt &pkt)
Attempts to obtain specified option from the specified relay block.
Definition token.cc:500
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Extract a field from a delimited string.
Definition token.cc:914
std::string value_
Constant value.
Definition token.h:144
TokenString(const std::string &str)
Value is set during token construction.
Definition token.h:134
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack).
Definition token.cc:42
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Extract a substring from a string.
Definition token.cc:814
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Convert a binary value to its hexadecimal string representation.
Definition token.cc:1066
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:333
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:366
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding).
Definition token.cc:301
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the evaluated string expression converted to upper case on the stack)...
Definition token.cc:117
TokenVendorClass(Option::Universe u, uint32_t vendor_id, RepresentationType repr)
This constructor is used to access fields.
Definition token.cc:1329
uint16_t getDataIndex() const
Returns data index.
Definition token.cc:1341
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
Definition token.cc:1346
uint16_t index_
Data chunk index.
Definition token.h:1318
Option::Universe universe_
Universe (V4 or V6).
Definition token.h:1235
uint32_t vendor_id_
Enterprise-id value.
Definition token.h:1241
FieldType field_
Specifies which field should be accessed.
Definition token.h:1244
uint32_t getVendorId() const
Returns enterprise-id.
Definition token.cc:1217
virtual unsigned evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
Definition token.cc:1227
TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field)
Constructor used for accessing a field.
Definition token.cc:1208
virtual OptionPtr getOption(Pkt &pkt)
Attempts to get a suboption.
Definition token.cc:1301
FieldType
Specifies a field of the vendor option.
Definition token.h:1153
@ DATA
data chunk, used in derived vendor-class only
Definition token.h:1157
@ EXISTS
vendor[123].exists
Definition token.h:1156
@ ENTERPRISE_ID
enterprise-id field (vendor-info, vendor-class)
Definition token.h:1155
@ SUBOPTION
If this token fetches a suboption, not a field.
Definition token.h:1154
FieldType getField() const
Returns field.
Definition token.cc:1222
static bool toBool(std::string value)
Coverts a (string) value to a boolean.
Definition token.h:105
Evaluation context, an interface to the expression evaluation.
static std::string fromUint32(const uint32_t integer)
Converts unsigned 32bit integer to string representation.
Evaluation error exception raised when trying to parse an exceptions.
@ 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_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
const isc::log::MessageID EVAL_DEBUG_POP_AND_BRANCH_FALSE
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
const isc::log::MessageID EVAL_DEBUG_MATCH_ERROR
const isc::log::MessageID EVAL_DEBUG_POP_OR_BRANCH_TRUE
const isc::log::MessageID EVAL_DEBUG_RELAY6_RANGE
const isc::log::MessageID EVAL_DEBUG_UCASE
const isc::log::MessageID EVAL_DEBUG_UINT32TOTEXT
const isc::log::MessageID EVAL_DEBUG_UINT16TOTEXT
const isc::log::MessageID EVAL_DEBUG_SPLIT_EMPTY
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_EXISTS
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND
const isc::log::MessageID EVAL_DEBUG_PKT
@ DHO_VIVCO_SUBOPTIONS
Definition dhcp4.h:188
@ DHO_DHCP_AGENT_OPTIONS
Definition dhcp4.h:151
@ DHO_VIVSO_SUBOPTIONS
Definition dhcp4.h:189
const isc::log::MessageID EVAL_DEBUG_HEXSTRING
const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA
const isc::log::MessageID EVAL_DEBUG_SPLIT_FIELD_OUT_OF_RANGE
const isc::log::MessageID EVAL_DEBUG_INT32TOTEXT
const isc::log::MessageID EVAL_DEBUG_OPTION
const int EVAL_DBG_STACK
Definition eval_log.h:26
const isc::log::MessageID EVAL_DEBUG_SUBSTRING
const isc::log::MessageID EVAL_DEBUG_PKT6
const isc::log::MessageID EVAL_DEBUG_RELAY6
const isc::log::MessageID EVAL_DEBUG_OR
const isc::log::MessageID EVAL_DEBUG_INT8TOTEXT
const isc::log::MessageID EVAL_DEBUG_VENDOR_ENTERPRISE_ID
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:154
const isc::log::MessageID EVAL_DEBUG_STRING
const isc::log::MessageID EVAL_DEBUG_MATCH
const isc::log::MessageID EVAL_DEBUG_VENDOR_ENTERPRISE_ID_MISMATCH
const isc::log::MessageID EVAL_DEBUG_BRANCH
const isc::log::MessageID EVAL_DEBUG_SPLIT
const isc::log::MessageID EVAL_DEBUG_PKT4
const isc::log::MessageID EVAL_DEBUG_INT16TOTEXT
isc::log::Logger eval_logger("eval")
Eval Logger.
Definition eval_log.h:33
const isc::log::MessageID EVAL_DEBUG_CONCAT
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID_MISMATCH
const isc::log::MessageID EVAL_DEBUG_VENDOR_EXISTS
const isc::log::MessageID EVAL_DEBUG_VENDOR_NO_OPTION
const isc::log::MessageID EVAL_DEBUG_LCASE
boost::shared_ptr< OptionVendorClass > OptionVendorClassPtr
Defines a pointer to the OptionVendorClass.
const isc::log::MessageID EVAL_DEBUG_IPADDRESS
const isc::log::MessageID EVAL_DEBUG_AND
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_NO_OPTION
const isc::log::MessageID EVAL_DEBUG_POP_OR_BRANCH_FALSE
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID
const isc::log::MessageID EVAL_DEBUG_UINT8TOTEXT
const isc::log::MessageID EVAL_DEBUG_EQUAL
const isc::log::MessageID EVAL_DEBUG_IPADDRESSTOTEXT
const isc::log::MessageID EVAL_DEBUG_SPLIT_DELIM_EMPTY
const isc::log::MessageID EVAL_DEBUG_MEMBER
const isc::log::MessageID EVAL_DEBUG_IFELSE_TRUE
const isc::log::MessageID EVAL_DEBUG_NOT
boost::shared_ptr< Option > OptionPtr
Definition option.h:37
const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE
std::stack< std::string > ValueStack
Evaluated values are stored as a stack of strings.
Definition token.h:34
const isc::log::MessageID EVAL_DEBUG_IFELSE_FALSE
const isc::log::MessageID EVAL_DEBUG_SUBSTRING_EMPTY
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
const std::string & byteToHex(uint8_t byte)
Converts a byte to a two hex digit string.
Definition str.cc:403
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
std::string toHex(std::string value)
Encode in hexadecimal inline.
Definition encode.h:293