Browse Source

[4204fd] Handle universe in option code range

Francis Dupont 9 years ago
parent
commit
3f5189fb7b

+ 3 - 3
src/lib/eval/eval_context.cc

@@ -19,8 +19,8 @@
 #include <fstream>
 
 EvalContext::EvalContext(const Option::Universe& option_universe)
-  : trace_scanning_(false), trace_parsing_(false),
-    option_universe_(option_universe)
+  : option_universe_(option_universe),
+    trace_scanning_(false), trace_parsing_(false)
 {
 }
 
@@ -34,7 +34,7 @@ EvalContext::parseString(const std::string& str)
     file_ = "<string>";
     string_ = str;
     scanStringBegin();
-    isc::eval::EvalParser parser(*this, option_universe_);
+    isc::eval::EvalParser parser(*this);
     parser.set_debug_level(trace_parsing_);
     int res = parser.parse();
     scanStringEnd();

+ 6 - 5
src/lib/eval/eval_context.h

@@ -85,6 +85,12 @@ public:
     /// cases when the EvalParser is not able to handle the packet.
     void error(const std::string& what);
 
+    /// @brief Option universe: DHCPv4 or DHCPv6.
+    ///
+    /// This is used by the parser to determine which option definitions
+    /// set should be used to map option name to option code.
+    Option::Universe option_universe_;
+
  private:
     /// @brief Flag determining scanner debugging.
     bool trace_scanning_;
@@ -92,11 +98,6 @@ public:
     /// @brief Flag determing parser debugging.
     bool trace_parsing_;
 
-    /// @brief Option universe: DHCPv4 or DHCPv6.
-    ///
-    /// This is used by the parser to determine which option definitions
-    /// set should be used to map option name to option code.
-    Option::Universe option_universe_;
 };
 
 }; // end of isc::eval namespace

+ 56 - 48
src/lib/eval/parser.cc

@@ -52,7 +52,7 @@
 #line 40 "parser.yy" // lalr1.cc:413
 
 # include "eval_context.h"
-#line 73 "parser.yy" // lalr1.cc:413
+#line 70 "parser.yy" // lalr1.cc:413
 
 namespace {
 
@@ -70,16 +70,23 @@ convert_option_code(const std::string& option_code,
         // This can't happen...
         ctx.error(loc, "Option code has invalid value in " + option_code);
     }
-    if (n < 0 || n > 65535) {
-        ctx.error(loc, "Option code has invalid value in "
-                      + option_code + ". Allowed range: 0..65535");
+    if (ctx.option_universe_ == Option::V6) {
+        if (n < 0 || n > 65535) {
+            ctx.error(loc, "Option code has invalid value in "
+                          + option_code + ". Allowed range: 0..65535");
+        }
+    } else {
+        if (n < 0 || n > 255) {
+            ctx.error(loc, "Option code has invalid value in "
+                          + option_code + ". Allowed range: 0..255");
+        }
     }
     return (static_cast<uint16_t>(n));
 }
 }
 
 
-#line 83 "parser.cc" // lalr1.cc:413
+#line 90 "parser.cc" // lalr1.cc:413
 
 
 #ifndef YY_
@@ -165,7 +172,7 @@ convert_option_code(const std::string& option_code,
 
 #line 21 "parser.yy" // lalr1.cc:479
 namespace isc { namespace eval {
-#line 169 "parser.cc" // lalr1.cc:479
+#line 176 "parser.cc" // lalr1.cc:479
 
   /* Return YYSTR after stripping away unnecessary quotes and
      backslashes, so that it's suitable for yyerror.  The heuristic is
@@ -206,14 +213,13 @@ namespace isc { namespace eval {
 
 
   /// Build a parser object.
-  EvalParser::EvalParser (EvalContext& ctx_yyarg, const Option::Universe& option_universe_yyarg)
+  EvalParser::EvalParser (EvalContext& ctx_yyarg)
     :
 #if YYDEBUG
       yydebug_ (false),
       yycdebug_ (&std::cerr),
 #endif
-      ctx (ctx_yyarg),
-      option_universe (option_universe_yyarg)
+      ctx (ctx_yyarg)
   {}
 
   EvalParser::~EvalParser ()
@@ -347,37 +353,37 @@ namespace isc { namespace eval {
     {
             case 15: // "constant string"
 
-#line 70 "parser.yy" // lalr1.cc:636
+#line 67 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 353 "parser.cc" // lalr1.cc:636
+#line 359 "parser.cc" // lalr1.cc:636
         break;
 
       case 16: // "integer"
 
-#line 70 "parser.yy" // lalr1.cc:636
+#line 67 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 360 "parser.cc" // lalr1.cc:636
+#line 366 "parser.cc" // lalr1.cc:636
         break;
 
       case 17: // "constant hexstring"
 
-#line 70 "parser.yy" // lalr1.cc:636
+#line 67 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 367 "parser.cc" // lalr1.cc:636
+#line 373 "parser.cc" // lalr1.cc:636
         break;
 
       case 18: // "option name"
 
-#line 70 "parser.yy" // lalr1.cc:636
+#line 67 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 374 "parser.cc" // lalr1.cc:636
+#line 380 "parser.cc" // lalr1.cc:636
         break;
 
       case 19: // TOKEN
 
-#line 70 "parser.yy" // lalr1.cc:636
+#line 67 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 381 "parser.cc" // lalr1.cc:636
+#line 387 "parser.cc" // lalr1.cc:636
         break;
 
 
@@ -603,59 +609,60 @@ namespace isc { namespace eval {
           switch (yyn)
             {
   case 3:
-#line 111 "parser.yy" // lalr1.cc:859
+#line 115 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr eq(new TokenEqual());
                     ctx.expression.push_back(eq);
                 }
-#line 612 "parser.cc" // lalr1.cc:859
+#line 618 "parser.cc" // lalr1.cc:859
     break;
 
   case 4:
-#line 118 "parser.yy" // lalr1.cc:859
+#line 122 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 621 "parser.cc" // lalr1.cc:859
+#line 627 "parser.cc" // lalr1.cc:859
     break;
 
   case 5:
-#line 123 "parser.yy" // lalr1.cc:859
+#line 127 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(hex);
                   }
-#line 630 "parser.cc" // lalr1.cc:859
+#line 636 "parser.cc" // lalr1.cc:859
     break;
 
   case 6:
-#line 128 "parser.yy" // lalr1.cc:859
+#line 132 "parser.yy" // lalr1.cc:859
     {
                       uint16_t numeric_code = convert_option_code(yystack_[3].value.as< std::string > (), yystack_[3].location, ctx);
                       TokenPtr opt(new TokenOption(numeric_code, TokenOption::TEXTUAL));
                       ctx.expression.push_back(opt);
                   }
-#line 640 "parser.cc" // lalr1.cc:859
+#line 646 "parser.cc" // lalr1.cc:859
     break;
 
   case 7:
-#line 134 "parser.yy" // lalr1.cc:859
+#line 138 "parser.yy" // lalr1.cc:859
     {
                       uint16_t numeric_code = convert_option_code(yystack_[3].value.as< std::string > (), yystack_[3].location, ctx);
                       TokenPtr opt(new TokenOption(numeric_code, TokenOption::HEXADECIMAL));
                       ctx.expression.push_back(opt);
                   }
-#line 650 "parser.cc" // lalr1.cc:859
+#line 656 "parser.cc" // lalr1.cc:859
     break;
 
   case 8:
-#line 140 "parser.yy" // lalr1.cc:859
+#line 144 "parser.yy" // lalr1.cc:859
     {
                       try {
                           // This may result in exception if the specified
                           // name is unknown.
-                          TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), option_universe,
+                          TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (),
+                                                       ctx.option_universe_,
                                                        TokenOption::TEXTUAL));
                           ctx.expression.push_back(opt);
 
@@ -663,16 +670,17 @@ namespace isc { namespace eval {
                           ctx.error(yystack_[3].location, ex.what());
                       }
                   }
-#line 667 "parser.cc" // lalr1.cc:859
+#line 674 "parser.cc" // lalr1.cc:859
     break;
 
   case 9:
-#line 153 "parser.yy" // lalr1.cc:859
+#line 158 "parser.yy" // lalr1.cc:859
     {
                       try {
                           // This may result in exception if the specified
                           // name is unknown.
-                          TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), option_universe,
+                          TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (),
+                                                       ctx.option_universe_,
                                                        TokenOption::HEXADECIMAL));
                           ctx.expression.push_back(opt);
 
@@ -680,47 +688,47 @@ namespace isc { namespace eval {
                           ctx.error(yystack_[3].location, ex.what());
                       }
                   }
-#line 684 "parser.cc" // lalr1.cc:859
+#line 692 "parser.cc" // lalr1.cc:859
     break;
 
   case 10:
-#line 166 "parser.yy" // lalr1.cc:859
+#line 172 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
                   }
-#line 693 "parser.cc" // lalr1.cc:859
+#line 701 "parser.cc" // lalr1.cc:859
     break;
 
   case 12:
-#line 175 "parser.yy" // lalr1.cc:859
+#line 181 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                      ctx.expression.push_back(str);
                  }
-#line 702 "parser.cc" // lalr1.cc:859
+#line 710 "parser.cc" // lalr1.cc:859
     break;
 
   case 13:
-#line 182 "parser.yy" // lalr1.cc:859
+#line 188 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 711 "parser.cc" // lalr1.cc:859
+#line 719 "parser.cc" // lalr1.cc:859
     break;
 
   case 14:
-#line 187 "parser.yy" // lalr1.cc:859
+#line 193 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString("all"));
                      ctx.expression.push_back(str);
                  }
-#line 720 "parser.cc" // lalr1.cc:859
+#line 728 "parser.cc" // lalr1.cc:859
     break;
 
 
-#line 724 "parser.cc" // lalr1.cc:859
+#line 732 "parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -1068,8 +1076,8 @@ namespace isc { namespace eval {
   const unsigned char
   EvalParser::yyrline_[] =
   {
-       0,   107,   107,   110,   117,   122,   127,   133,   139,   152,
-     165,   170,   174,   181,   186
+       0,   111,   111,   114,   121,   126,   131,   137,   143,   157,
+     171,   176,   180,   187,   192
   };
 
   // Print the state stack on the debug stream.
@@ -1104,8 +1112,8 @@ namespace isc { namespace eval {
 
 #line 21 "parser.yy" // lalr1.cc:1167
 } } // isc::eval
-#line 1108 "parser.cc" // lalr1.cc:1167
-#line 193 "parser.yy" // lalr1.cc:1168
+#line 1116 "parser.cc" // lalr1.cc:1167
+#line 199 "parser.yy" // lalr1.cc:1168
 
 void
 isc::eval::EvalParser::error(const location_type& loc,

+ 2 - 3
src/lib/eval/parser.h

@@ -521,7 +521,7 @@ namespace isc { namespace eval {
 
 
     /// Build a parser object.
-    EvalParser (EvalContext& ctx_yyarg, const Option::Universe& option_universe_yyarg);
+    EvalParser (EvalContext& ctx_yyarg);
     virtual ~EvalParser ();
 
     /// Parse.
@@ -735,7 +735,6 @@ namespace isc { namespace eval {
 
     // User arguments.
     EvalContext& ctx;
-    const Option::Universe& option_universe;
   };
 
   // Symbol number corresponding to token number t.
@@ -1101,7 +1100,7 @@ namespace isc { namespace eval {
 
 #line 21 "parser.yy" // lalr1.cc:392
 } } // isc::eval
-#line 1105 "parser.h" // lalr1.cc:392
+#line 1104 "parser.h" // lalr1.cc:392
 
 
 

+ 14 - 8
src/lib/eval/parser.yy

@@ -40,9 +40,6 @@ using namespace isc::eval;
 {
 # include "eval_context.h"
 }
-// Option universe: DHCPv4 or DHCPv6. This is required to use correct option
-// definition set to map option names to codes.
-%parse-param { const Option::Universe& option_universe }
 
 %define api.token.prefix {TOKEN_}
 %token
@@ -87,9 +84,16 @@ convert_option_code(const std::string& option_code,
         // This can't happen...
         ctx.error(loc, "Option code has invalid value in " + option_code);
     }
-    if (n < 0 || n > 65535) {
-        ctx.error(loc, "Option code has invalid value in "
-                      + option_code + ". Allowed range: 0..65535");
+    if (ctx.option_universe_ == Option::V6) {
+        if (n < 0 || n > 65535) {
+            ctx.error(loc, "Option code has invalid value in "
+                          + option_code + ". Allowed range: 0..65535");
+        }
+    } else {
+        if (n < 0 || n > 255) {
+            ctx.error(loc, "Option code has invalid value in "
+                          + option_code + ". Allowed range: 0..255");
+        }
     }
     return (static_cast<uint16_t>(n));
 }
@@ -141,7 +145,8 @@ string_expr : STRING
                       try {
                           // This may result in exception if the specified
                           // name is unknown.
-                          TokenPtr opt(new TokenOption($3, option_universe,
+                          TokenPtr opt(new TokenOption($3,
+                                                       ctx.option_universe_,
                                                        TokenOption::TEXTUAL));
                           ctx.expression.push_back(opt);
 
@@ -154,7 +159,8 @@ string_expr : STRING
                       try {
                           // This may result in exception if the specified
                           // name is unknown.
-                          TokenPtr opt(new TokenOption($3, option_universe,
+                          TokenPtr opt(new TokenOption($3,
+                                                       ctx.option_universe_,
                                                        TokenOption::HEXADECIMAL));
                           ctx.expression.push_back(opt);
 

+ 20 - 2
src/lib/eval/tests/context_unittest.cc

@@ -31,6 +31,12 @@ namespace {
 /// @brief Test class for testing EvalContext aka class test parsing
 class EvalContextTest : public ::testing::Test {
 public:
+    /// @brief constructor to initialize members
+    EvalContextTest() : ::testing::Test() {
+        parsed_ = false;
+        universe_ = Option::V4;
+    }
+
     /// @brief checks if the given token is a string with the expected value
     void checkTokenString(const TokenPtr& token, const std::string& expected) {
         ASSERT_TRUE(token);
@@ -95,7 +101,7 @@ public:
     /// @brief checks if the given expression raises the expected message
     /// when it is parsed.
     void checkError(const string& expr, const string& msg) {
-        EvalContext eval(Option::V4);
+        EvalContext eval(universe_);
         parsed_ = false;
         try {
             parsed_ = eval.parseString(expr);
@@ -110,6 +116,13 @@ public:
         }
     }
 
+    /// @brief sets the universe
+    /// @note the default universe is DHCPv4
+    void setUniverse(const Option::Universe& universe) {
+        universe_ = universe;
+    }
+
+    Option::Universe universe_;
     bool parsed_; ///< Parsing status
 };
 
@@ -292,10 +305,15 @@ TEST_F(EvalContextTest, scanParseErrors) {
     checkError("===", "<string>:1.1-2: syntax error, unexpected ==");
     checkError("option[-1].text",
                "<string>:1.8-9: Option code has invalid "
-               "value in -1. Allowed range: 0..65535");
+               "value in -1. Allowed range: 0..255");
+    checkError("option[256].text",
+               "<string>:1.8-10: Option code has invalid "
+               "value in 256. Allowed range: 0..255");
+    setUniverse(Option::V6);
     checkError("option[65536].text",
                "<string>:1.8-12: Option code has invalid "
                "value in 65536. Allowed range: 0..65535");
+    setUniverse(Option::V4);
     checkError("option[12345678901234567890].text",
                "<string>:1.8-27: Failed to convert 12345678901234567890 "
                "to an integer.");