mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 06:55:16 +00:00
[master] Merged trac4091 (hex strings)
This commit is contained in:
@@ -593,7 +593,7 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
|
|||||||
// The decodeHex function expects that the string contains an
|
// The decodeHex function expects that the string contains an
|
||||||
// even number of digits. If we don't meet this requirement,
|
// even number of digits. If we don't meet this requirement,
|
||||||
// we have to insert a leading 0.
|
// we have to insert a leading 0.
|
||||||
if (!data_param.empty() && data_param.length() % 2) {
|
if (!data_param.empty() && ((data_param.length() % 2) != 0)) {
|
||||||
data_param = data_param.insert(0, "0");
|
data_param = data_param.insert(0, "0");
|
||||||
}
|
}
|
||||||
util::encode::decodeHex(data_param, binary);
|
util::encode::decodeHex(data_param, binary);
|
||||||
|
@@ -26,7 +26,7 @@ if HAVE_GTEST
|
|||||||
|
|
||||||
TESTS += libeval_unittests
|
TESTS += libeval_unittests
|
||||||
|
|
||||||
libeval_unittests_SOURCES = token_unittest.cc main.cc
|
libeval_unittests_SOURCES = token_unittest.cc run_unittests.cc
|
||||||
libeval_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
libeval_unittests_CXXFLAGS = $(AM_CXXFLAGS)
|
||||||
libeval_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
libeval_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
||||||
libeval_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
|
libeval_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
|
||||||
|
@@ -24,6 +24,8 @@
|
|||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace isc::dhcp;
|
using namespace isc::dhcp;
|
||||||
|
|
||||||
@@ -127,6 +129,116 @@ TEST_F(TokenTest, string6) {
|
|||||||
EXPECT_EQ("foo", values_.top());
|
EXPECT_EQ("foo", values_.top());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This simple test checks that a TokenHexString, representing a constant
|
||||||
|
// string coded in hexadecimal, can be used in Pkt4 evaluation.
|
||||||
|
// (The actual packet is not used)
|
||||||
|
TEST_F(TokenTest, hexstring4) {
|
||||||
|
TokenPtr empty;
|
||||||
|
TokenPtr bad;
|
||||||
|
TokenPtr nodigit;
|
||||||
|
TokenPtr baddigit;
|
||||||
|
TokenPtr bell;
|
||||||
|
TokenPtr foo;
|
||||||
|
TokenPtr cookie;
|
||||||
|
|
||||||
|
// Store constant empty hexstring "" ("") in the TokenHexString object.
|
||||||
|
ASSERT_NO_THROW(empty.reset(new TokenHexString("")));
|
||||||
|
// Store bad encoded hexstring "0abc" ("").
|
||||||
|
ASSERT_NO_THROW(bad.reset(new TokenHexString("0abc")));
|
||||||
|
// Store hexstring with no digits "0x" ("").
|
||||||
|
ASSERT_NO_THROW(nodigit.reset(new TokenHexString("0x")));
|
||||||
|
// Store hexstring with a bad hexdigit "0xxabc" ("").
|
||||||
|
ASSERT_NO_THROW(baddigit.reset(new TokenHexString("0xxabc")));
|
||||||
|
// Store hexstring with an odd number of hexdigits "0x7" ("\a").
|
||||||
|
ASSERT_NO_THROW(bell.reset(new TokenHexString("0x7")));
|
||||||
|
// Store constant hexstring "0x666f6f" ("foo").
|
||||||
|
ASSERT_NO_THROW(foo.reset(new TokenHexString("0x666f6f")));
|
||||||
|
// Store constant hexstring "0x63825363" (DHCP_OPTIONS_COOKIE).
|
||||||
|
ASSERT_NO_THROW(cookie.reset(new TokenHexString("0x63825363")));
|
||||||
|
|
||||||
|
// Make sure that tokens can be evaluated without exceptions.
|
||||||
|
ASSERT_NO_THROW(empty->evaluate(*pkt4_, values_));
|
||||||
|
ASSERT_NO_THROW(bad->evaluate(*pkt4_, values_));
|
||||||
|
ASSERT_NO_THROW(nodigit->evaluate(*pkt4_, values_));
|
||||||
|
ASSERT_NO_THROW(baddigit->evaluate(*pkt4_, values_));
|
||||||
|
ASSERT_NO_THROW(bell->evaluate(*pkt4_, values_));
|
||||||
|
ASSERT_NO_THROW(foo->evaluate(*pkt4_, values_));
|
||||||
|
ASSERT_NO_THROW(cookie->evaluate(*pkt4_, values_));
|
||||||
|
|
||||||
|
// Check that the evaluation put its value on the values stack.
|
||||||
|
ASSERT_EQ(7, values_.size());
|
||||||
|
uint32_t expected = htonl(DHCP_OPTIONS_COOKIE);
|
||||||
|
EXPECT_EQ(4, values_.top().size());
|
||||||
|
EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("foo", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("\a", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This simple test checks that a TokenHexString, representing a constant
|
||||||
|
// string coded in hexadecimal, can be used in Pkt6 evaluation.
|
||||||
|
// (The actual packet is not used)
|
||||||
|
TEST_F(TokenTest, hexstring6) {
|
||||||
|
TokenPtr empty;
|
||||||
|
TokenPtr bad;
|
||||||
|
TokenPtr nodigit;
|
||||||
|
TokenPtr baddigit;
|
||||||
|
TokenPtr bell;
|
||||||
|
TokenPtr foo;
|
||||||
|
TokenPtr cookie;
|
||||||
|
|
||||||
|
// Store constant empty hexstring "" ("") in the TokenHexString object.
|
||||||
|
ASSERT_NO_THROW(empty.reset(new TokenHexString("")));
|
||||||
|
// Store bad encoded hexstring "0abc" ("").
|
||||||
|
ASSERT_NO_THROW(bad.reset(new TokenHexString("0abc")));
|
||||||
|
// Store hexstring with no digits "0x" ("").
|
||||||
|
ASSERT_NO_THROW(nodigit.reset(new TokenHexString("0x")));
|
||||||
|
// Store hexstring with a bad hexdigit "0xxabc" ("").
|
||||||
|
ASSERT_NO_THROW(baddigit.reset(new TokenHexString("0xxabc")));
|
||||||
|
// Store hexstring with an odd number of hexdigits "0x7" ("\a").
|
||||||
|
ASSERT_NO_THROW(bell.reset(new TokenHexString("0x7")));
|
||||||
|
// Store constant hexstring "0x666f6f" ("foo").
|
||||||
|
ASSERT_NO_THROW(foo.reset(new TokenHexString("0x666f6f")));
|
||||||
|
// Store constant hexstring "0x63825363" (DHCP_OPTIONS_COOKIE).
|
||||||
|
ASSERT_NO_THROW(cookie.reset(new TokenHexString("0x63825363")));
|
||||||
|
|
||||||
|
// Make sure that tokens can be evaluated without exceptions.
|
||||||
|
ASSERT_NO_THROW(empty->evaluate(*pkt6_, values_));
|
||||||
|
ASSERT_NO_THROW(bad->evaluate(*pkt6_, values_));
|
||||||
|
ASSERT_NO_THROW(nodigit->evaluate(*pkt6_, values_));
|
||||||
|
ASSERT_NO_THROW(baddigit->evaluate(*pkt6_, values_));
|
||||||
|
ASSERT_NO_THROW(bell->evaluate(*pkt6_, values_));
|
||||||
|
ASSERT_NO_THROW(foo->evaluate(*pkt6_, values_));
|
||||||
|
ASSERT_NO_THROW(cookie->evaluate(*pkt6_, values_));
|
||||||
|
|
||||||
|
// Check that the evaluation put its value on the values stack.
|
||||||
|
ASSERT_EQ(7, values_.size());
|
||||||
|
uint32_t expected = htonl(DHCP_OPTIONS_COOKIE);
|
||||||
|
EXPECT_EQ(4, values_.top().size());
|
||||||
|
EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("foo", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("\a", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
values_.pop();
|
||||||
|
EXPECT_EQ("", values_.top());
|
||||||
|
}
|
||||||
|
|
||||||
// This test checks if a token representing an option value is able to extract
|
// This test checks if a token representing an option value is able to extract
|
||||||
// the option from an IPv4 packet and properly store the option's value.
|
// the option from an IPv4 packet and properly store the option's value.
|
||||||
TEST_F(TokenTest, optionString4) {
|
TEST_F(TokenTest, optionString4) {
|
||||||
|
@@ -14,7 +14,9 @@
|
|||||||
|
|
||||||
#include <eval/token.h>
|
#include <eval/token.h>
|
||||||
#include <eval/eval_log.h>
|
#include <eval/eval_log.h>
|
||||||
|
#include <util/encode/hex.h>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace isc::dhcp;
|
using namespace isc::dhcp;
|
||||||
@@ -26,6 +28,40 @@ TokenString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
|
|||||||
values.push(value_);
|
values.push(value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TokenHexString::TokenHexString(const string& str) : value_("") {
|
||||||
|
// Check string starts "0x" or "0x" and has at least one additional character.
|
||||||
|
if ((str.size() < 3) ||
|
||||||
|
(str[0] != '0') ||
|
||||||
|
((str[1] != 'x') && (str[1] != 'X'))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string digits = str.substr(2);
|
||||||
|
|
||||||
|
// Transform string of hexadecimal digits into binary format
|
||||||
|
vector<uint8_t> binary;
|
||||||
|
try {
|
||||||
|
// The decodeHex function expects that the string contains an
|
||||||
|
// even number of digits. If we don't meet this requirement,
|
||||||
|
// we have to insert a leading 0.
|
||||||
|
if ((digits.length() % 2) != 0) {
|
||||||
|
digits = digits.insert(0, "0");
|
||||||
|
}
|
||||||
|
util::encode::decodeHex(digits, binary);
|
||||||
|
} catch (...) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to a string (note that binary.size() cannot be 0)
|
||||||
|
value_.resize(binary.size());
|
||||||
|
memmove(&value_[0], &binary[0], binary.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TokenHexString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
|
||||||
|
// Literals only push, nothing to pop
|
||||||
|
values.push(value_);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenOption::evaluate(const Pkt& pkt, ValueStack& values) {
|
TokenOption::evaluate(const Pkt& pkt, ValueStack& values) {
|
||||||
OptionPtr opt = pkt.getOption(option_code_);
|
OptionPtr opt = pkt.getOption(option_code_);
|
||||||
|
@@ -101,6 +101,31 @@ protected:
|
|||||||
std::string value_; ///< Constant value
|
std::string value_; ///< Constant value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief Token representing a constant string in hexadecimal format
|
||||||
|
///
|
||||||
|
/// This token holds value of a constant string giving in an hexadecimal
|
||||||
|
/// format, for instance 0x666f6f is "foo"
|
||||||
|
class TokenHexString : public Token {
|
||||||
|
public:
|
||||||
|
/// Value is set during token construction.
|
||||||
|
///
|
||||||
|
/// @param str constant string to be represented
|
||||||
|
/// (must be "0x" or "0X" followed by a string of hexadecimal digits
|
||||||
|
/// or decoding will fail)
|
||||||
|
TokenHexString(const std::string& str);
|
||||||
|
|
||||||
|
/// @brief Token evaluation (puts value of the constant string on
|
||||||
|
/// the stack after decoding or an empty string if decoding fails
|
||||||
|
/// (note it should not if the parser is correct)
|
||||||
|
///
|
||||||
|
/// @param pkt (ignored)
|
||||||
|
/// @param values (represented string will be pushed here)
|
||||||
|
void evaluate(const Pkt& pkt, ValueStack& values);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string value_; ///< Constant value
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief Token that represents a value of an option
|
/// @brief Token that represents a value of an option
|
||||||
///
|
///
|
||||||
/// This represents a reference to a given option, e.g. in the expression
|
/// This represents a reference to a given option, e.g. in the expression
|
||||||
|
Reference in New Issue
Block a user