-// File created from ../../../src/lib/eval/eval_messages.mes on Fri Feb 08 2019 20:17
+// File created from ../../../src/lib/eval/eval_messages.mes on Fri Jun 14 2019 20:35
#include <cstddef>
#include <log/message_types.h>
extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING = "EVAL_DEBUG_SUBSTRING";
extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING_EMPTY = "EVAL_DEBUG_SUBSTRING_EMPTY";
extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE = "EVAL_DEBUG_SUBSTRING_RANGE";
+extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION = "EVAL_DEBUG_SUB_OPTION";
+extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION_NO_OPTION = "EVAL_DEBUG_SUB_OPTION_NO_OPTION";
extern const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING = "EVAL_DEBUG_TOHEXSTRING";
extern const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA = "EVAL_DEBUG_VENDOR_CLASS_DATA";
extern const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND = "EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND";
"EVAL_DEBUG_SUBSTRING", "Popping length %1, start %2, string %3 pushing result %4",
"EVAL_DEBUG_SUBSTRING_EMPTY", "Popping length %1, start %2, string %3 pushing result %4",
"EVAL_DEBUG_SUBSTRING_RANGE", "Popping length %1, start %2, string %3 pushing result %4",
+ "EVAL_DEBUG_SUB_OPTION", "Pushing option %1 sub-option %2 with value %3",
+ "EVAL_DEBUG_SUB_OPTION_NO_OPTION", "Requested option %1 sub-option %2, but the parent option is not present, pushing result %3",
"EVAL_DEBUG_TOHEXSTRING", "Popping binary value %1 and separator %2, pushing result %3",
"EVAL_DEBUG_VENDOR_CLASS_DATA", "Data %1 (out of %2 received) in vendor class found, pushing result '%3'",
"EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND", "Requested data index %1, but option with enterprise-id %2 has only %3 data tuple(s), pushing result '%4'",
-// File created from ../../../src/lib/eval/eval_messages.mes on Fri Feb 08 2019 20:17
+// File created from ../../../src/lib/eval/eval_messages.mes on Fri Jun 14 2019 20:35
#ifndef EVAL_MESSAGES_H
#define EVAL_MESSAGES_H
extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING;
extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING_EMPTY;
extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE;
+extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION;
+extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION_NO_OPTION;
extern const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING;
extern const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA;
extern const isc::log::MessageID EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND;
-# Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2015-2019 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
length and string are still popped from the stack and the result is
still pushed. The strings are displayed in hex.
+# For use with TokenSubOption
+
+% EVAL_DEBUG_SUB_OPTION Pushing option %1 sub-option %2 with value %3
+This debug message indicates that the given string representing the
+value of the requested sub-option of the requested parent option is
+being pushed onto the value stack. The string may be the text or
+binary value of the string based on the representation type requested
+(.text or .hex) or "true" or "false" if the requested type is .exists.
+The codes are the parent option and the sub-option codes as requested
+in the classification statement.
+
+% EVAL_DEBUG_SUB_OPTION_NO_OPTION Requested option %1 sub-option %2, but the parent option is not present, pushing result %3
+This debug message indicates that the parent option was not found.
+The codes are the parent option and the sub-option codes as requested
+in the classification statement.
+
# For use with TokenToHexString
% EVAL_DEBUG_TOHEXSTRING Popping binary value %1 and separator %2, pushing result %3
-/* Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2015-2019 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
TokenPtr opt(new TokenOption($3, TokenOption::EXISTS));
ctx.expression.push_back(opt);
}
+ | OPTION "[" option_code "]" "." OPTION "[" option_code "]" "." EXISTS
+ {
+ TokenPtr opt(new TokenSubOption($3, $8, TokenOption::EXISTS));
+ ctx.expression.push_back(opt);
+ }
| RELAY4 "[" option_code "]" "." EXISTS
{
switch (ctx.getUniverse()) {
TokenPtr opt(new TokenOption($3, $6));
ctx.expression.push_back(opt);
}
+ | OPTION "[" option_code "]" "." OPTION "[" option_code "]" "." option_repr_type
+ {
+ TokenPtr opt(new TokenSubOption($3, $8, $11));
+ ctx.expression.push_back(opt);
+ }
| RELAY4 "[" option_code "]" "." option_repr_type
{
switch (ctx.getUniverse()) {
-// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2019 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
:TokenString(EvalContext::fromUint32(value)), int_value_(value) {
}
+
+OptionPtr
+TokenSubOption::getSubOption(const OptionPtr& parent) {
+ return (parent->getOption(sub_option_code_));
+}
+
+void
+TokenSubOption::evaluate(Pkt& pkt, ValueStack& values) {
+ OptionPtr parent = getOption(pkt);
+ std::string txt;
+ if (!parent) {
+ // There's no parent option, give up.
+ txt = pushFailure(values);
+ LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_SUB_OPTION_NO_OPTION)
+ .arg(option_code_)
+ .arg(sub_option_code_)
+ .arg(txt);
+ return;
+ }
+
+ OptionPtr sub = getSubOption(parent);
+ if (!sub) {
+ // Failed to find the sub-option
+ txt = pushFailure(values);
+ LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_SUB_OPTION)
+ .arg(option_code_)
+ .arg(sub_option_code_)
+ .arg(txt);
+ return;
+ }
+
+ if (representation_type_ == TEXTUAL) {
+ txt = sub->toString();
+ } else if (representation_type_ == HEXADECIMAL) {
+ std::vector<uint8_t> binary = sub->toBinary();
+ txt.resize(binary.size());
+ if (!binary.empty()) {
+ memmove(&txt[0], &binary[0], binary.size());
+ }
+ } else {
+ txt = "true";
+ }
+ values.push(txt);
+
+ // Log what we pushed, both exists and textual are simple text
+ // and can be output directly. We also include the code numbers
+ // of the requested parent option and sub-option.
+ if (representation_type_ == HEXADECIMAL) {
+ LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_SUB_OPTION)
+ .arg(option_code_)
+ .arg(sub_option_code_)
+ .arg(toHex(txt));
+ } else {
+ LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_SUB_OPTION)
+ .arg(option_code_)
+ .arg(sub_option_code_)
+ .arg('\'' + txt + '\'');
+ }
+}
uint16_t index_;
};
+/// @brief Token that represents sub-options in DHCPv4 and DHCPv6.
+///
+/// It covers any options which encapsulate sub-options, for instance
+/// dhcp-agent-options (72, DHCPv4) or rsoo (66, DHCPv6).
+/// This class is derived from TokenOption and leverages its ability
+/// to operate on sub-options. It also adds additional capabilities.
+///
+/// It can represent the following expressions:
+/// option[149].exists - check if option 149 exists
+/// option[149].option[1].exists - check if suboption 1 exists in the option 149
+/// option[149].option[1].hex - return content of suboption 1 for option 149
+class TokenSubOption : public TokenOption {
+public:
+
+ /// @note Does not define its own representation type:
+ /// simply use the @c TokenOption::RepresentationType
+
+ /// @brief Constructor that takes an option and sub-option codes as parameter
+ ///
+ /// Note: There is no constructor that takes names.
+ ///
+ /// @param option_code code of the parent option.
+ /// @param sub_option_code code of the sub-option to be represented.
+ /// @param rep_type Token representation type.
+ TokenSubOption(const uint16_t option_code,
+ const uint16_t sub_option_code,
+ const RepresentationType& rep_type)
+ : TokenOption(option_code, rep_type), sub_option_code_(sub_option_code) {}
+
+ /// @brief This is a method for evaluating a packet.
+ ///
+ /// This token represents a value of the sub-option, so this method
+ /// attempts to extract the parent option from the packet and when
+ /// it succeeds to extract the sub-option from the option and
+ /// its value on the stack.
+ /// If the parent option or the sub-option is not there, an empty
+ /// string ("") is put on the stack.
+ ///
+ /// @param pkt specified parent option will be extracted from this packet
+ /// @param values value of the sub-option will be pushed here (or "")
+ virtual void evaluate(Pkt& pkt, ValueStack& values);
+
+ /// @brief Returns sub-option-code
+ ///
+ /// This method is used in testing to determine if the parser had
+ /// instantiated TokenSubOption with correct parameters.
+ ///
+ /// @return option-code of the sub-option this token expects to extract.
+ uint16_t getSubCode() const {
+ return (sub_option_code_);
+ }
+
+protected:
+ /// @brief Attempts to retrieve a sub-option.
+ ///
+ /// @param parent the sub-option will be retrieved from here
+ /// @return sub-option instance (or NULL if not found)
+ virtual OptionPtr getSubOption(const OptionPtr& parent);
+
+ uint16_t sub_option_code_; ///< Code of the sub-option to be extracted
+};
+
}; // end of isc::dhcp namespace
}; // end of isc namespace