From ce3d4e3c25dc13aeae6ad648a60dab70150a4e08 Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Thu, 31 Mar 2016 18:48:08 +0000 Subject: [PATCH] [trac4265] First round of allowing access to v6 relay options via the classification code --- src/lib/dhcp/pkt6.cc | 12 +- src/lib/dhcp/pkt6.h | 2 +- src/lib/eval/eval_context.cc | 26 ++- src/lib/eval/eval_context.h | 14 +- src/lib/eval/lexer.cc | 322 ++++++++++++++------------ src/lib/eval/lexer.ll | 3 + src/lib/eval/parser.cc | 424 +++++++++++++++++++++++------------ src/lib/eval/parser.h | 197 +++++++++++----- src/lib/eval/parser.yy | 64 ++++++ src/lib/eval/token.cc | 31 +++ src/lib/eval/token.h | 102 +++++++++ 11 files changed, 838 insertions(+), 359 deletions(-) diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc index 3eab9e536e..432dd95e9a 100644 --- a/src/lib/dhcp/pkt6.cc +++ b/src/lib/dhcp/pkt6.cc @@ -112,18 +112,16 @@ OptionPtr Pkt6::getAnyRelayOption(uint16_t opt_type, RelaySearchOrder order) { return (OptionPtr()); } -OptionPtr Pkt6::getRelayOption(uint16_t opt_type, uint8_t relay_level) { +OptionPtr Pkt6::getRelayOption(uint16_t opt_type, uint8_t relay_level) const { if (relay_level >= relay_info_.size()) { isc_throw(OutOfRange, "This message was relayed " << relay_info_.size() << " time(s)." << " There is no info about " << relay_level + 1 << " relay."); } - for (OptionCollection::iterator it = relay_info_[relay_level].options_.begin(); - it != relay_info_[relay_level].options_.end(); ++it) { - if ((*it).second->getType() == opt_type) { - return (it->second); - } - } + OptionCollection::const_iterator x = relay_info_[relay_level].options_.find(opt_type); + if (x != options_.end()) { + return (*x).second; + } return (OptionPtr()); } diff --git a/src/lib/dhcp/pkt6.h b/src/lib/dhcp/pkt6.h index 65ee16fbe6..83704c9c16 100644 --- a/src/lib/dhcp/pkt6.h +++ b/src/lib/dhcp/pkt6.h @@ -239,7 +239,7 @@ public: /// @param nesting_level see description above /// /// @return pointer to the option (or NULL if there is no such option) - OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level); + OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level) const; /// @brief Return first instance of a specified option /// diff --git a/src/lib/eval/eval_context.cc b/src/lib/eval/eval_context.cc index 6d098a45a6..9ef2faec89 100644 --- a/src/lib/eval/eval_context.cc +++ b/src/lib/eval/eval_context.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2016 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 @@ -92,6 +92,30 @@ EvalContext::convertOptionName(const std::string& option_name, return (option_def->getCode()); } +uint8_t +EvalContext::convertNestLevelNumber(const std::string& nest_level, + const isc::eval::location& loc) +{ + int n = 0; + try { + n = boost::lexical_cast(nest_level); + } catch (const boost::bad_lexical_cast &) { + // This can't happen... + error(loc, "Nest level has invalid value in " + nest_level); + } + if (option_universe_ == Option::V6) { + if (n < 0 || n > 31) { + error(loc, "Nest level has invalid value in " + + nest_level + ". Allowed range: 0..31"); + } + } else { + error(loc, "Nest level invalid for DHCPv4 packets"); + } + + return (static_cast(n)); +} + + void EvalContext::fatal (const std::string& what) { diff --git a/src/lib/eval/eval_context.h b/src/lib/eval/eval_context.h index c5c0c20914..939f9ec35e 100644 --- a/src/lib/eval/eval_context.h +++ b/src/lib/eval/eval_context.h @@ -82,12 +82,12 @@ public: /// This is for should not happen but fatal errors static void fatal(const std::string& what); - /// @brief Option code convertion + /// @brief Option code conversion /// /// @param option_code a string representing the integer code /// @param loc the location of the token /// @result the option code - /// @throw calls the syntax error function if the value is no in + /// @throw calls the syntax error function if the value is not in /// the range 0..255 or 0..65535 uint16_t convertOptionCode(const std::string& option_code, const isc::eval::location& loc); @@ -101,6 +101,16 @@ public: uint16_t convertOptionName(const std::string& option_name, const isc::eval::location& loc); + /// @brief Nest level conversion + /// + /// @param nest_level a string representing the integer nesting level + /// @param loc the location of the token + /// @result the nesting level + /// @throw calls the syntax error function if the value is not in + /// the range 0..31 + uint8_t convertNestLevelNumber(const std::string& nest_level, + const isc::eval::location& loc); + /// @brief Returns the universe (v4 or v6) /// /// @return universe diff --git a/src/lib/eval/lexer.cc b/src/lib/eval/lexer.cc index 7cc13ac9a3..25ba5f1f2c 100644 --- a/src/lib/eval/lexer.cc +++ b/src/lib/eval/lexer.cc @@ -483,8 +483,8 @@ static void yy_fatal_error (yyconst char msg[] ); (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 27 -#define YY_END_OF_BUFFER 28 +#define YY_NUM_RULES 30 +#define YY_END_OF_BUFFER 31 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -492,38 +492,43 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_acclist[138] = +static yyconst flex_int16_t yy_acclist[162] = { 0, - 28, 26, 27, 1, 26, 27, 2, 27, 26, 27, - 21, 26, 27, 22, 26, 27, 25, 26, 27, 26, - 27, 20, 26, 27, 5, 26, 27, 5, 26, 27, - 26, 27, 26, 27, 26, 27,16390, 26, 27,16390, - 23, 26, 27, 24, 26, 27, 26, 27,16390, 26, - 27,16390, 26, 27,16390, 26, 27,16390, 26, 27, - 16390, 26, 27,16390, 26, 27,16390, 26, 27,16390, - 26, 27,16390, 1, 2, 3, 5, 5, 7, 8, - 16390,16390, 8198,16390,16390,16390,16390,16390,16390,16390, - 19,16390,16390,16390,16390, 4, 7, 15,16390, 18, - - 16390,16390,16390, 12,16390, 17,16390,16390,16390,16390, - 16390,16390,16390,16390,16390,16390, 11,16390,16390,16390, - 16390,16390,16390, 16,16390, 13,16390, 9,16390, 10, - 16390,16390, 7,16390,16390, 14,16390 + 31, 29, 30, 1, 29, 30, 2, 30, 29, 30, + 24, 29, 30, 25, 29, 30, 28, 29, 30, 29, + 30, 23, 29, 30, 5, 29, 30, 5, 29, 30, + 29, 30, 29, 30, 29, 30,16390, 29, 30,16390, + 26, 29, 30, 27, 29, 30, 29, 30,16390, 29, + 30,16390, 29, 30,16390, 29, 30,16390, 29, 30, + 16390, 29, 30,16390, 29, 30,16390, 29, 30,16390, + 29, 30,16390, 29, 30,16390, 29, 30,16390, 1, + 2, 3, 5, 5, 7, 8,16390,16390, 8198,16390, + 16390,16390,16390,16390,16390,16390,16390, 22,16390,16390, + + 16390,16390,16390, 4, 7, 18,16390, 21,16390,16390, + 16390, 15,16390,16390, 20,16390,16390,16390,16390,16390, + 16390,16390,16390,16390,16390,16390,16390,16390, 14,16390, + 16390,16390,16390,16390,16390,16390,16390, 19,16390, 16, + 16390,16390, 9,16390,16390, 10,16390, 11,16390,16390, + 7,16390,16390,16390, 13,16390, 12,16390,16390, 17, + 16390 } ; -static yyconst flex_int16_t yy_accept[97] = +static yyconst flex_int16_t yy_accept[114] = { 0, 1, 1, 1, 2, 4, 7, 9, 11, 14, 17, 20, 22, 25, 28, 31, 33, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, - 75, 76, 76, 77, 78, 78, 79, 79, 79, 79, - 79, 80, 81, 81, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 93, 94, 95, 96, 96, - 97, 98, 100, 102, 103, 104, 106, 108, 109, 110, - 111, 112, 112, 113, 114, 115, 116, 117, 119, 119, - 120, 121, 122, 123, 124, 124, 126, 128, 130, 132, - 133, 134, 135, 136, 138, 138 - + 77, 80, 81, 82, 82, 83, 84, 84, 85, 85, + 85, 85, 85, 86, 87, 87, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 100, 101, + 102, 103, 104, 104, 105, 106, 108, 110, 111, 112, + 114, 115, 117, 118, 119, 120, 121, 122, 122, 123, + 124, 125, 126, 127, 128, 129, 131, 131, 132, 133, + 134, 135, 136, 137, 138, 138, 140, 142, 143, 145, + + 146, 148, 150, 151, 152, 153, 154, 155, 157, 159, + 160, 162, 162 } ; static yyconst YY_CHAR yy_ec[256] = @@ -533,15 +538,15 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4, 5, 6, 1, 1, 7, 8, 9, 1, 10, 11, 11, - 11, 12, 11, 11, 11, 11, 11, 13, 1, 1, - 14, 1, 1, 1, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 17, 16, 16, - 18, 1, 19, 1, 20, 1, 21, 22, 23, 24, - - 25, 15, 26, 27, 28, 16, 16, 29, 16, 30, - 31, 32, 16, 33, 34, 35, 36, 16, 16, 37, - 38, 16, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 12, 11, 13, 11, 11, 11, 14, 1, 1, + 15, 1, 1, 1, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 18, 17, 17, + 19, 1, 20, 1, 21, 1, 22, 23, 24, 25, + + 26, 16, 27, 28, 29, 17, 30, 31, 17, 32, + 33, 34, 17, 35, 36, 37, 38, 17, 17, 39, + 40, 17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -558,116 +563,128 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst YY_CHAR yy_meta[39] = +static yyconst YY_CHAR yy_meta[41] = { 0, 1, 1, 2, 1, 1, 1, 1, 1, 3, 4, - 4, 4, 5, 1, 4, 1, 1, 1, 1, 1, - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 + 4, 4, 4, 5, 1, 4, 1, 1, 1, 1, + 1, 4, 4, 4, 4, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; -static yyconst flex_uint16_t yy_base[101] = +static yyconst flex_uint16_t yy_base[118] = { 0, - 0, 0, 191, 192, 188, 186, 184, 192, 192, 192, - 29, 192, 33, 30, 174, 172, 69, 98, 192, 192, - 22, 154, 147, 158, 151, 27, 156, 144, 154, 176, - 174, 172, 192, 51, 54, 32, 162, 161, 0, 160, - 0, 192, 112, 114, 0, 0, 192, 143, 147, 140, - 141, 131, 132, 131, 0, 136, 142, 126, 64, 0, - 0, 0, 0, 139, 127, 0, 0, 132, 138, 124, - 122, 114, 135, 120, 123, 115, 117, 0, 118, 106, - 98, 88, 100, 54, 124, 0, 0, 0, 0, 55, - 127, 48, 42, 0, 192, 139, 141, 143, 49, 146 - + 0, 0, 220, 221, 217, 215, 213, 221, 221, 221, + 31, 221, 36, 33, 202, 200, 74, 105, 221, 221, + 24, 181, 174, 186, 182, 177, 29, 183, 182, 169, + 180, 203, 201, 199, 221, 55, 68, 35, 188, 187, + 0, 186, 0, 221, 120, 122, 0, 0, 221, 168, + 173, 165, 167, 156, 162, 156, 155, 0, 165, 159, + 166, 149, 123, 0, 0, 0, 0, 163, 150, 0, + 155, 0, 155, 148, 160, 145, 143, 133, 157, 141, + 155, 143, 153, 134, 136, 0, 138, 135, 125, 116, + 107, 113, 57, 102, 142, 0, 0, 101, 0, 95, + + 0, 0, 64, 146, 54, 48, 41, 0, 0, 44, + 0, 221, 159, 161, 163, 53, 166 } ; -static yyconst flex_int16_t yy_def[101] = +static yyconst flex_int16_t yy_def[118] = { 0, - 95, 1, 95, 95, 95, 95, 96, 95, 95, 95, - 95, 95, 95, 13, 97, 95, 95, 17, 95, 95, - 17, 17, 17, 18, 18, 18, 18, 18, 18, 95, - 95, 96, 95, 95, 95, 13, 97, 98, 99, 97, - 100, 95, 95, 18, 17, 18, 95, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 95, 99, - 100, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 95, 18, 18, 18, 18, 18, 18, 95, 18, - 18, 18, 18, 18, 95, 18, 18, 18, 18, 18, - 95, 18, 18, 18, 0, 95, 95, 95, 95, 95 - + 112, 1, 112, 112, 112, 112, 113, 112, 112, 112, + 112, 112, 112, 13, 114, 112, 112, 17, 112, 112, + 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, + 18, 112, 112, 113, 112, 112, 112, 13, 114, 115, + 116, 114, 117, 112, 112, 18, 17, 18, 112, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 112, 116, 117, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 112, 18, 18, + 18, 18, 18, 18, 18, 18, 112, 18, 18, 18, + 18, 18, 18, 18, 112, 18, 18, 18, 18, 18, + + 18, 18, 18, 112, 18, 18, 18, 18, 18, 18, + 18, 0, 112, 112, 112, 112, 112 } ; -static yyconst flex_uint16_t yy_nxt[231] = +static yyconst flex_uint16_t yy_nxt[262] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 14, 15, 16, 17, 18, 18, 19, 20, 4, - 21, 17, 22, 17, 23, 18, 24, 18, 18, 25, - 26, 18, 27, 28, 29, 18, 18, 18, 34, 34, - 34, 35, 36, 36, 36, 37, 95, 38, 95, 39, - 48, 49, 60, 38, 38, 38, 38, 38, 54, 55, - 34, 34, 34, 59, 59, 59, 95, 94, 95, 39, - 43, 43, 72, 59, 59, 59, 44, 93, 45, 45, - 45, 37, 92, 45, 46, 46, 90, 47, 44, 45, - 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, - - 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, - 95, 89, 46, 43, 43, 95, 95, 88, 46, 46, - 46, 46, 46, 79, 79, 79, 85, 79, 79, 79, - 47, 87, 95, 91, 91, 91, 91, 91, 91, 32, - 86, 32, 32, 32, 40, 40, 38, 38, 61, 61, - 61, 84, 83, 82, 81, 80, 78, 77, 76, 75, - 74, 73, 71, 70, 69, 68, 67, 66, 65, 64, - 63, 62, 41, 37, 41, 33, 31, 30, 58, 57, - 56, 53, 52, 51, 50, 42, 41, 33, 31, 30, - 95, 3, 95, 95, 95, 95, 95, 95, 95, 95, - - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95 + 14, 14, 14, 15, 16, 17, 18, 18, 19, 20, + 4, 21, 17, 22, 17, 23, 18, 24, 18, 18, + 25, 26, 27, 28, 29, 30, 31, 18, 18, 18, + 36, 36, 36, 36, 37, 38, 38, 38, 38, 39, + 112, 40, 112, 41, 50, 51, 64, 40, 40, 40, + 40, 40, 57, 58, 36, 36, 36, 36, 101, 102, + 111, 112, 110, 112, 41, 45, 45, 63, 63, 63, + 63, 46, 109, 47, 47, 47, 47, 39, 108, 47, + 48, 48, 107, 49, 46, 47, 47, 47, 47, 47, + + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 112, 106, + 48, 45, 45, 112, 112, 105, 48, 48, 48, 48, + 48, 78, 63, 63, 63, 63, 103, 100, 99, 49, + 98, 112, 87, 87, 87, 87, 95, 87, 87, 87, + 87, 104, 104, 104, 104, 104, 104, 104, 104, 34, + 97, 34, 34, 34, 42, 42, 40, 40, 65, 65, + 65, 96, 94, 93, 92, 91, 90, 89, 88, 86, + 85, 84, 83, 82, 81, 80, 79, 77, 76, 75, + 74, 73, 72, 71, 70, 69, 68, 67, 66, 43, + + 39, 43, 35, 33, 32, 62, 61, 60, 59, 56, + 55, 54, 53, 52, 44, 43, 35, 33, 32, 112, + 3, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112 } ; -static yyconst flex_int16_t yy_chk[231] = +static yyconst flex_int16_t yy_chk[262] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 11, 11, - 11, 13, 13, 13, 13, 13, 14, 13, 36, 13, - 21, 21, 99, 13, 13, 13, 13, 13, 26, 26, - 34, 34, 34, 35, 35, 35, 14, 93, 36, 13, - 17, 17, 59, 59, 59, 59, 17, 92, 17, 17, - 17, 17, 90, 17, 17, 17, 84, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, + 14, 13, 38, 13, 21, 21, 116, 13, 13, 13, + 13, 13, 27, 27, 36, 36, 36, 36, 93, 93, + 110, 14, 107, 38, 13, 17, 17, 37, 37, 37, + 37, 17, 106, 17, 17, 17, 17, 17, 105, 17, + 17, 17, 103, 17, 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, - 18, 83, 18, 43, 43, 44, 44, 82, 18, 18, - 18, 18, 18, 72, 72, 72, 79, 79, 79, 79, - 43, 81, 44, 85, 85, 85, 91, 91, 91, 96, - 80, 96, 96, 96, 97, 97, 98, 98, 100, 100, - 100, 77, 76, 75, 74, 73, 71, 70, 69, 68, - 65, 64, 58, 57, 56, 54, 53, 52, 51, 50, - 49, 48, 40, 38, 37, 32, 31, 30, 29, 28, - 27, 25, 24, 23, 22, 16, 15, 7, 6, 5, - 3, 95, 95, 95, 95, 95, 95, 95, 95, 95, - - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95 + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 18, 18, 18, 18, 18, 100, + 18, 45, 45, 46, 46, 98, 18, 18, 18, 18, + 18, 63, 63, 63, 63, 63, 94, 92, 91, 45, + 90, 46, 78, 78, 78, 78, 87, 87, 87, 87, + 87, 95, 95, 95, 95, 104, 104, 104, 104, 113, + 89, 113, 113, 113, 114, 114, 115, 115, 117, 117, + 117, 88, 85, 84, 83, 82, 81, 80, 79, 77, + 76, 75, 74, 73, 71, 69, 68, 62, 61, 60, + 59, 57, 56, 55, 54, 53, 52, 51, 50, 42, + + 40, 39, 34, 33, 32, 31, 30, 29, 28, 26, + 25, 24, 23, 22, 16, 15, 7, 6, 5, 3, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[28] = +static yyconst flex_int32_t yy_rule_can_match_eol[31] = { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; extern int yy_flex_debug; int yy_flex_debug = 1; -static yyconst flex_int16_t yy_rule_linenum[27] = +static yyconst flex_int16_t yy_rule_linenum[30] = { 0, 82, 86, 92, 102, 108, 122, 129, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 162 + 156, 157, 158, 159, 160, 161, 162, 163, 165 } ; static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; @@ -746,7 +763,7 @@ static isc::eval::location loc; // by moving it ahead by yyleng bytes. yyleng specifies the length of the // currently matched token. #define YY_USER_ACTION loc.columns(yyleng); -#line 750 "lexer.cc" +#line 767 "lexer.cc" #define INITIAL 0 @@ -1043,7 +1060,7 @@ YY_DECL loc.step(); -#line 1047 "lexer.cc" +#line 1064 "lexer.cc" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1071,14 +1088,14 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 96 ) + if ( yy_current_state >= 113 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; *(yy_state_ptr)++ = yy_current_state; ++yy_cp; } - while ( yy_current_state != 95 ); + while ( yy_current_state != 112 ); yy_find_action: /* %% [10.0] code to find the action number goes here */ @@ -1141,13 +1158,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 27 ) + else if ( yy_act < 30 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 27 ) + else if ( yy_act == 30 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 28 ) + else if ( yy_act == 31 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1259,93 +1276,108 @@ return isc::eval::EvalParser::make_RELAY4(loc); case 11: YY_RULE_SETUP #line 146 "lexer.ll" -return isc::eval::EvalParser::make_TEXT(loc); +return isc::eval::EvalParser::make_RELAY6(loc); YY_BREAK case 12: YY_RULE_SETUP #line 147 "lexer.ll" -return isc::eval::EvalParser::make_HEX(loc); +return isc::eval::EvalParser::make_PEERADDR(loc); YY_BREAK case 13: YY_RULE_SETUP #line 148 "lexer.ll" -return isc::eval::EvalParser::make_EXISTS(loc); +return isc::eval::EvalParser::make_LINKADDR(loc); YY_BREAK case 14: YY_RULE_SETUP #line 149 "lexer.ll" -return isc::eval::EvalParser::make_SUBSTRING(loc); +return isc::eval::EvalParser::make_TEXT(loc); YY_BREAK case 15: YY_RULE_SETUP #line 150 "lexer.ll" -return isc::eval::EvalParser::make_ALL(loc); +return isc::eval::EvalParser::make_HEX(loc); YY_BREAK case 16: YY_RULE_SETUP #line 151 "lexer.ll" -return isc::eval::EvalParser::make_CONCAT(loc); +return isc::eval::EvalParser::make_EXISTS(loc); YY_BREAK case 17: YY_RULE_SETUP #line 152 "lexer.ll" -return isc::eval::EvalParser::make_NOT(loc); +return isc::eval::EvalParser::make_SUBSTRING(loc); YY_BREAK case 18: YY_RULE_SETUP #line 153 "lexer.ll" -return isc::eval::EvalParser::make_AND(loc); +return isc::eval::EvalParser::make_ALL(loc); YY_BREAK case 19: YY_RULE_SETUP #line 154 "lexer.ll" -return isc::eval::EvalParser::make_OR(loc); +return isc::eval::EvalParser::make_CONCAT(loc); YY_BREAK case 20: YY_RULE_SETUP #line 155 "lexer.ll" -return isc::eval::EvalParser::make_DOT(loc); +return isc::eval::EvalParser::make_NOT(loc); YY_BREAK case 21: YY_RULE_SETUP #line 156 "lexer.ll" -return isc::eval::EvalParser::make_LPAREN(loc); +return isc::eval::EvalParser::make_AND(loc); YY_BREAK case 22: YY_RULE_SETUP #line 157 "lexer.ll" -return isc::eval::EvalParser::make_RPAREN(loc); +return isc::eval::EvalParser::make_OR(loc); YY_BREAK case 23: YY_RULE_SETUP #line 158 "lexer.ll" -return isc::eval::EvalParser::make_LBRACKET(loc); +return isc::eval::EvalParser::make_DOT(loc); YY_BREAK case 24: YY_RULE_SETUP #line 159 "lexer.ll" -return isc::eval::EvalParser::make_RBRACKET(loc); +return isc::eval::EvalParser::make_LPAREN(loc); YY_BREAK case 25: YY_RULE_SETUP #line 160 "lexer.ll" -return isc::eval::EvalParser::make_COMA(loc); +return isc::eval::EvalParser::make_RPAREN(loc); YY_BREAK case 26: YY_RULE_SETUP +#line 161 "lexer.ll" +return isc::eval::EvalParser::make_LBRACKET(loc); + YY_BREAK +case 27: +YY_RULE_SETUP #line 162 "lexer.ll" +return isc::eval::EvalParser::make_RBRACKET(loc); + YY_BREAK +case 28: +YY_RULE_SETUP +#line 163 "lexer.ll" +return isc::eval::EvalParser::make_COMA(loc); + YY_BREAK +case 29: +YY_RULE_SETUP +#line 165 "lexer.ll" driver.error (loc, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 163 "lexer.ll" +#line 166 "lexer.ll" return isc::eval::EvalParser::make_END(loc); YY_BREAK -case 27: +case 30: YY_RULE_SETUP -#line 164 "lexer.ll" +#line 167 "lexer.ll" ECHO; YY_BREAK -#line 1349 "lexer.cc" +#line 1381 "lexer.cc" case YY_END_OF_BUFFER: { @@ -1630,7 +1662,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 96 ) + if ( yy_current_state >= 113 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1658,11 +1690,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 96 ) + if ( yy_current_state >= 113 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 95); + yy_is_jam = (yy_current_state == 112); if ( ! yy_is_jam ) *(yy_state_ptr)++ = yy_current_state; @@ -2428,7 +2460,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 164 "lexer.ll" +#line 167 "lexer.ll" diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 18a4b87591..9e44407c70 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -143,6 +143,9 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]* "==" return isc::eval::EvalParser::make_EQUAL(loc); "option" return isc::eval::EvalParser::make_OPTION(loc); "relay4" return isc::eval::EvalParser::make_RELAY4(loc); +"relay6" return isc::eval::EvalParser::make_RELAY6(loc); +"peeraddr" return isc::eval::EvalParser::make_PEERADDR(loc); +"linkaddr" return isc::eval::EvalParser::make_LINKADDR(loc); "text" return isc::eval::EvalParser::make_TEXT(loc); "hex" return isc::eval::EvalParser::make_HEX(loc); "exists" return isc::eval::EvalParser::make_EXISTS(loc); diff --git a/src/lib/eval/parser.cc b/src/lib/eval/parser.cc index 2887ba9461..f074b0f959 100644 --- a/src/lib/eval/parser.cc +++ b/src/lib/eval/parser.cc @@ -251,22 +251,30 @@ namespace isc { namespace eval { { switch (that.type_get ()) { - case 31: // option_repr_type + case 34: // option_repr_type value.move< TokenOption::RepresentationType > (that.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + value.move< TokenRelay6::FieldType > (that.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" value.move< std::string > (that.value); break; - case 30: // option_code + case 33: // option_code value.move< uint16_t > (that.value); break; + case 38: // nest_level + value.move< uint8_t > (that.value); + break; + default: break; } @@ -282,22 +290,30 @@ namespace isc { namespace eval { state = that.state; switch (that.type_get ()) { - case 31: // option_repr_type + case 34: // option_repr_type value.copy< TokenOption::RepresentationType > (that.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + value.copy< TokenRelay6::FieldType > (that.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" value.copy< std::string > (that.value); break; - case 30: // option_code + case 33: // option_code value.copy< uint16_t > (that.value); break; + case 38: // nest_level + value.copy< uint8_t > (that.value); + break; + default: break; } @@ -334,53 +350,67 @@ namespace isc { namespace eval { << yysym.location << ": "; switch (yytype) { - case 21: // "constant string" + case 24: // "constant string" -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 342 "parser.cc" // lalr1.cc:636 +#line 358 "parser.cc" // lalr1.cc:636 break; - case 22: // "integer" + case 25: // "integer" -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 349 "parser.cc" // lalr1.cc:636 +#line 365 "parser.cc" // lalr1.cc:636 break; - case 23: // "constant hexstring" + case 26: // "constant hexstring" -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 356 "parser.cc" // lalr1.cc:636 +#line 372 "parser.cc" // lalr1.cc:636 break; - case 24: // "option name" + case 27: // "option name" -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 363 "parser.cc" // lalr1.cc:636 +#line 379 "parser.cc" // lalr1.cc:636 break; - case 25: // "ip address" + case 28: // "ip address" -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< std::string > (); } -#line 370 "parser.cc" // lalr1.cc:636 +#line 386 "parser.cc" // lalr1.cc:636 break; - case 30: // option_code + case 33: // option_code -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< uint16_t > (); } -#line 377 "parser.cc" // lalr1.cc:636 +#line 393 "parser.cc" // lalr1.cc:636 break; - case 31: // option_repr_type + case 34: // option_repr_type -#line 73 "parser.yy" // lalr1.cc:636 +#line 78 "parser.yy" // lalr1.cc:636 { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); } -#line 384 "parser.cc" // lalr1.cc:636 +#line 400 "parser.cc" // lalr1.cc:636 + break; + + case 37: // relay6_field + +#line 78 "parser.yy" // lalr1.cc:636 + { yyoutput << yysym.value.template as< TokenRelay6::FieldType > (); } +#line 407 "parser.cc" // lalr1.cc:636 + break; + + case 38: // nest_level + +#line 78 "parser.yy" // lalr1.cc:636 + { yyoutput << yysym.value.template as< uint8_t > (); } +#line 414 "parser.cc" // lalr1.cc:636 break; @@ -580,22 +610,30 @@ namespace isc { namespace eval { when using variants. */ switch (yyr1_[yyn]) { - case 31: // option_repr_type + case 34: // option_repr_type yylhs.value.build< TokenOption::RepresentationType > (); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + yylhs.value.build< TokenRelay6::FieldType > (); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" yylhs.value.build< std::string > (); break; - case 30: // option_code + case 33: // option_code yylhs.value.build< uint16_t > (); break; + case 38: // nest_level + yylhs.value.build< uint8_t > (); + break; + default: break; } @@ -614,52 +652,52 @@ namespace isc { namespace eval { switch (yyn) { case 4: -#line 87 "parser.yy" // lalr1.cc:859 +#line 92 "parser.yy" // lalr1.cc:859 { TokenPtr neg(new TokenNot()); ctx.expression.push_back(neg); } -#line 623 "parser.cc" // lalr1.cc:859 +#line 661 "parser.cc" // lalr1.cc:859 break; case 5: -#line 92 "parser.yy" // lalr1.cc:859 +#line 97 "parser.yy" // lalr1.cc:859 { TokenPtr neg(new TokenAnd()); ctx.expression.push_back(neg); } -#line 632 "parser.cc" // lalr1.cc:859 +#line 670 "parser.cc" // lalr1.cc:859 break; case 6: -#line 97 "parser.yy" // lalr1.cc:859 +#line 102 "parser.yy" // lalr1.cc:859 { TokenPtr neg(new TokenOr()); ctx.expression.push_back(neg); } -#line 641 "parser.cc" // lalr1.cc:859 +#line 679 "parser.cc" // lalr1.cc:859 break; case 7: -#line 102 "parser.yy" // lalr1.cc:859 +#line 107 "parser.yy" // lalr1.cc:859 { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); } -#line 650 "parser.cc" // lalr1.cc:859 +#line 688 "parser.cc" // lalr1.cc:859 break; case 8: -#line 107 "parser.yy" // lalr1.cc:859 +#line 112 "parser.yy" // lalr1.cc:859 { TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS)); ctx.expression.push_back(opt); } -#line 659 "parser.cc" // lalr1.cc:859 +#line 697 "parser.cc" // lalr1.cc:859 break; case 9: -#line 112 "parser.yy" // lalr1.cc:859 +#line 117 "parser.yy" // lalr1.cc:859 { switch (ctx.getUniverse()) { case Option::V4: @@ -679,47 +717,65 @@ namespace isc { namespace eval { error(yystack_[5].location, "relay4 can only be used in DHCPv4."); } } -#line 683 "parser.cc" // lalr1.cc:859 +#line 721 "parser.cc" // lalr1.cc:859 break; case 10: -#line 134 "parser.yy" // lalr1.cc:859 +#line 137 "parser.yy" // lalr1.cc:859 + { + switch (ctx.getUniverse()) { + case Option::V6: + { + TokenPtr opt(new TokenRelay6Option(yystack_[8].value.as< uint8_t > (), yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS)); + ctx.expression.push_back(opt); + break; + } + case Option::V4: + // For now we only use relay6 in DHCPv6. + error(yystack_[10].location, "relay6 can only be used in DHCPv6."); + } + } +#line 739 "parser.cc" // lalr1.cc:859 + break; + + case 11: +#line 153 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 692 "parser.cc" // lalr1.cc:859 +#line 748 "parser.cc" // lalr1.cc:859 break; - case 11: -#line 139 "parser.yy" // lalr1.cc:859 + case 12: +#line 158 "parser.yy" // lalr1.cc:859 { TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(hex); } -#line 701 "parser.cc" // lalr1.cc:859 +#line 757 "parser.cc" // lalr1.cc:859 break; - case 12: -#line 144 "parser.yy" // lalr1.cc:859 + case 13: +#line 163 "parser.yy" // lalr1.cc:859 { TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(ip); } -#line 710 "parser.cc" // lalr1.cc:859 +#line 766 "parser.cc" // lalr1.cc:859 break; - case 13: -#line 149 "parser.yy" // lalr1.cc:859 + case 14: +#line 168 "parser.yy" // lalr1.cc:859 { TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ())); ctx.expression.push_back(opt); } -#line 719 "parser.cc" // lalr1.cc:859 +#line 775 "parser.cc" // lalr1.cc:859 break; - case 14: -#line 154 "parser.yy" // lalr1.cc:859 + case 15: +#line 173 "parser.yy" // lalr1.cc:859 { switch (ctx.getUniverse()) { case Option::V4: @@ -739,88 +795,144 @@ namespace isc { namespace eval { error(yystack_[5].location, "relay4 can only be used in DHCPv4."); } } -#line 743 "parser.cc" // lalr1.cc:859 +#line 799 "parser.cc" // lalr1.cc:859 break; - case 15: -#line 174 "parser.yy" // lalr1.cc:859 + case 16: +#line 194 "parser.yy" // lalr1.cc:859 + { + switch (ctx.getUniverse()) { + case Option::V6: + { + TokenPtr opt(new TokenRelay6Option(yystack_[8].value.as< uint8_t > (), yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ())); + ctx.expression.push_back(opt); + break; + } + case Option::V4: + // For now we only use relay6 in DHCPv6. + error(yystack_[10].location, "relay6 can only be used in DHCPv6."); + } + } +#line 817 "parser.cc" // lalr1.cc:859 + break; + + case 17: +#line 209 "parser.yy" // lalr1.cc:859 + { + switch (ctx.getUniverse()) { + case Option::V6: + { + TokenPtr relay6field(new TokenRelay6(yystack_[3].value.as< uint8_t > (), yystack_[0].value.as< TokenRelay6::FieldType > ())); + ctx.expression.push_back(relay6field); + break; + } + case Option::V4: + // For now we only use relay6 in DHCPv6. + error(yystack_[5].location, "relay6 can only be used in DHCPv6."); + } + } +#line 835 "parser.cc" // lalr1.cc:859 + break; + + case 18: +#line 225 "parser.yy" // lalr1.cc:859 { TokenPtr sub(new TokenSubstring()); ctx.expression.push_back(sub); } -#line 752 "parser.cc" // lalr1.cc:859 +#line 844 "parser.cc" // lalr1.cc:859 break; - case 16: -#line 179 "parser.yy" // lalr1.cc:859 + case 19: +#line 230 "parser.yy" // lalr1.cc:859 { TokenPtr conc(new TokenConcat()); ctx.expression.push_back(conc); } -#line 761 "parser.cc" // lalr1.cc:859 +#line 853 "parser.cc" // lalr1.cc:859 break; - case 17: -#line 186 "parser.yy" // lalr1.cc:859 + case 20: +#line 237 "parser.yy" // lalr1.cc:859 { yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location); } -#line 769 "parser.cc" // lalr1.cc:859 +#line 861 "parser.cc" // lalr1.cc:859 break; - case 18: -#line 190 "parser.yy" // lalr1.cc:859 + case 21: +#line 241 "parser.yy" // lalr1.cc:859 { yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location); } -#line 777 "parser.cc" // lalr1.cc:859 +#line 869 "parser.cc" // lalr1.cc:859 break; - case 19: -#line 196 "parser.yy" // lalr1.cc:859 + case 22: +#line 247 "parser.yy" // lalr1.cc:859 { yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL; } -#line 785 "parser.cc" // lalr1.cc:859 +#line 877 "parser.cc" // lalr1.cc:859 break; - case 20: -#line 200 "parser.yy" // lalr1.cc:859 + case 23: +#line 251 "parser.yy" // lalr1.cc:859 { yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL; } -#line 793 "parser.cc" // lalr1.cc:859 +#line 885 "parser.cc" // lalr1.cc:859 break; - case 21: -#line 206 "parser.yy" // lalr1.cc:859 + case 24: +#line 257 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 802 "parser.cc" // lalr1.cc:859 +#line 894 "parser.cc" // lalr1.cc:859 break; - case 22: -#line 213 "parser.yy" // lalr1.cc:859 + case 25: +#line 264 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ())); ctx.expression.push_back(str); } -#line 811 "parser.cc" // lalr1.cc:859 +#line 903 "parser.cc" // lalr1.cc:859 break; - case 23: -#line 218 "parser.yy" // lalr1.cc:859 + case 26: +#line 269 "parser.yy" // lalr1.cc:859 { TokenPtr str(new TokenString("all")); ctx.expression.push_back(str); } -#line 820 "parser.cc" // lalr1.cc:859 +#line 912 "parser.cc" // lalr1.cc:859 + break; + + case 27: +#line 275 "parser.yy" // lalr1.cc:859 + { yylhs.value.as< TokenRelay6::FieldType > () = TokenRelay6::PEERADDR; } +#line 918 "parser.cc" // lalr1.cc:859 break; + case 28: +#line 276 "parser.yy" // lalr1.cc:859 + { yylhs.value.as< TokenRelay6::FieldType > () = TokenRelay6::LINKADDR; } +#line 924 "parser.cc" // lalr1.cc:859 + break; -#line 824 "parser.cc" // lalr1.cc:859 + case 29: +#line 280 "parser.yy" // lalr1.cc:859 + { + yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location); + } +#line 932 "parser.cc" // lalr1.cc:859 + break; + + +#line 936 "parser.cc" // lalr1.cc:859 default: break; } @@ -1075,96 +1187,108 @@ namespace isc { namespace eval { } - const signed char EvalParser::yypact_ninf_ = -29; + const signed char EvalParser::yypact_ninf_ = -47; const signed char EvalParser::yytable_ninf_ = -1; const signed char EvalParser::yypact_[] = { - -1, -1, -1, 24, 27, 18, 37, -29, -29, -29, - 50, 6, 43, 11, -29, 10, 10, 16, 16, -29, - -1, -1, 16, -29, -29, -29, 40, 41, 44, 45, - 35, 38, -29, 52, -29, 46, 47, 10, 10, 39, - 16, 28, 31, 51, 53, -29, 48, 58, -29, -29, - -29, -29, -29, -29, 55, 56, -15, -29, 34, 34, - -29, -29, 60, -29 + 11, 11, 11, -4, -1, 3, 21, 27, -47, -47, + -47, 49, 51, 28, 44, -47, -2, -2, 19, 36, + 36, -47, 11, 11, 36, -47, -47, -47, 46, 48, + -47, 57, 59, 60, 61, 43, 54, -47, 71, -47, + 62, 63, 64, -2, -2, 19, 56, 36, 23, 35, + -5, 67, 68, 69, -47, 65, 81, -47, -47, -47, + -47, -47, -47, 72, -47, -47, -47, 73, 74, 75, + -16, -47, -2, 53, 53, 6, -47, -47, 84, 77, + 79, -47, 78, -2, 50, 80, -47, -47, 82, 53 }; const unsigned char EvalParser::yydefact_[] = { - 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, - 0, 2, 0, 0, 4, 0, 0, 0, 0, 1, - 0, 0, 0, 3, 17, 18, 0, 0, 0, 0, - 0, 0, 5, 6, 7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 21, 0, 0, 19, 20, - 8, 13, 9, 14, 0, 0, 0, 16, 0, 0, - 23, 22, 0, 15 + 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, + 13, 0, 2, 0, 0, 4, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 3, 20, 21, 0, 0, + 29, 0, 0, 0, 0, 0, 0, 5, 6, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 0, 0, 22, 23, 8, + 14, 9, 15, 0, 27, 28, 17, 0, 0, 0, + 0, 19, 0, 0, 0, 0, 26, 25, 0, 0, + 0, 18, 0, 0, 0, 0, 10, 16, 0, 0 }; const signed char EvalParser::yypgoto_[] = { - -29, -29, 9, -17, -10, -28, -29, -29 + -47, -47, 10, -18, -17, -46, -47, -47, -47, 52 }; const signed char EvalParser::yydefgoto_[] = { - -1, 10, 11, 12, 26, 51, 46, 62 + -1, 11, 12, 13, 28, 60, 55, 78, 66, 31 }; const unsigned char EvalParser::yytable_[] = { - 30, 31, 1, 60, 2, 34, 27, 61, 3, 4, - 13, 14, 20, 21, 53, 23, 5, 20, 21, 6, - 7, 17, 8, 47, 9, 28, 29, 43, 44, 32, - 33, 53, 24, 5, 25, 15, 6, 7, 16, 8, - 18, 9, 48, 49, 50, 48, 49, 52, 48, 49, - 19, 22, 35, 36, 39, 37, 38, 40, 20, 41, - 42, 45, 57, 54, 63, 55, 0, 56, 58, 59 + 29, 35, 36, 62, 63, 76, 39, 64, 65, 77, + 16, 14, 15, 17, 1, 80, 2, 18, 64, 65, + 3, 4, 5, 26, 19, 27, 51, 52, 62, 56, + 20, 6, 37, 38, 7, 8, 24, 9, 87, 10, + 57, 58, 59, 87, 30, 32, 33, 34, 25, 21, + 22, 23, 57, 58, 61, 79, 6, 22, 23, 7, + 8, 40, 9, 41, 10, 46, 85, 57, 58, 86, + 57, 58, 42, 43, 44, 45, 47, 22, 48, 49, + 50, 54, 67, 68, 69, 71, 72, 70, 81, 73, + 74, 75, 82, 83, 84, 88, 0, 53, 89 }; const signed char EvalParser::yycheck_[] = { - 17, 18, 3, 18, 5, 22, 16, 22, 9, 10, - 1, 2, 6, 7, 42, 4, 17, 6, 7, 20, - 21, 3, 23, 40, 25, 9, 10, 37, 38, 20, - 21, 59, 22, 17, 24, 11, 20, 21, 11, 23, - 3, 25, 14, 15, 16, 14, 15, 16, 14, 15, - 0, 8, 12, 12, 19, 11, 11, 19, 6, 13, - 13, 22, 4, 12, 4, 12, -1, 19, 13, 13 + 17, 19, 20, 49, 9, 21, 24, 12, 13, 25, + 14, 1, 2, 14, 3, 9, 5, 14, 12, 13, + 9, 10, 11, 25, 3, 27, 43, 44, 74, 47, + 3, 20, 22, 23, 23, 24, 8, 26, 84, 28, + 17, 18, 19, 89, 25, 9, 10, 11, 4, 0, + 6, 7, 17, 18, 19, 72, 20, 6, 7, 23, + 24, 15, 26, 15, 28, 22, 83, 17, 18, 19, + 17, 18, 15, 14, 14, 14, 22, 6, 16, 16, + 16, 25, 15, 15, 15, 4, 14, 22, 4, 16, + 16, 16, 15, 14, 16, 15, -1, 45, 16 }; const unsigned char EvalParser::yystos_[] = { - 0, 3, 5, 9, 10, 17, 20, 21, 23, 25, - 27, 28, 29, 28, 28, 11, 11, 3, 3, 0, - 6, 7, 8, 4, 22, 24, 30, 30, 9, 10, - 29, 29, 28, 28, 29, 12, 12, 11, 11, 19, - 19, 13, 13, 30, 30, 22, 32, 29, 14, 15, - 16, 31, 16, 31, 12, 12, 19, 4, 13, 13, - 18, 22, 33, 4 + 0, 3, 5, 9, 10, 11, 20, 23, 24, 26, + 28, 30, 31, 32, 31, 31, 14, 14, 14, 3, + 3, 0, 6, 7, 8, 4, 25, 27, 33, 33, + 25, 38, 9, 10, 11, 32, 32, 31, 31, 32, + 15, 15, 15, 14, 14, 14, 22, 22, 16, 16, + 16, 33, 33, 38, 25, 35, 32, 17, 18, 19, + 34, 19, 34, 9, 12, 13, 37, 15, 15, 15, + 22, 4, 14, 16, 16, 16, 21, 25, 36, 33, + 9, 4, 15, 14, 16, 33, 19, 34, 15, 16 }; const unsigned char EvalParser::yyr1_[] = { - 0, 26, 27, 28, 28, 28, 28, 28, 28, 28, - 29, 29, 29, 29, 29, 29, 29, 30, 30, 31, - 31, 32, 33, 33 + 0, 29, 30, 31, 31, 31, 31, 31, 31, 31, + 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 33, 33, 34, 34, 35, 36, 36, 37, 37, 38 }; const unsigned char EvalParser::yyr2_[] = { 0, 2, 1, 3, 2, 3, 3, 3, 6, 6, - 1, 1, 1, 6, 6, 8, 6, 1, 1, 1, - 1, 1, 1, 1 + 11, 1, 1, 1, 6, 6, 11, 6, 8, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -1175,21 +1299,23 @@ namespace isc { namespace eval { const EvalParser::yytname_[] = { "\"end of file\"", "error", "$undefined", "\"(\"", "\")\"", "\"not\"", - "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"[\"", - "\"]\"", "\".\"", "\"text\"", "\"hex\"", "\"exists\"", "\"substring\"", - "\"all\"", "\",\"", "\"concat\"", "\"constant string\"", "\"integer\"", + "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"relay6\"", + "\"peeraddr\"", "\"linkaddr\"", "\"[\"", "\"]\"", "\".\"", "\"text\"", + "\"hex\"", "\"exists\"", "\"substring\"", "\"all\"", "\",\"", + "\"concat\"", "\"constant string\"", "\"integer\"", "\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept", "expression", "bool_expr", "string_expr", "option_code", - "option_repr_type", "start_expr", "length_expr", YY_NULLPTR + "option_repr_type", "start_expr", "length_expr", "relay6_field", + "nest_level", YY_NULLPTR }; #if YYDEBUG - const unsigned char + const unsigned short int EvalParser::yyrline_[] = { - 0, 82, 82, 85, 86, 91, 96, 101, 106, 111, - 133, 138, 143, 148, 153, 173, 178, 185, 189, 195, - 199, 205, 212, 217 + 0, 87, 87, 90, 91, 96, 101, 106, 111, 116, + 136, 152, 157, 162, 167, 172, 193, 208, 224, 229, + 236, 240, 246, 250, 256, 263, 268, 275, 276, 279 }; // Print the state stack on the debug stream. @@ -1224,8 +1350,8 @@ namespace isc { namespace eval { #line 13 "parser.yy" // lalr1.cc:1167 } } // isc::eval -#line 1228 "parser.cc" // lalr1.cc:1167 -#line 224 "parser.yy" // lalr1.cc:1168 +#line 1354 "parser.cc" // lalr1.cc:1167 +#line 288 "parser.yy" // lalr1.cc:1168 void isc::eval::EvalParser::error(const location_type& loc, diff --git a/src/lib/eval/parser.h b/src/lib/eval/parser.h index 0678aeac29..93fece51db 100644 --- a/src/lib/eval/parser.h +++ b/src/lib/eval/parser.h @@ -298,15 +298,21 @@ namespace isc { namespace eval { // option_repr_type char dummy1[sizeof(TokenOption::RepresentationType)]; + // relay6_field + char dummy2[sizeof(TokenRelay6::FieldType)]; + // "constant string" // "integer" // "constant hexstring" // "option name" // "ip address" - char dummy2[sizeof(std::string)]; + char dummy3[sizeof(std::string)]; // option_code - char dummy3[sizeof(uint16_t)]; + char dummy4[sizeof(uint16_t)]; + + // nest_level + char dummy5[sizeof(uint8_t)]; }; /// Symbol semantic values. @@ -338,21 +344,24 @@ namespace isc { namespace eval { TOKEN_EQUAL = 263, TOKEN_OPTION = 264, TOKEN_RELAY4 = 265, - TOKEN_LBRACKET = 266, - TOKEN_RBRACKET = 267, - TOKEN_DOT = 268, - TOKEN_TEXT = 269, - TOKEN_HEX = 270, - TOKEN_EXISTS = 271, - TOKEN_SUBSTRING = 272, - TOKEN_ALL = 273, - TOKEN_COMA = 274, - TOKEN_CONCAT = 275, - TOKEN_STRING = 276, - TOKEN_INTEGER = 277, - TOKEN_HEXSTRING = 278, - TOKEN_OPTION_NAME = 279, - TOKEN_IP_ADDRESS = 280 + TOKEN_RELAY6 = 266, + TOKEN_PEERADDR = 267, + TOKEN_LINKADDR = 268, + TOKEN_LBRACKET = 269, + TOKEN_RBRACKET = 270, + TOKEN_DOT = 271, + TOKEN_TEXT = 272, + TOKEN_HEX = 273, + TOKEN_EXISTS = 274, + TOKEN_SUBSTRING = 275, + TOKEN_ALL = 276, + TOKEN_COMA = 277, + TOKEN_CONCAT = 278, + TOKEN_STRING = 279, + TOKEN_INTEGER = 280, + TOKEN_HEXSTRING = 281, + TOKEN_OPTION_NAME = 282, + TOKEN_IP_ADDRESS = 283 }; }; @@ -392,10 +401,14 @@ namespace isc { namespace eval { basic_symbol (typename Base::kind_type t, const TokenOption::RepresentationType v, const location_type& l); + basic_symbol (typename Base::kind_type t, const TokenRelay6::FieldType v, const location_type& l); + basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l); basic_symbol (typename Base::kind_type t, const uint16_t v, const location_type& l); + basic_symbol (typename Base::kind_type t, const uint8_t v, const location_type& l); + /// Constructor for symbols with semantic value. basic_symbol (typename Base::kind_type t, @@ -499,6 +512,18 @@ namespace isc { namespace eval { symbol_type make_RELAY4 (const location_type& l); + static inline + symbol_type + make_RELAY6 (const location_type& l); + + static inline + symbol_type + make_PEERADDR (const location_type& l); + + static inline + symbol_type + make_LINKADDR (const location_type& l); + static inline symbol_type make_LBRACKET (const location_type& l); @@ -665,7 +690,7 @@ namespace isc { namespace eval { static const char* const yytname_[]; #if YYDEBUG // YYRLINE[YYN] -- Source line where rule number YYN was defined. - static const unsigned char yyrline_[]; + static const unsigned short int yyrline_[]; /// Report on the debug stream that the rule \a r is going to be reduced. virtual void yy_reduce_print_ (int r); /// Print the state stack on the debug stream. @@ -764,12 +789,12 @@ namespace isc { namespace eval { enum { yyeof_ = 0, - yylast_ = 69, ///< Last index in yytable_. - yynnts_ = 8, ///< Number of nonterminal symbols. - yyfinal_ = 19, ///< Termination state number. + yylast_ = 98, ///< Last index in yytable_. + yynnts_ = 10, ///< Number of nonterminal symbols. + yyfinal_ = 21, ///< Termination state number. yyterror_ = 1, yyerrcode_ = 256, - yyntokens_ = 26 ///< Number of tokens. + yyntokens_ = 29 ///< Number of tokens. }; @@ -814,9 +839,9 @@ namespace isc { namespace eval { 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25 + 25, 26, 27, 28 }; - const unsigned int user_token_number_max_ = 280; + const unsigned int user_token_number_max_ = 283; const token_number_type undef_token_ = 2; if (static_cast(t) <= yyeof_) @@ -849,22 +874,30 @@ namespace isc { namespace eval { { switch (other.type_get ()) { - case 31: // option_repr_type + case 34: // option_repr_type value.copy< TokenOption::RepresentationType > (other.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + value.copy< TokenRelay6::FieldType > (other.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" value.copy< std::string > (other.value); break; - case 30: // option_code + case 33: // option_code value.copy< uint16_t > (other.value); break; + case 38: // nest_level + value.copy< uint8_t > (other.value); + break; + default: break; } @@ -882,22 +915,30 @@ namespace isc { namespace eval { (void) v; switch (this->type_get ()) { - case 31: // option_repr_type + case 34: // option_repr_type value.copy< TokenOption::RepresentationType > (v); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + value.copy< TokenRelay6::FieldType > (v); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" value.copy< std::string > (v); break; - case 30: // option_code + case 33: // option_code value.copy< uint16_t > (v); break; + case 38: // nest_level + value.copy< uint8_t > (v); + break; + default: break; } @@ -920,6 +961,13 @@ namespace isc { namespace eval { , location (l) {} + template + EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const TokenRelay6::FieldType v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} + template EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l) : Base (t) @@ -934,6 +982,13 @@ namespace isc { namespace eval { , location (l) {} + template + EvalParser::basic_symbol::basic_symbol (typename Base::kind_type t, const uint8_t v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} + template inline @@ -960,22 +1015,30 @@ namespace isc { namespace eval { // Type destructor. switch (yytype) { - case 31: // option_repr_type + case 34: // option_repr_type value.template destroy< TokenOption::RepresentationType > (); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + value.template destroy< TokenRelay6::FieldType > (); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" value.template destroy< std::string > (); break; - case 30: // option_code + case 33: // option_code value.template destroy< uint16_t > (); break; + case 38: // nest_level + value.template destroy< uint8_t > (); + break; + default: break; } @@ -999,22 +1062,30 @@ namespace isc { namespace eval { super_type::move(s); switch (this->type_get ()) { - case 31: // option_repr_type + case 34: // option_repr_type value.move< TokenOption::RepresentationType > (s.value); break; - case 21: // "constant string" - case 22: // "integer" - case 23: // "constant hexstring" - case 24: // "option name" - case 25: // "ip address" + case 37: // relay6_field + value.move< TokenRelay6::FieldType > (s.value); + break; + + case 24: // "constant string" + case 25: // "integer" + case 26: // "constant hexstring" + case 27: // "option name" + case 28: // "ip address" value.move< std::string > (s.value); break; - case 30: // option_code + case 33: // option_code value.move< uint16_t > (s.value); break; + case 38: // nest_level + value.move< uint8_t > (s.value); + break; + default: break; } @@ -1072,7 +1143,7 @@ namespace isc { namespace eval { { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280 + 275, 276, 277, 278, 279, 280, 281, 282, 283 }; return static_cast (yytoken_number_[type]); } @@ -1131,6 +1202,24 @@ namespace isc { namespace eval { return symbol_type (token::TOKEN_RELAY4, l); } + EvalParser::symbol_type + EvalParser::make_RELAY6 (const location_type& l) + { + return symbol_type (token::TOKEN_RELAY6, l); + } + + EvalParser::symbol_type + EvalParser::make_PEERADDR (const location_type& l) + { + return symbol_type (token::TOKEN_PEERADDR, l); + } + + EvalParser::symbol_type + EvalParser::make_LINKADDR (const location_type& l) + { + return symbol_type (token::TOKEN_LINKADDR, l); + } + EvalParser::symbol_type EvalParser::make_LBRACKET (const location_type& l) { @@ -1224,7 +1313,7 @@ namespace isc { namespace eval { #line 13 "parser.yy" // lalr1.cc:377 } } // isc::eval -#line 1228 "parser.h" // lalr1.cc:377 +#line 1317 "parser.h" // lalr1.cc:377 diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index d02002e202..7c160d7c19 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -45,6 +45,9 @@ using namespace isc::eval; EQUAL "==" OPTION "option" RELAY4 "relay4" + RELAY6 "relay6" + PEERADDR "peeraddr" + LINKADDR "linkaddr" LBRACKET "[" RBRACKET "]" DOT "." @@ -65,6 +68,8 @@ using namespace isc::eval; %type option_code %type option_repr_type +%type relay6_field +%type nest_level %left OR %left AND @@ -128,6 +133,20 @@ bool_expr : "(" bool_expr ")" error(@1, "relay4 can only be used in DHCPv4."); } } + | RELAY6 "[" nest_level "]" "." OPTION "[" option_code "]" "." EXISTS + { + switch (ctx.getUniverse()) { + case Option::V6: + { + TokenPtr opt(new TokenRelay6Option($3, $8, TokenOption::EXISTS)); + ctx.expression.push_back(opt); + break; + } + case Option::V4: + // For now we only use relay6 in DHCPv6. + error(@1, "relay6 can only be used in DHCPv6."); + } + } ; string_expr : STRING @@ -170,6 +189,38 @@ string_expr : STRING error(@1, "relay4 can only be used in DHCPv4."); } } + + | RELAY6 "[" nest_level "]" "." OPTION "[" option_code "]" "." option_repr_type + { + switch (ctx.getUniverse()) { + case Option::V6: + { + TokenPtr opt(new TokenRelay6Option($3, $8, $11)); + ctx.expression.push_back(opt); + break; + } + case Option::V4: + // For now we only use relay6 in DHCPv6. + error(@1, "relay6 can only be used in DHCPv6."); + } + } + + | RELAY6 "[" nest_level "]" "." relay6_field + { + switch (ctx.getUniverse()) { + case Option::V6: + { + TokenPtr relay6field(new TokenRelay6($3, $6)); + ctx.expression.push_back(relay6field); + break; + } + case Option::V4: + // For now we only use relay6 in DHCPv6. + error(@1, "relay6 can only be used in DHCPv6."); + } + } + + | SUBSTRING "(" string_expr "," start_expr "," length_expr ")" { TokenPtr sub(new TokenSubstring()); @@ -221,6 +272,19 @@ length_expr : INTEGER } ; +relay6_field : PEERADDR { $$ = TokenRelay6::PEERADDR; } + | LINKADDR { $$ = TokenRelay6::LINKADDR; } + ; + +nest_level : INTEGER + { + $$ = ctx.convertNestLevelNumber($1, @1); + } + // Eventually we may add strings to handle different + // ways of choosing from which relay we want to extract + // an option or field. + ; + %% void isc::eval::EvalParser::error(const location_type& loc, diff --git a/src/lib/eval/token.cc b/src/lib/eval/token.cc index fcbdc91057..490c4ceb31 100644 --- a/src/lib/eval/token.cc +++ b/src/lib/eval/token.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -295,3 +296,33 @@ TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) { values.push("false"); } } + +OptionPtr TokenRelay6Option::getOption(const Pkt& pkt) { + + try { + // Check if it's a Pkt6. If it's not the dynamic_cast will + // throw std::bad_cast. + const Pkt6& pkt6 = dynamic_cast(pkt); + + try { + // Now that we have the right type of packet we can + // get the option and return it. + return(pkt6.getRelayOption(option_code_, nest_level_)); + } + catch (const isc::OutOfRange&) { + // The only exception we expect is OutOfRange if the nest + // level is invalid. We return a NULL in that case. + return (OptionPtr()); + } + + } catch (const std::bad_cast&) { + isc_throw(EvalTypeError, "Specified packet is not Pkt6"); + } + +} + +void +TokenRelay6::evaluate(const Pkt& /*pkt*/, ValueStack& values) { + // test routine, need to add code in pkt6 to get the proper fields + values.push(""); +} diff --git a/src/lib/eval/token.h b/src/lib/eval/token.h index 4d4ab7a41b..b4a06b8af2 100644 --- a/src/lib/eval/token.h +++ b/src/lib/eval/token.h @@ -467,6 +467,108 @@ public: void evaluate(const Pkt& pkt, ValueStack& values); }; +/// @brief Token that represents a value of an option within a DHCPv6 relay +/// encapsulation +/// +/// This represents a reference to a given option similar to TokenOption +/// but from within the information from a relay. In the expresssion +/// relay6[nest-level].option[option-code], nest-level indicates which +/// of the relays to examine and option-code which option to extract. +/// +/// During the evaluation it tries to extract the value of the specified +/// option from the requested relay block. If the relay block doesn't +/// exist or the option is not found an empty string ("") is returned +/// (or "false" when the representation is EXISTS). +/// +/// The nesting level can go from 0 (closest to the server) to 31 +class TokenRelay6Option : public TokenOption { +public: + /// @brief Constructor that takes a nesting level and an option + /// code as paramaters. + /// + /// @param nest_level the nesting for which relay to examine. + /// @param option_code code of the option. + /// @param rep_type Token representation type. + TokenRelay6Option(const uint8_t nest_level, const uint16_t option_code, + const RepresentationType& rep_type) + :TokenOption(option_code, rep_type), nest_level_(nest_level) {} + + /// @brief Returns nest-level + /// + /// This method is used in testing to determine if the parser has + /// instantiated TokenRelay6Option with correct parameters. + /// + /// @return nest-level of the relay block this token expects to use + /// for extraction. + uint8_t getNest() const { + return (nest_level_); + } + +protected: + /// @brief Attempts to obtain specified option from the specified relay block + /// @param pkt DHCPv6 packet that hopefully contains the proper relay block + /// @return option instance if available + virtual OptionPtr getOption(const Pkt& pkt); + + uint8_t nest_level_; ///< nesting level of the relay block to use +}; + +/// @breif Token that represents a value of a field within a DHCPv6 relay +/// encapsulation +/// +/// This represents a reference to a field with a given DHCPv6 relay encapsulation. +/// In the expression relay6[nest-level].field-name, nest-level indicates which of +/// the relays to examine and field-name which of the fields to extract. +/// +/// During the evaluation it tries to extract the value of the specified +/// field from the requested relay block. If the relay block doesn't exist +/// an empty string ("") is returned. If the relay block does exist the field +/// is always returned as a 16 byte IPv6 address. As the relay may not have +/// set the field it may be 0s. +/// +/// The nesting level can go from 0 (closest to the server) to 31. +class TokenRelay6 : public Token { +public: + + /// @brief enum value that determines the field. + enum FieldType { + PEERADDR, ///< Peer address field (IPv6 address) + LINKADDR ///< Link address field (IPv6 address) + }; + + /// @brief Constructor that takes a nesting level and field type + /// as parameters. + /// + /// @param nest_level the nesting level for which relay to examine. + /// @param type which field to extract. + TokenRelay6(const uint8_t nest_level, const FieldType type) + : nest_level_(nest_level), type_(type) {} + + /// @brief Extracts the specified field from the requested relay + /// + /// Evaluation uses fields available in the packet. It does not require + /// any values to be present on the stack. + /// + /// @param pkt fields will be extracted from here + /// @param values - stack of values (1 result will be pushed) + void evaluate(const Pkt& pkt, ValueStack& values); + + /// @brief Returns field type + /// + /// This method is used only in testing to determine if the parser has + /// instantiated TokenRelay6 with correct parameters. + /// + /// @return type of the field. + FieldType getType() { + return (type_); + } + +protected: + /// @brief Specifies field of the DHCPv6 relay option to get + uint8_t nest_level_; ///< nesting level of the relay block to use + FieldType type_; ///< field to get +}; + }; // end of isc::dhcp namespace }; // end of isc namespace -- 2.47.2