17 #include <boost/lexical_cast.hpp> 23 #include <boost/algorithm/string/classification.hpp> 24 #include <boost/algorithm/string/split.hpp> 45 .arg(
'\'' + value_ +
'\'');
48 TokenHexString::TokenHexString(
const string& str) : value_(
"") {
50 if ((str.size() < 3) ||
52 ((str[1] !=
'x') && (str[1] !=
'X'))) {
55 string digits = str.substr(2);
58 vector<uint8_t> binary;
63 if ((digits.length() % 2) != 0) {
64 digits = digits.insert(0,
"0");
72 value_.resize(binary.size());
73 memmove(&
value_[0], &binary[0], binary.size());
88 vector<uint8_t> binary;
97 value_.resize(binary.size());
98 memmove(&
value_[0], &binary[0], binary.size());
113 if (values.size() == 0) {
117 string op = values.top();
118 size_t size = op.size();
126 if ((size != V4ADDRESS_LEN) && (size != V6ADDRESS_LEN)) {
130 std::vector<uint8_t> binary(op.begin(), op.end());
132 if (size == V4ADDRESS_LEN) {
147 if (values.size() == 0) {
151 string op = values.top();
152 size_t size = op.size();
160 if (size !=
sizeof(int8_t)) {
165 tmp << static_cast<int32_t>(*(
reinterpret_cast<int8_t*
>(
const_cast<char*
>(op.data()))));
176 if (values.size() == 0) {
180 string op = values.top();
181 size_t size = op.size();
189 if (size !=
sizeof(int16_t)) {
194 uint16_t value = *(
reinterpret_cast<uint16_t*
>(
const_cast<char*
>(op.data())));
195 std::string data = EvalContext::fromUint16(value);
196 tmp << *(reinterpret_cast<int16_t*>(
const_cast<char*
>(data.data())));
207 if (values.size() == 0) {
211 string op = values.top();
212 size_t size = op.size();
220 if (size !=
sizeof(int32_t)) {
225 uint32_t value = *(
reinterpret_cast<uint32_t*
>(
const_cast<char*
>(op.data())));
226 std::string data = EvalContext::fromUint32(value);
227 tmp << *(reinterpret_cast<int32_t*>(
const_cast<char*
>(data.data())));
238 if (values.size() == 0) {
242 string op = values.top();
243 size_t size = op.size();
251 if (size !=
sizeof(uint8_t)) {
256 tmp << static_cast<uint32_t>(*(
reinterpret_cast<uint8_t*
>(
const_cast<char*
>(op.data()))));
267 if (values.size() == 0) {
271 string op = values.top();
272 size_t size = op.size();
280 if (size !=
sizeof(uint16_t)) {
285 uint16_t value = *(
reinterpret_cast<uint16_t*
>(
const_cast<char*
>(op.data())));
286 std::string data = EvalContext::fromUint16(value);
287 tmp << *(reinterpret_cast<uint16_t*>(
const_cast<char*
>(data.data())));
298 if (values.size() == 0) {
302 string op = values.top();
303 size_t size = op.size();
311 if (size !=
sizeof(uint32_t)) {
316 uint32_t value = *(
reinterpret_cast<uint32_t*
>(
const_cast<char*
>(op.data())));
317 std::string data = EvalContext::fromUint32(value);
318 tmp << *(reinterpret_cast<uint32_t*>(
const_cast<char*
>(data.data())));
337 if (representation_type_ == TEXTUAL) {
338 opt_str = opt->toString();
339 }
else if (representation_type_ == HEXADECIMAL) {
340 std::vector<uint8_t> binary = opt->toBinary();
341 opt_str.resize(binary.size());
342 if (!binary.empty()) {
343 memmove(&opt_str[0], &binary[0], binary.size());
348 }
else if (representation_type_ == EXISTS) {
354 values.push(opt_str);
359 if (representation_type_ == HEXADECIMAL) {
362 .arg(
toHex(opt_str));
366 .arg(
'\'' + opt_str +
'\'');
373 if (representation_type_ == EXISTS) {
400 Pkt6& pkt6 =
dynamic_cast<Pkt6&
>(pkt);
405 if (nest_level_ >= 0) {
406 uint8_t nesting_level =
static_cast<uint8_t
>(nest_level_);
409 int nesting_level = pkt6.
relay_info_.size() + nest_level_;
410 if (nesting_level < 0) {
414 static_cast<uint8_t>(nesting_level)));
425 }
catch (
const std::bad_cast&) {
434 vector<uint8_t> binary;
436 bool is_binary =
true;
437 bool print_hex =
true;
458 value = EvalContext::fromUint32(static_cast<uint32_t>(const_cast<Pkt&>(pkt).len()));
465 << static_cast<int>(type_) );
469 value.resize(binary.size());
470 if (!binary.empty()) {
471 memmove(&value[0], &binary[0], binary.size());
479 .arg(print_hex ?
toHex(value) : value);
484 vector<uint8_t> binary;
491 const Pkt4& pkt4 =
dynamic_cast<const Pkt4&
>(pkt);
500 "Packet does not have hardware address");
502 binary = hwaddr->hwaddr_;
524 value = EvalContext::fromUint32(pkt4.
getHlen());
529 value = EvalContext::fromUint32(pkt4.
getHtype());
533 value = EvalContext::fromUint32(pkt4.
getType());
534 type_str =
"msgtype";
537 value = EvalContext::fromUint32(pkt4.
getTransid());
538 type_str =
"transid";
542 << static_cast<int>(type_) );
545 }
catch (
const std::bad_cast&) {
549 if (!binary.empty()) {
550 value.resize(binary.size());
551 memmove(&value[0], &binary[0], binary.size());
569 const Pkt6& pkt6 =
dynamic_cast<const Pkt6&
>(pkt);
574 value = EvalContext::fromUint32(pkt6.
getType());
575 type_str =
"msgtype";
580 value = EvalContext::fromUint32(pkt6.
getTransid());
581 type_str =
"transid";
586 << static_cast<int>(type_) );
589 }
catch (
const std::bad_cast&) {
603 vector<uint8_t> binary;
608 const Pkt6& pkt6 =
dynamic_cast<const Pkt6&
>(pkt);
612 if (nest_level_ >= 0) {
613 relay_level =
static_cast<uint8_t
>(nest_level_);
615 int nesting_level = pkt6.
relay_info_.size() + nest_level_;
616 if (nesting_level < 0) {
620 relay_level =
static_cast<uint8_t
>(nesting_level);
626 type_str =
"linkaddr";
630 type_str =
"peeraddr";
641 .arg(
int(nest_level_))
645 }
catch (
const std::bad_cast&) {
650 value.resize(binary.size());
651 if (!binary.empty()) {
652 memmove(&value[0], &binary[0], binary.size());
659 .arg(
int(nest_level_))
665 if (values.size() < 2) {
667 "2 values for == operator, got " << values.size());
670 string op1 = values.top();
672 string op2 = values.top();
678 values.push(
"false");
684 .arg(
'\'' + values.top() +
'\'');
689 if (values.size() < 3) {
691 "3 values for substring operator, got " << values.size());
694 string len_str = values.top();
696 string start_str = values.top();
698 string string_str = values.top();
702 if (string_str.empty()) {
721 start_pos = boost::lexical_cast<
int>(start_str);
722 }
catch (
const boost::bad_lexical_cast&) {
724 <<
"' for the starting position of the substring " 725 <<
"couldn't be converted to an integer.");
728 if (len_str ==
"all") {
729 length = string_str.length();
731 length = boost::lexical_cast<
int>(len_str);
733 }
catch (
const boost::bad_lexical_cast&) {
735 <<
"' for the length of the substring " 736 <<
"couldn't be converted to an integer.");
739 const int string_length = string_str.length();
742 if ((start_pos < -string_length) || (start_pos >= string_length)) {
749 .arg(
toHex(string_str))
758 start_pos = string_length + start_pos;
763 if (length <= start_pos){
772 values.push(string_str.substr(start_pos, length));
778 .arg(
toHex(string_str))
779 .arg(
toHex(values.top()));
784 if (values.size() < 3) {
786 "3 values for split operator, got " << values.size());
790 string field_str = values.top();
792 string delim_str = values.top();
794 string string_str = values.top();
798 if (string_str.empty()) {
814 field = boost::lexical_cast<
int>(field_str);
815 }
catch (
const boost::bad_lexical_cast&) {
817 <<
"' for the field field for split " 818 <<
"couldn't be converted to an integer.");
822 if (delim_str.empty()) {
823 values.push(string_str);
830 .arg(
toHex(values.top()));
835 std::vector<std::string> fields;
836 boost::split(fields, string_str, boost::is_any_of(delim_str),
837 boost::algorithm::token_compress_off);
840 if (field < 1 || field > fields.size()) {
854 values.push(fields[field - 1]);
861 .arg(
toHex(values.top()));
866 if (values.size() < 2) {
868 "2 values for concat, got " << values.size());
871 string op1 = values.top();
873 string op2 = values.top();
877 values.push(op2 + op1);
883 .arg(
toHex(values.top()));
888 if (values.size() < 3) {
890 "3 values for ifelse, got " << values.size());
893 string iffalse = values.top();
895 string iftrue = values.top();
897 string cond = values.top();
904 values.push(iffalse);
910 .arg(
'\'' + cond +
'\'')
915 .arg(
'\'' +cond +
'\'')
917 .arg(
toHex(iffalse));
923 if (values.size() < 2) {
925 "2 values for hexstring, got " << values.size());
928 string separator = values.top();
930 string binary = values.top();
936 for (
size_t i = 0; i < binary.size(); ++i) {
942 tmp << setw(2) << setfill(
'0')
943 << (
static_cast<unsigned>(binary[i]) & 0xff);
945 values.push(tmp.str());
956 if (values.size() == 0) {
960 string op = values.top();
967 values.push(
"false");
972 .arg(
'\'' + op +
'\'')
973 .arg(
'\'' + values.top() +
'\'');
978 if (values.size() < 2) {
980 "2 values for and operator, got " << values.size());
983 string op1 = values.top();
986 string op2 = values.top();
993 values.push(
"false");
998 .arg(
'\'' + op1 +
'\'')
999 .arg(
'\'' + op2 +
'\'')
1000 .arg(
'\'' + values.top() +
'\'');
1005 if (values.size() < 2) {
1007 "2 values for or operator, got " << values.size());
1010 string op1 = values.top();
1013 string op2 = values.top();
1018 values.push(
"true");
1020 values.push(
"false");
1025 .arg(
'\'' + op1 +
'\'')
1026 .arg(
'\'' + op2 +
'\'')
1027 .arg(
'\'' + values.top() +
'\'');
1032 if (pkt.
inClass(client_class_)) {
1033 values.push(
"true");
1035 values.push(
"false");
1041 .arg(
'\'' + values.top() +
'\'');
1045 uint16_t option_code)
1046 :
TokenOption(option_code, repr), universe_(u), vendor_id_(vendor_id),
1047 field_(option_code ? SUBOPTION :
EXISTS) {
1095 .arg(vendor->getVendorId())
1104 string txt(
sizeof(uint32_t), 0);
1105 uint32_t value = htonl(vendor->getVendorId());
1106 memcpy(&txt[0], &value,
sizeof(uint32_t));
1109 .arg(vendor->getVendorId())
1123 .arg(vendor->getVendorId())
1125 values.push(
"true");
1200 .arg(vendor->getVendorId())
1209 string txt(
sizeof(uint32_t), 0);
1210 uint32_t value = htonl(vendor->getVendorId());
1211 memcpy(&txt[0], &value,
sizeof(uint32_t));
1214 .arg(vendor->getVendorId())
1227 .arg(vendor->getVendorId())
1229 values.push(
"true");
1233 size_t max = vendor->getTuplesNum();
1239 .arg(vendor->getVendorId())
1248 string txt(buf.begin(), buf.end());
1272 return (parent->getOption(sub_option_code_));
1283 if (representation_type_ == EXISTS) {
1290 if (representation_type_ == EXISTS) {
1294 if (representation_type_ == TEXTUAL) {
1295 txt = sub->toString();
1296 }
else if (representation_type_ == HEXADECIMAL) {
1297 std::vector<uint8_t> binary = sub->toBinary();
1298 txt.resize(binary.size());
1299 if (!binary.empty()) {
1300 memmove(&txt[0], &binary[0], binary.size());
1315 if (representation_type_ == HEXADECIMAL) {
1318 .arg(sub_option_code_)
1323 .arg(sub_option_code_)
1324 .arg(
'\'' + txt +
'\'');
data chunk, used in derived vendor-class only
boost::shared_ptr< OptionVendorClass > OptionVendorClassPtr
Defines a pointer to the OptionVendorClass.
void evaluate(Pkt &pkt, ValueStack &values)
Logical negation.
uint32_t vendor_id_
Enterprise-id value.
virtual OptionPtr getOption(Pkt &pkt)
Attempts to get a suboption.
uint8_t getHlen() const
Returns hlen field.
HWAddrPtr getHWAddr() const
returns hardware address information
const isc::log::MessageID EVAL_DEBUG_VENDOR_NO_OPTION
void evaluate(Pkt &pkt, ValueStack &values)
Alternative.
const isc::log::MessageID EVAL_DEBUG_SPLIT_EMPTY
The order where Token subtypes are declared should be:
uint8_t getHtype() const
Returns htype field.
const isc::asiolink::IOAddress & getRelay6LinkAddress(uint8_t relay_level) const
return the link address field from a relay option
const isc::log::MessageID EVAL_DEBUG_IPADDRESS
const isc::log::MessageID EVAL_DEBUG_OPTION
uint16_t getDataIndex() const
Returns data index.
const isc::log::MessageID EVAL_DEBUG_IPADDRESSTOTEXT
const isc::log::MessageID EVAL_DEBUG_SUB_OPTION
bool inClass(const isc::dhcp::ClientClass &client_class)
Checks whether a client belongs to a given class.
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_EXISTS
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
void evaluate(Pkt &pkt, ValueStack &values)
Gets a value from the specified packet.
virtual OptionPtr getSubOption(const OptionPtr &parent)
Attempts to retrieve a sub-option.
std::string value_
< Constant value (empty string if the IP address cannot be converted)
const isc::log::MessageID EVAL_DEBUG_SPLIT_FIELD_OUT_OF_RANGE
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_NO_OPTION
const isc::log::MessageID EVAL_DEBUG_PKT6
const isc::log::MessageID EVAL_DEBUG_SUBSTRING_EMPTY
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
const isc::log::MessageID EVAL_DEBUG_SUB_OPTION_NO_OPTION
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
const isc::asiolink::IOAddress & getCiaddr() const
Returns ciaddr field.
const isc::log::MessageID EVAL_DEBUG_SPLIT
uint16_t option_code_
Code of the option to be extracted.
If this token fetches a suboption, not a field.
const isc::log::MessageID EVAL_DEBUG_PKT4
void evaluate(Pkt &pkt, ValueStack &values)
Gets a value of the specified packet.
Base class for classes representing DHCP messages.
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (check if client_class_ was added to packet client classes)
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID EVAL_DEBUG_VENDOR_ENTERPRISE_ID
const isc::log::MessageID EVAL_DEBUG_SPLIT_DELIM_EMPTY
Universe
defines option universe DHCPv4 or DHCPv6
Represents a DHCPv6 packet.
const isc::asiolink::IOAddress & getSiaddr() const
Returns siaddr field.
FieldType
Specifies a field of the vendor option.
OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level)
Returns option inserted by relay.
void evaluate(Pkt &pkt, ValueStack &values)
Extracts the specified field from the requested relay.
const isc::asiolink::IOAddress & getRelay6PeerAddress(uint8_t relay_level) const
return the peer address field from a relay option
std::string getIface() const
Returns interface name.
isc::log::Logger eval_logger("eval")
Eval Logger.
FieldType getField() const
Returns field.
std::vector< RelayInfo > relay_info_
Relay information.
TokenRelay4Option(const uint16_t option_code, const RepresentationType &rep_type)
Constructor for extracting sub-option from RAI (option 82)
virtual OptionPtr getOption(Pkt &pkt)
Attempts to obtain specified option from the specified relay block.
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND
const isc::log::MessageID EVAL_DEBUG_SUBSTRING
virtual OptionPtr getOption(Pkt &pkt)
Attempts to retrieve an option.
void evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
const isc::asiolink::IOAddress & getYiaddr() const
Returns yiaddr field.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
const isc::log::MessageID EVAL_DEBUG_INT8TOTEXT
const isc::log::MessageID EVAL_DEBUG_VENDOR_EXISTS
Option::Universe universe_
Universe (V4 or V6)
const isc::log::MessageID EVAL_DEBUG_STRING
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
enterprise-id field (vendor-info, vendor-class)
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
TokenInteger(const uint32_t value)
Integer value set during construction.
std::stack< std::string > ValueStack
Evaluated values are stored as a stack of strings.
uint8_t getType() const
Returns DHCP message type (e.g.
std::string value_
Constant value.
Evaluation context, an interface to the expression evaluation.
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
const isc::log::MessageID EVAL_DEBUG_PKT
const isc::log::MessageID EVAL_DEBUG_RELAY6
static bool toBool(std::string value)
Coverts a (string) value to a boolean.
virtual void evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
const isc::log::MessageID EVAL_DEBUG_MEMBER
void evaluate(Pkt &pkt, ValueStack &values)
Extract a substring from a string.
Token that represents a value of an option.
const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE
virtual OptionPtr getOption(Pkt &pkt)
Attempts to obtain specified sub-option of option 82 from the packet.
const isc::log::MessageID EVAL_DEBUG_EQUAL
virtual std::string pushFailure(ValueStack &values)
Auxiliary method that puts string representing a failure.
void evaluate(Pkt &pkt, ValueStack &values)
Logical and.
std::vector< uint8_t > Buffer
Defines a type of the data buffer used to hold the opaque data.
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack after decoding or an empty string if...
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
const isc::asiolink::IOAddress & getGiaddr() const
Returns giaddr field.
void evaluate(Pkt &pkt, ValueStack &values)
Concatenate two values.
void evaluate(Pkt &pkt, ValueStack &values)
Gets a value from the specified packet.
const isc::asiolink::IOAddress & getRemoteAddr() const
Returns remote IP address.
const isc::log::MessageID EVAL_DEBUG_IFELSE_FALSE
const isc::log::MessageID EVAL_DEBUG_CONCAT
const isc::log::MessageID EVAL_DEBUG_RELAY6_RANGE
TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field)
Constructor used for accessing a field.
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the constant string on the stack after decoding)
Represents DHCPv4 packet.
const isc::log::MessageID EVAL_DEBUG_INT32TOTEXT
const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING
void evaluate(Pkt &pkt, ValueStack &values)
Compare two values.
const isc::log::MessageID EVAL_DEBUG_UINT8TOTEXT
RepresentationType
Token representation type.
const isc::log::MessageID EVAL_DEBUG_UINT16TOTEXT
EvalBadStack is thrown when more or less parameters are on the stack than expected.
const isc::log::MessageID EVAL_DEBUG_OR
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
RepresentationType representation_type_
Representation type.
OptionPtr getOption(const uint16_t type)
Returns the first option of specified type.
void evaluate(Pkt &pkt, ValueStack &values)
Convert a binary value to its hexadecimal string representation.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Represents a single instance of the opaque data preceded by length.
void evaluate(Pkt &pkt, ValueStack &values)
Extract a field from a delimited string.
const isc::log::MessageID EVAL_DEBUG_NOT
const isc::log::MessageID EVAL_DEBUG_IFELSE_TRUE
const isc::log::MessageID EVAL_DEBUG_HEXSTRING
virtual uint8_t getType() const
Returns message type (e.g.
std::string toHex(std::string value)
Encode in hexadecimal inline.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
uint32_t getVendorId() const
Returns enterprise-id.
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
const isc::log::MessageID EVAL_DEBUG_VENDOR_ENTERPRISE_ID_MISMATCH
const isc::log::MessageID EVAL_DEBUG_UINT32TOTEXT
void evaluate(Pkt &pkt, ValueStack &values)
Token evaluation (puts value of the string on the stack after decoding)
EvalTypeError is thrown when a value on the stack has a content with an unexpected type...
uint16_t index_
Data chunk index.
void evaluate(Pkt &pkt, ValueStack &values)
Logical or.
TokenIpAddress(const std::string &addr)
Value is set during token construction.
virtual void evaluate(Pkt &pkt, ValueStack &values)
This is a method for evaluating a packet.
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID
The IOAddress class represents an IP addresses (version agnostic)
const isc::asiolink::IOAddress & getLocalAddr() const
Returns local IP address.
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
void evaluate(Pkt &pkt, ValueStack &values)
Evaluates the values of the option.
const isc::log::MessageID EVAL_DEBUG_AND
uint32_t getTransid() const
Returns value of transaction-id field.
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID_MISMATCH
This class represents vendor-specific information option.
TokenVendorClass(Option::Universe u, uint32_t vendor_id, RepresentationType repr)
This constructor is used to access fields.
This class encapsulates DHCPv6 Vendor Class and DHCPv4 V-I Vendor Class options.
Token that represents vendor options in DHCPv4 and DHCPv6.
const isc::log::MessageID EVAL_DEBUG_INT16TOTEXT
FieldType field_
Specifies which field should be accessed.
const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA