summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2018-09-16 12:41:06 +0200
committerFrancis Dupont <fdupont@isc.org>2018-09-16 12:41:06 +0200
commit91d36d92c6455e1edec73d00904f1d8418863a1a (patch)
treeb02831bce06ab61eeb0ce952f3765e42bc1a9515 /src
parent[master] Removed parsers/dbaccess_parser.{h,cc} which were moved to database (diff)
downloadkea-91d36d92c6455e1edec73d00904f1d8418863a1a.tar.xz
kea-91d36d92c6455e1edec73d00904f1d8418863a1a.zip
[67-expressions-hexa-strings] checkpoint to update syntax
Diffstat (limited to 'src')
-rw-r--r--src/lib/eval/eval.dox4
-rw-r--r--src/lib/eval/eval_messages.mes9
-rw-r--r--src/lib/eval/lexer.ll3
-rw-r--r--src/lib/eval/parser.yy6
-rw-r--r--src/lib/eval/tests/context_unittest.cc6
-rw-r--r--src/lib/eval/token.cc40
-rw-r--r--src/lib/eval/token.h41
7 files changed, 105 insertions, 4 deletions
diff --git a/src/lib/eval/eval.dox b/src/lib/eval/eval.dox
index 4f7d814273..bb7e1ff178 100644
--- a/src/lib/eval/eval.dox
+++ b/src/lib/eval/eval.dox
@@ -160,7 +160,9 @@ instantiated with the appropriate value and put onto the expression vector.
- 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
diff --git a/src/lib/eval/eval_messages.mes b/src/lib/eval/eval_messages.mes
index c70b7aeb3f..1bf42ed9f6 100644
--- a/src/lib/eval/eval_messages.mes
+++ b/src/lib/eval/eval_messages.mes
@@ -144,6 +144,15 @@ string and an empty result will be pushed onto the stack. The start,
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
diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll
index d990b013eb..8d3f1b4fd3 100644
--- a/src/lib/eval/lexer.ll
+++ b/src/lib/eval/lexer.ll
@@ -1,4 +1,4 @@
-/* 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
@@ -201,6 +201,7 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
"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);
diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy
index f9f0261627..f35fa23a77 100644
--- a/src/lib/eval/parser.yy
+++ b/src/lib/eval/parser.yy
@@ -74,6 +74,7 @@ using namespace isc::eval;
COMA ","
CONCAT "concat"
IFELSE "ifelse"
+ TOHEXSTRING "hexstring"
PKT6 "pkt6"
MSGTYPE "msgtype"
TRANSID "transid"
@@ -349,6 +350,11 @@ string_expr : STRING
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
diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc
index ab487cc138..f40df5e0d0 100644
--- a/src/lib/eval/tests/context_unittest.cc
+++ b/src/lib/eval/tests/context_unittest.cc
@@ -1056,6 +1056,12 @@ TEST_F(EvalContextTest, pkt4FieldChaddr) {
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);
diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc
index 7225d4bb1f..e223aa0b6d 100644
--- a/src/lib/eval/token.cc
+++ b/src/lib/eval/token.cc
@@ -1,4 +1,4 @@
-// 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
@@ -21,6 +21,8 @@
#include <dhcp/option_vendor_class.h>
#include <cstring>
#include <string>
+#include <iomanip>
+#include <sstream>
using namespace isc::dhcp;
using namespace isc::util;
@@ -630,6 +632,42 @@ TokenIfElse::evaluate(Pkt& /*pkt*/, ValueStack& values) {
}
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) {
if (values.size() == 0) {
diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h
index 330bc60dfb..bba3ab9917 100644
--- a/src/lib/eval/token.h
+++ b/src/lib/eval/token.h
@@ -1,4 +1,4 @@
-// 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
@@ -725,6 +725,45 @@ public:
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')"