<row><entry>Concat</entry><entry>concat('foo','bar')</entry><entry>Return the
concatenation of the strings</entry></row>
<row><entry>Ifelse</entry><entry>ifelse('foo' == 'bar','us','them')</entry><entry>Return the branch value according to the condition</entry></row>
+<row><entry>Hexstring</entry><entry>hexstring('foo', '-')</entry><entry>Return the binary value as an hexadecimal string</entry></row>
</tbody>
</tgroup>
</table>
ifelse(option[230].exists, option[230].hex, 'none')
</screen>
</section>
+ <section>
+ <title>Hexstring</title>
+ The hexstring function "hexstring(binary, separator)" returns
+ the binary value as its hexadecimal string representation:
+ pairs of hexadecimal digits separated by '-' or ':' or not
+ separated (separator '').
+ <screen>
+ hexstring(pkt4.mac, ':')
+ </screen>
+ </section>
</section>
<note>
- isc::dhcp::TokenSubstring -- represents the substring(text, start, length) operator.
- isc::dhcp::TokenConcat -- represents the concat operator which
concatenate two other tokens.
- - isc::dhcp::TokenIfElse == represents the ifelse(cond, iftrue, ifelse) operator.
+ - isc::dhcp::TokenIfElse -- represents the ifelse(cond, iftrue, ifelse) operator.
+ - isc::dhcp::TokenToHexString -- represents the hexstring operator which
+ converts a binary value to its hexadecimal string representation.
- isc::dhcp::TokenNot -- the logical not operator.
- isc::dhcp::TokenAnd -- the logical and (strict) operator.
- isc::dhcp::TokenOr -- the logical or (strict) operator (strict means
length and string are still popped from the stack and the result is
still pushed. The strings are displayed in hex.
+# For use with TokenToHexString
+
+% EVAL_DEBUG_TOHEXSTRING Popping binary value %1 and separator %2, pushing result %3
+This debug message indicates that two values are being popped from
+the value stack and a result is being pushed onto the value stack.
+The values being popped are the binary value to convert and the separator.
+The binary value is converted to its hexadecimal string representation
+and pushed onto the stack. The binary value is displayed in hex.
+
% EVAL_DEBUG_VENDOR_CLASS_DATA Data %1 (out of %2 received) in vendor class found, pushing result '%3'
This debug message indicates that vendor class option was found and passed
enterprise-id checks and has sufficient number of data chunks. The total number
-/* Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
"all" return isc::eval::EvalParser::make_ALL(loc);
"concat" return isc::eval::EvalParser::make_CONCAT(loc);
"ifelse" return isc::eval::EvalParser::make_IFELSE(loc);
+"hexstring" return isc::eval::EvalParser::make_TOHEXSTRING(loc);
"not" return isc::eval::EvalParser::make_NOT(loc);
"and" return isc::eval::EvalParser::make_AND(loc);
"or" return isc::eval::EvalParser::make_OR(loc);
COMA ","
CONCAT "concat"
IFELSE "ifelse"
+ TOHEXSTRING "hexstring"
PKT6 "pkt6"
MSGTYPE "msgtype"
TRANSID "transid"
TokenPtr cond(new TokenIfElse());
ctx.expression.push_back(cond);
}
+ | TOHEXSTRING "(" string_expr "," string_expr ")"
+ {
+ TokenPtr tohex(new TokenToHexString());
+ ctx.expression.push_back(tohex);
+ }
| VENDOR "." ENTERPRISE
{
// expression: vendor.enterprise
testPkt4Field("pkt4.mac == 0x000102030405", TokenPkt4::CHADDR, 3);
}
+// Tests whether chaddr field in DHCPv4 can be accessed and converted.
+TEST_F(EvalContextTest, pkt4FieldChaddrHexa) {
+ testPkt4Field("hexstring(pkt4.mac, ':') == '00:01:02:03:04:05'",
+ TokenPkt4::CHADDR, 5);
+}
+
// Tests whether hlen field in DHCPv4 can be accessed.
TEST_F(EvalContextTest, pkt4FieldHlen) {
testPkt4Field("pkt4.hlen == 0x6", TokenPkt4::HLEN, 3);
-// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <dhcp/option_vendor_class.h>
#include <cstring>
#include <string>
+#include <iomanip>
+#include <sstream>
using namespace isc::dhcp;
using namespace isc::util;
}
}
+void
+TokenToHexString::evaluate(Pkt& /*pkt*/, ValueStack& values) {
+ if (values.size() < 2) {
+ isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
+ "2 values for hexstring, got " << values.size());
+ }
+
+ string separator = values.top();
+ values.pop();
+ string binary = values.top();
+ values.pop();
+
+ // Unknown separator is interpreted as none.
+ if ((separator != ":") && (separator != "-") && !separator.empty()) {
+ separator.clear();
+ }
+
+ bool first = true;
+ stringstream tmp;
+ tmp << hex;
+ for (size_t i = 0; i < binary.size(); ++i) {
+ if (!first) {
+ tmp << separator;
+ first = false;
+ }
+ tmp << setw(2) << setfill('0') << static_cast<unsigned>(binary[i]);
+ }
+ values.push(tmp.str());
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_TOHEXSTRING)
+ .arg(toHex(binary))
+ .arg(separator)
+ .arg(tmp.str());
+}
+
void
TokenNot::evaluate(Pkt& /*pkt*/, ValueStack& values) {
-// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
void evaluate(Pkt& pkt, ValueStack& values);
};
+/// @brief Token that converts to hexadecimal string
+///
+/// For example in the sub-expression "hexstring(pkt4.mac, ':')"
+/// the binary MAC address is converted to its usual hexadecimal
+/// representation as a list of (6) pairs of hexadecimal digits
+/// separated by colons (':').
+/// Please note the token is named TokenToHexString when the syntax
+/// use the hexstring name without a leading "to".
+class TokenToHexString : public Token {
+public:
+ /// @brief Constructor (does nothing)
+ TokenToHexString() { }
+
+ /// @brief Convert a binary value to its hexadecimal string representation
+ ///
+ /// Evaluation does not use packet information. It requires at least
+ /// two values to be present on the stack. It will consume the top
+ /// two values on the stack as parameters and push the resulting
+ /// hexadecimal string onto the stack.
+ /// From the top it expects the values on the stack as:
+ /// - separator ('-', ':' or something else interpreted as '')
+ /// - binary
+ ///
+ /// binary is the binary value (note it can be any value, i.e.
+ /// it is not checked to really be not printable).
+ /// separator is litteral '-' or ':' or something else interpreted as ''
+ /// i.e. no separator.
+ ///
+ /// The following example use a binary MAC address 06:ce:8f:55:b3:33:
+ /// - <mac>, '-' => "06-ce-8f-55-b3-33"
+ ///
+ /// @throw EvalBadStack if there are less than 2 values on stack
+ ///
+ /// @param pkt (unused)
+ /// @param values - stack of values (2 arguments will be popped, 1 result
+ /// will be pushed)
+ void evaluate(Pkt& pkt, ValueStack& values);
+};
+
/// @brief Token that represents logical negation operator
///
/// For example in the expression "not(option[vendor-class].text == 'MSF')"