diff options
author | Francis Dupont <fdupont@isc.org> | 2019-06-14 20:40:17 +0200 |
---|---|---|
committer | Tomek Mrugalski <tomasz@isc.org> | 2019-08-14 10:13:02 +0200 |
commit | 1ef44a79d22f4277b6ef30e6bd03992922201c3f (patch) | |
tree | 8a200698066424f917de9188cb6385e454c4657f | |
parent | [#433,!473] ChangeLog updated. (diff) | |
download | kea-1ef44a79d22f4277b6ef30e6bd03992922201c3f.tar.xz kea-1ef44a79d22f4277b6ef30e6bd03992922201c3f.zip |
[150-add-sub-option-classification] Checkpoint: code done, todo regen and tests
-rw-r--r-- | src/lib/eval/eval_messages.cc | 6 | ||||
-rw-r--r-- | src/lib/eval/eval_messages.h | 4 | ||||
-rw-r--r-- | src/lib/eval/eval_messages.mes | 18 | ||||
-rw-r--r-- | src/lib/eval/parser.yy | 12 | ||||
-rw-r--r-- | src/lib/eval/token.cc | 61 | ||||
-rw-r--r-- | src/lib/eval/token.h | 62 |
6 files changed, 158 insertions, 5 deletions
diff --git a/src/lib/eval/eval_messages.cc b/src/lib/eval/eval_messages.cc index 3f7803b3f5..a10d1e90f2 100644 --- a/src/lib/eval/eval_messages.cc +++ b/src/lib/eval/eval_messages.cc @@ -1,4 +1,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 #include <cstddef> #include <log/message_types.h> @@ -27,6 +27,8 @@ extern const isc::log::MessageID EVAL_DEBUG_STRING = "EVAL_DEBUG_STRING"; 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"; @@ -66,6 +68,8 @@ const char* values[] = { "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'", diff --git a/src/lib/eval/eval_messages.h b/src/lib/eval/eval_messages.h index 99af4eabf3..bae6c37c8e 100644 --- a/src/lib/eval/eval_messages.h +++ b/src/lib/eval/eval_messages.h @@ -1,4 +1,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 @@ -28,6 +28,8 @@ extern const isc::log::MessageID EVAL_DEBUG_STRING; 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; diff --git a/src/lib/eval/eval_messages.mes b/src/lib/eval/eval_messages.mes index 0f37eaef64..6a9698ad67 100644 --- a/src/lib/eval/eval_messages.mes +++ b/src/lib/eval/eval_messages.mes @@ -1,4 +1,4 @@ -# 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 @@ -144,6 +144,22 @@ 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 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 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index f35fa23a77..4f8626c1f8 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -1,4 +1,4 @@ -/* 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 @@ -152,6 +152,11 @@ bool_expr : "(" bool_expr ")" 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()) { @@ -251,6 +256,11 @@ string_expr : STRING 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()) { diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc index 1147fdfa3b..f96dabe669 100644 --- a/src/lib/eval/token.cc +++ b/src/lib/eval/token.cc @@ -1,4 +1,4 @@ -// 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 @@ -985,3 +985,62 @@ TokenInteger::TokenInteger(const uint32_t value) :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 + '\''); + } +} diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index d3559fd21b..8275f98da1 100644 --- a/src/lib/eval/token.h +++ b/src/lib/eval/token.h @@ -1057,6 +1057,68 @@ protected: 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 |