Browse Source

[4204fd] Applied my proposed changes

Francis Dupont 9 years ago
parent
commit
c4cd450f03

+ 5 - 5
doc/guide/classify.xml

@@ -161,7 +161,7 @@
 <row><entry>Hex String</entry><entry>0XABCD</entry><entry>A hexadecimal string</entry></row>
 <row><entry>Integer</entry><entry>123</entry><entry>An integer value</entry></row>
 <row><entry>Option Text</entry><entry>option[code].text</entry><entry>The value of the option with code "code" from the packet as text</entry></row>
-<row><entry>Option Hex</entry><entry>option[code].hex</entry><entry>The value of the option with code "code" from the packet as hex</entry></row>
+<row><entry>Option Bin</entry><entry>option[code].bin</entry><entry>The value of the option with code "code" from the packet as binary</entry></row>
           </tbody>
           </tgroup>
         </table>
@@ -178,8 +178,8 @@
       <para>
       "option[code]" extracts the value of the option with the given code
       from the incoming packet. If the packet doesn't contain the option, it
-      returns the empty string.  The string can be presented as text or hex
-      with the ".text" or ".hex" modifiers.  In both cases only the payload
+      returns the empty string.  The string can be presented as text or binary
+      with the ".text" or ".bin" modifiers.  In both cases only the payload
       is presented; the type code and length fields are not included.
       </para>
 
@@ -297,7 +297,7 @@
     "client-classes": [<userinput>
         {
             "name": "Client_enterprise",
-            "test": "substring(option[2].hex,0,6) == 0x0002AABBCCDD'",
+            "test": "substring(option[2].bin,0,6) == 0x0002AABBCCDD'",
             "option-data": [
                 {
                     "name": "dns-servers",
@@ -370,7 +370,7 @@
     "client-classes": [
         {
             "name": "Client_enterprise",
-            "test": "substring(option[2].hex,0,6) == 0x0002AABBCCDD'",
+            "test": "substring(option[2].bin,0,6) == 0x0002AABBCCDD'",
             "option-data": [
                 {
                     "name": "dns-servers",

+ 1 - 1
doc/guide/dhcp6-srv.xml

@@ -1615,7 +1615,7 @@ should include options from the isc option space:
     "client-classes": [
         {<userinput>
             "name": "Client_enterprise",
-            "test": "substring(option[2].hex,0,6) == 0x0002AABBCCDD'",
+            "test": "substring(option[2].bin,0,6) == 0x0002AABBCCDD'",
             "option-data": [
                 {
                     "name": "dns-servers",

+ 95 - 0
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

@@ -1766,6 +1766,101 @@ TEST_F(Dhcpv4SrvTest, matchClassification) {
     EXPECT_FALSE(opt3);
 }
 
+// Checks if client packets are classified properly using match expressions
+// using option names
+TEST_F(Dhcpv4SrvTest, matchClassificationOptionName) {
+    NakedDhcpv4Srv srv(0);
+
+    // The router class matches incoming packets with foo in a host-name
+    string config = "{ \"interfaces-config\": {"
+        "    \"interfaces\": [ \"*\" ] }, "
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"valid-lifetime\": 4000, "
+        "\"subnet4\": [ "
+        "{   \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ], "
+        "    \"subnet\": \"192.0.2.0/24\" } ], "
+        "\"client-classes\": [ "
+        "{   \"name\": \"router\", "
+        "    \"test\": \"option[host-name].text == 'foo'\" } ] }";
+
+    ElementPtr json = Element::fromJSON(config);
+    ConstElementPtr status;
+
+    // Configure the server and make sure the config is accepted
+    EXPECT_NO_THROW(status = configureDhcp4Server(srv, json));
+    ASSERT_TRUE(status);
+    comment_ = config::parseAnswer(rcode_, status);
+    ASSERT_EQ(0, rcode_);
+
+    CfgMgr::instance().commit();
+
+    // Create a packet with enough to select the subnet
+    Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234));
+    query->setRemoteAddr(IOAddress("192.0.2.1"));
+
+    // Create and add a host-name option to the query
+    OptionStringPtr hostname(new OptionString(Option::V4, 12, "foo"));
+    ASSERT_TRUE(hostname);
+    query->addOption(hostname);
+
+    // Classify packets
+    srv.classifyPacket(query);
+
+    // The queey should be in the router class
+    EXPECT_TRUE(query->inClass("router"));
+}
+
+// Checks if client packets are classified properly using match expressions
+// using option names and definitions
+TEST_F(Dhcpv4SrvTest, matchClassificationOptionDef) {
+    NakedDhcpv4Srv srv(0);
+
+    // The router class matches incoming packets with foo in a defined
+    // option
+    string config = "{ \"interfaces-config\": {"
+        "    \"interfaces\": [ \"*\" ] }, "
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"valid-lifetime\": 4000, "
+        "\"subnet4\": [ "
+        "{   \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ], "
+        "    \"subnet\": \"192.0.2.0/24\" } ], "
+        "\"client-classes\": [ "
+        "{   \"name\": \"router\", "
+        "    \"test\": \"option[my-host-name].text == 'foo'\" } ], "
+        "\"option-def\": [ {"
+        "    \"name\": \"my-host-name\", "
+        "    \"code\": 250, "
+        "    \"type\": \"string\" } ] }";
+
+    ElementPtr json = Element::fromJSON(config);
+    ConstElementPtr status;
+
+    // Configure the server and make sure the config is accepted
+    EXPECT_NO_THROW(status = configureDhcp4Server(srv, json));
+    ASSERT_TRUE(status);
+    comment_ = config::parseAnswer(rcode_, status);
+    ASSERT_EQ(0, rcode_);
+
+    CfgMgr::instance().commit();
+
+    // Create a packet with enough to select the subnet
+    Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234));
+    query->setRemoteAddr(IOAddress("192.0.2.1"));
+
+    // Create and add a my-host-name option to the query
+    OptionStringPtr hostname(new OptionString(Option::V4, 250, "foo"));
+    ASSERT_TRUE(hostname);
+    query->addOption(hostname);
+
+    // Classify packets
+    srv.classifyPacket(query);
+
+    // The queey should be in the router class
+    EXPECT_TRUE(query->inClass("router"));
+}
+
 // Checks subnet options have the priority over class options
 TEST_F(Dhcpv4SrvTest, subnetClassPriority) {
     IfaceMgrTestConfig test_config(true);

+ 2 - 1
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -1837,6 +1837,7 @@ TEST_F(Dhcpv6SrvTest, docsisClientClassification) {
 }
 
 // Checks if client packets are classified properly using match expressions.
+// Note option names and definitions are used.
 TEST_F(Dhcpv6SrvTest, matchClassification) {
     IfaceMgrTestConfig test_config(true);
 
@@ -1866,7 +1867,7 @@ TEST_F(Dhcpv6SrvTest, matchClassification) {
         "    \"option-data\": ["
         "        {    \"name\": \"ipv6-forwarding\", "
         "             \"data\": \"true\" } ], "
-        "    \"test\": \"option[1234].text == 'foo'\" } ] }";
+        "    \"test\": \"option[host-name].text == 'foo'\" } ] }";
     ASSERT_NO_THROW(configure(config));
 
     // Create packets with enough to select the subnet

+ 1 - 1
src/lib/dhcp/option.cc

@@ -229,7 +229,7 @@ Option::toBinary(const bool include_header) {
         pack(buf);
 
     } catch (const std::exception &ex) {
-        isc_throw(OutOfRange, "unable to obtain hexadecimal representation"
+        isc_throw(OutOfRange, "unable to obtain binary representation"
                   " of option " << getType() << ": " << ex.what());
     }
     const uint8_t* option_data = static_cast<const uint8_t*>(buf.getData());

+ 12 - 12
src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc

@@ -182,19 +182,19 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName4) {
                               "hundred4");
 }
 
-// Verifies that given a valid expression using .hex operator for option, the
+// Verifies that given a valid expression using .bin operator for option, the
 // ExpressionParser produces an Expression which can be evaluated against
 // a v4 packet.
-TEST_F(ExpressionParserTest, validExpressionWithHex4) {
-    testValidExpression<Pkt4>(Option::V4, "\"option[12].hex == 0x68756E6472656434\"",
+TEST_F(ExpressionParserTest, validExpressionWithBin4) {
+    testValidExpression<Pkt4>(Option::V4, "\"option[12].bin == 0x68756E6472656434\"",
                               "hundred4");
 }
 
-// Verifies that the option name can be used together with .hex operator in
+// Verifies that the option name can be used together with .bin operator in
 // the evaluated expression.
-TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) {
+TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndBin4) {
     testValidExpression<Pkt6>(Option::V4,
-                              "\"option[host-name].text == 0x68756E6472656434\"",
+                              "\"option[host-name].bin == 0x68756E6472656434\"",
                               "hundred4");
 }
 
@@ -212,19 +212,19 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName6) {
                               "hundred6");
 }
 
-// Verifies that given a valid expression using .hex operator for option, the
+// Verifies that given a valid expression using .bin operator for option, the
 // ExpressionParser produces an Expression which can be evaluated against
 // a v6 packet.
-TEST_F(ExpressionParserTest, validExpressionWithHex6) {
-    testValidExpression<Pkt6>(Option::V6, "\"option[59].hex == 0x68756E6472656436\"",
+TEST_F(ExpressionParserTest, validExpressionWithBin6) {
+    testValidExpression<Pkt6>(Option::V6, "\"option[59].bin == 0x68756E6472656436\"",
                               "hundred6");
 }
 
-// Verifies that the option name can be used together with .hex operator in
+// Verifies that the option name can be used together with .bin operator in
 // the evaluated expression.
-TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex6) {
+TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndBin6) {
     testValidExpression<Pkt6>(Option::V6,
-                              "\"option[bootfile-url].text == 0x68756E6472656436\"",
+                              "\"option[bootfile-url].bin == 0x68756E6472656436\"",
                               "hundred6");
 }
 

+ 3 - 3
src/lib/eval/eval.dox

@@ -85,9 +85,9 @@
 19.                 TokenPtr opt(new TokenOption($3, TokenOption::TEXTUAL));
 20.                 ctx.expression.push_back(opt);
 21.             }
-22.       | OPTION '[' INTEGER ']' DOT HEX
+22.       | OPTION '[' INTEGER ']' DOT BIN
 23.             {
-24.                 TokenPtr opt(new TokenOption($3, TokenOption::HEXADECIMAL));
+24.                 TokenPtr opt(new TokenOption($3, TokenOption::BINARY));
 25.                 ctx.expression.push_back(opt);
 26.              }
 27.       ;
@@ -99,7 +99,7 @@ single token or an expression "token == token" (EQUAL has been defined as
 "==" elsewhere). Token is further
 defined in lines 7-22: it may either be a string (lines 7-11),
 a hex string (lines 12-16), option in the textual format (lines 17-21)
-or option in a hexadecimal format (lines 22-26).
+or option in the binary format (lines 22-26).
 When the actual case is determined, the respective C++ action
 is executed. For example, if the token is a string, the TokenString class is
 instantiated with the appropriate value and put onto the expression vector.

+ 142 - 144
src/lib/eval/lexer.cc

@@ -18,7 +18,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_SUBMINOR_VERSION 39
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -72,7 +72,6 @@ typedef int16_t flex_int16_t;
 typedef uint16_t flex_uint16_t;
 typedef int32_t flex_int32_t;
 typedef uint32_t flex_uint32_t;
-typedef uint64_t flex_uint64_t;
 #else
 typedef signed char flex_int8_t;
 typedef short int flex_int16_t;
@@ -80,7 +79,6 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -111,6 +109,8 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
+#endif /* ! C99 */
+
 #endif /* ! FLEXINT_H */
 
 /* %endif */
@@ -225,11 +225,18 @@ extern FILE *yyin, *yyout;
      */
     #define  YY_LESS_LINENO(n) \
             do { \
-                yy_size_t yyl;\
+                int yyl;\
                 for ( yyl = n; yyl < yyleng; ++yyl )\
                     if ( yytext[yyl] == '\n' )\
                         --yylineno;\
             }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
     
 /* Return all but the first "n" matched characters back to the input stream. */
 #define yyless(n) \
@@ -420,7 +427,7 @@ void yyfree (void *  );
 /* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
 /* Begin user sect3 */
 
-#define yywrap(n) 1
+#define yywrap() 1
 #define YY_SKIP_YYWRAP
 
 #define FLEX_DEBUG
@@ -438,6 +445,8 @@ int yylineno = 1;
 extern char *yytext;
 #define yytext_ptr yytext
 
+/* %% [1.5] DFA */
+
 /* %if-c-only Standard (non-C++) definition */
 
 static yy_state_type yy_get_previous_state (void );
@@ -453,7 +462,7 @@ static void yy_fatal_error (yyconst char msg[]  );
 #define YY_DO_BEFORE_ACTION \
 	(yytext_ptr) = yy_bp; \
 /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
-	yyleng = (yy_size_t) (yy_cp - yy_bp); \
+	yyleng = (size_t) (yy_cp - yy_bp); \
 	(yy_hold_char) = *yy_cp; \
 	*yy_cp = '\0'; \
 /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
@@ -469,27 +478,27 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_acclist[84] =
+static yyconst flex_int16_t yy_acclist[90] =
     {   0,
        21,   19,   20,    1,   19,   20,    2,   20,   19,   20,
-       13,   19,   20,   14,   19,   20,   17,   19,   20,   19,
-       20,   12,   19,   20,    5,   19,   20,    5,   19,   20,
-       19,   20,   19,   20,   15,   19,   20,   16,   19,   20,
-       19,   20,   19,   20,   19,   20,   19,   20,   19,   20,
-        1,    2,    3,    5,    6,16402,16402,16402,16402,16402,
-    16402,    4, 8210,   11,16402,    9,16402,16402,16402,16402,
-    16402,16402,    8,16402,16402,16402,    7,16402,16402,16402,
-    16402,   10,16402
+       14,   19,   20,   15,   19,   20,   18,   19,   20,   19,
+       20,   13,   19,   20,    5,   19,   20,    5,   19,   20,
+       19,   20,   19,   20,16390,   16,   19,   20,   17,   19,
+       20,   19,   20,16390,   19,   20,16390,   19,   20,16390,
+       19,   20,16390,   19,   20,16390,    1,    2,    3,    5,
+        7,16390, 8198,16390,16390,16390,16390,16390,    4,   12,
+    16390,   10,16390,16390,16390,16390,16390,16390,    9,16390,
+    16390,16390,    8,16390,16390,16390,16390,   11,16390
     } ;
 
-static yyconst flex_int16_t yy_accept[57] =
+static yyconst flex_int16_t yy_accept[58] =
     {   0,
         1,    1,    1,    2,    4,    7,    9,   11,   14,   17,
-       20,   22,   25,   28,   31,   33,   35,   38,   41,   43,
-       45,   47,   49,   51,   52,   53,   53,   54,   55,   55,
-       56,   57,   58,   59,   60,   61,   62,   63,   63,   64,
-       66,   68,   69,   70,   71,   72,   73,   75,   76,   77,
-       79,   80,   81,   82,   84,   84
+       20,   22,   25,   28,   31,   33,   36,   39,   42,   45,
+       48,   51,   54,   57,   58,   59,   59,   60,   61,   61,
+       62,   62,   62,   63,   64,   65,   66,   67,   68,   69,
+       70,   72,   74,   75,   76,   77,   78,   79,   81,   82,
+       83,   85,   86,   87,   88,   90,   90
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -505,8 +514,8 @@ static yyconst flex_int32_t yy_ec[256] =
        14,   14,   14,   14,   14,   14,   14,   15,   14,   14,
        16,    1,   17,    1,   18,    1,   19,   20,   13,   13,
 
-       21,   13,   22,   23,   24,   14,   14,   25,   14,   26,
-       27,   28,   14,   29,   30,   31,   32,   14,   14,   33,
+       21,   13,   22,   14,   23,   14,   14,   24,   14,   25,
+       26,   27,   14,   28,   29,   30,   31,   14,   14,   32,
        14,   14,    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,
@@ -524,74 +533,72 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[34] =
+static yyconst flex_int32_t yy_meta[33] =
     {   0,
-        1,    1,    2,    1,    1,    1,    1,    3,    1,    4,
-        4,    1,    4,    3,    3,    1,    1,    3,    4,    4,
-        4,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3
+        1,    2,    3,    1,    1,    1,    1,    2,    1,    4,
+        4,    1,    4,    2,    2,    1,    2,    2,    4,    4,
+        4,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2
     } ;
 
-static yyconst flex_int16_t yy_base[59] =
+static yyconst flex_int16_t yy_base[60] =
     {   0,
-        0,    0,  121,  122,  118,  116,  110,  122,  122,  122,
-       24,  122,   26,   28,   98,    0,  122,  122,   77,   79,
-       67,   61,   63,   68,   50,   47,  122,   32,    0,  122,
-       38,   43,   44,   45,   46,   47,    0,   48,  122,   50,
-       52,   54,   55,   56,   72,   73,   77,   79,   80,   81,
-       84,   86,   89,   90,  122,  112,  114,   40
+        0,    0,  113,  114,  110,  108,  106,  114,  114,  114,
+       23,  114,   25,   27,   97,   37,  114,  114,   56,   18,
+       19,   20,   26,  106,  104,  102,  114,   38,    0,  114,
+       50,   51,   81,  114,   80,   35,   32,   41,   39,    0,
+       79,   78,   46,   48,   52,   55,   54,   76,   61,   59,
+       73,   65,   66,   70,   69,  114,   94,   97,   62
     } ;
 
-static yyconst flex_int16_t yy_def[59] =
+static yyconst flex_int16_t yy_def[60] =
     {   0,
-       55,    1,   55,   55,   55,   55,   56,   55,   55,   55,
-       55,   55,   55,   55,   55,   57,   55,   55,   57,   57,
-       57,   57,   57,   55,   55,   56,   55,   55,   58,   55,
-       57,   57,   57,   57,   57,   57,   58,   55,   55,   57,
-       57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,   57,    0,   55,   55,   55
+       56,    1,   56,   56,   56,   56,   57,   56,   56,   56,
+       56,   56,   56,   56,   56,   58,   56,   56,   58,   19,
+       19,   19,   19,   56,   56,   57,   56,   56,   59,   56,
+       56,   19,   19,   56,   19,   19,   19,   19,   19,   59,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,    0,   56,   56,   56
     } ;
 
-static yyconst flex_int16_t yy_nxt[156] =
+static yyconst flex_int16_t yy_nxt[147] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   15,   16,   16,   16,   17,   18,    4,   19,   16,
-       16,   16,   20,   16,   16,   16,   21,   16,   16,   22,
-       23,   16,   16,   28,   28,   28,   28,   28,   28,   38,
-       29,   28,   28,   37,   38,   38,   38,   38,   38,   38,
-       27,   38,   25,   38,   39,   38,   38,   38,   29,   39,
-       39,   39,   39,   39,   39,   43,   39,   40,   39,   24,
-       39,   39,   39,   38,   38,   42,   41,   45,   38,   44,
-       38,   38,   38,   36,   46,   38,   47,   38,   39,   39,
-       38,   38,   35,   39,   34,   39,   39,   39,   48,   33,
-
-       39,   32,   39,   49,   50,   39,   39,   52,   51,   30,
-       54,   53,   26,   27,   26,   26,   31,   31,   25,   24,
-       55,    3,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55
+       14,   15,   16,   16,   16,   17,   18,    4,   19,   20,
+       16,   16,   16,   16,   16,   21,   16,   16,   22,   23,
+       16,   16,   28,   28,   28,   28,   28,   28,   31,   29,
+       36,   33,   33,   33,   32,   37,   39,   28,   28,   33,
+       38,   31,   56,   34,   32,   33,   29,   31,   33,   42,
+       44,   43,   33,   32,   33,   40,   34,   56,   46,   33,
+       45,   33,   34,   32,   33,   33,   47,   33,   33,   35,
+       49,   48,   33,   50,   33,   51,   52,   53,   33,   33,
+       54,   55,   33,   33,   26,   26,   33,   26,   33,   33,
+
+       33,   33,   33,   41,   33,   27,   25,   24,   30,   27,
+       25,   24,   56,    3,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56
     } ;
 
-static yyconst flex_int16_t yy_chk[156] =
+static yyconst flex_int16_t yy_chk[147] =
     {   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,   11,   11,   13,   13,   14,   14,   31,
-       13,   28,   28,   58,   32,   33,   34,   35,   36,   38,
-       26,   40,   25,   41,   31,   42,   43,   44,   13,   32,
-       33,   34,   35,   36,   38,   35,   40,   32,   41,   24,
-       42,   43,   44,   45,   46,   34,   33,   42,   47,   36,
-       48,   49,   50,   23,   43,   51,   44,   52,   45,   46,
-       53,   54,   22,   47,   21,   48,   49,   50,   45,   20,
-
-       51,   19,   52,   46,   48,   53,   54,   51,   49,   15,
-       53,   52,   56,    7,   56,   56,   57,   57,    6,    5,
-        3,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55
+        1,    1,   11,   11,   13,   13,   14,   14,   16,   13,
+       20,   20,   21,   22,   16,   21,   23,   28,   28,   23,
+       22,   31,   32,   16,   16,   37,   13,   19,   36,   36,
+       38,   37,   39,   19,   38,   59,   31,   32,   43,   43,
+       39,   44,   19,   19,   32,   45,   44,   47,   46,   19,
+       46,   45,   50,   47,   49,   49,   50,   52,   52,   53,
+       53,   54,   55,   54,   57,   57,   51,   57,   58,   48,
+
+       58,   42,   41,   35,   33,   26,   25,   24,   15,    7,
+        6,    5,    3,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56
     } ;
 
 /* Table of booleans, true if rule could match eol. */
@@ -605,8 +612,8 @@ int yy_flex_debug = 1;
 
 static yyconst flex_int16_t yy_rule_linenum[20] =
     {   0,
-       83,   87,   93,  103,  109,  123,  124,  125,  126,  127,
-      128,  129,  130,  131,  132,  133,  134,  136,  143
+       83,   87,   93,  103,  109,  123,  130,  131,  132,  133,
+      134,  135,  136,  137,  138,  139,  140,  141,  143
     } ;
 
 static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@ -688,7 +695,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 692 "lexer.cc"
+#line 699 "lexer.cc"
 
 #define INITIAL 0
 
@@ -806,7 +813,7 @@ static int input (void );
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
 /* %endif */
 /* %if-c++-only C++ definition */
 /* %endif */
@@ -821,7 +828,7 @@ static int input (void );
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		yy_size_t n; \
+		size_t n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -927,17 +934,6 @@ YY_DECL
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
-/* %% [7.0] user's declarations go here */
-#line 76 "lexer.ll"
-
-
-
-    // Code run each time yylex is called.
-    loc.step();
-
-
-#line 940 "lexer.cc"
-
 	if ( !(yy_init) )
 		{
 		(yy_init) = 1;
@@ -978,6 +974,18 @@ YY_DECL
 		yy_load_buffer_state( );
 		}
 
+	{
+/* %% [7.0] user's declarations go here */
+#line 76 "lexer.ll"
+
+
+
+    // Code run each time yylex is called.
+    loc.step();
+
+
+#line 988 "lexer.cc"
+
 	while ( 1 )		/* loops until end-of-file is reached */
 		{
 /* %% [8.0] yymore()-related code goes here */
@@ -1000,24 +1008,23 @@ YY_DECL
 yy_match:
 		do
 			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
 			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 >= 56 )
+				if ( yy_current_state >= 57 )
 					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 != 55 );
+		while ( yy_current_state != 56 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
 		yy_current_state = *--(yy_state_ptr);
 		(yy_lp) = yy_accept[yy_current_state];
-goto find_rule; /* Shut up GCC warning -Wall */
 find_rule: /* we branch to this label when backing up */
 		for ( ; ; ) /* until we find what rule we matched */
 			{
@@ -1150,72 +1157,72 @@ YY_RULE_SETUP
 case 6:
 YY_RULE_SETUP
 #line 123 "lexer.ll"
-return isc::eval::EvalParser::make_EQUAL(loc);
+{
+    // This string specifies option name starting with a letter
+    // and further containing letters, digits, hyphens and
+    // underscores and finishing by letters or digits.
+    return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc);
+}
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 124 "lexer.ll"
-return isc::eval::EvalParser::make_OPTION(loc);
+#line 130 "lexer.ll"
+return isc::eval::EvalParser::make_EQUAL(loc);
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 125 "lexer.ll"
-return isc::eval::EvalParser::make_TEXT(loc);
+#line 131 "lexer.ll"
+return isc::eval::EvalParser::make_OPTION(loc);
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 126 "lexer.ll"
-return isc::eval::EvalParser::make_HEX(loc);
+#line 132 "lexer.ll"
+return isc::eval::EvalParser::make_TEXT(loc);
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 127 "lexer.ll"
-return isc::eval::EvalParser::make_SUBSTRING(loc);
+#line 133 "lexer.ll"
+return isc::eval::EvalParser::make_BIN(loc);
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 128 "lexer.ll"
-return isc::eval::EvalParser::make_ALL(loc);
+#line 134 "lexer.ll"
+return isc::eval::EvalParser::make_SUBSTRING(loc);
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 129 "lexer.ll"
-return isc::eval::EvalParser::make_DOT(loc);
+#line 135 "lexer.ll"
+return isc::eval::EvalParser::make_ALL(loc);
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 130 "lexer.ll"
-return isc::eval::EvalParser::make_LPAREN(loc);
+#line 136 "lexer.ll"
+return isc::eval::EvalParser::make_DOT(loc);
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 131 "lexer.ll"
-return isc::eval::EvalParser::make_RPAREN(loc);
+#line 137 "lexer.ll"
+return isc::eval::EvalParser::make_LPAREN(loc);
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 132 "lexer.ll"
-return isc::eval::EvalParser::make_LBRACKET(loc);
+#line 138 "lexer.ll"
+return isc::eval::EvalParser::make_RPAREN(loc);
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 133 "lexer.ll"
-return isc::eval::EvalParser::make_RBRACKET(loc);
+#line 139 "lexer.ll"
+return isc::eval::EvalParser::make_LBRACKET(loc);
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 134 "lexer.ll"
-return isc::eval::EvalParser::make_COMA(loc);
+#line 140 "lexer.ll"
+return isc::eval::EvalParser::make_RBRACKET(loc);
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 136 "lexer.ll"
-{
-    // This string specifies option name starting with a letter
-    // and further containing letters, digits, hyphens and
-    // underscores.
-    return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc);
-}
+#line 141 "lexer.ll"
+return isc::eval::EvalParser::make_COMA(loc);
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
@@ -1231,7 +1238,7 @@ YY_RULE_SETUP
 #line 145 "lexer.ll"
 ECHO;
 	YY_BREAK
-#line 1235 "lexer.cc"
+#line 1242 "lexer.cc"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1361,6 +1368,7 @@ ECHO;
 			"fatal flex scanner internal error--no action found" );
 	} /* end of action switch */
 		} /* end of scanning one token */
+	} /* end of user's declarations */
 } /* end of yylex */
 /* %ok-for-header */
 
@@ -1511,7 +1519,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 >= 56 )
+			if ( yy_current_state >= 57 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1539,15 +1547,15 @@ 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 >= 56 )
+		if ( yy_current_state >= 57 )
 			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 == 55);
+	yy_is_jam = (yy_current_state == 56);
 	if ( ! yy_is_jam )
 		*(yy_state_ptr)++ = yy_current_state;
 
-	return yy_is_jam ? 0 : yy_current_state;
+		return yy_is_jam ? 0 : yy_current_state;
 }
 
 /* %if-c-only */
@@ -1606,7 +1614,7 @@ static int yy_get_next_buffer (void)
 				case EOB_ACT_END_OF_FILE:
 					{
 					if ( yywrap( ) )
-						return 0;
+						return EOF;
 
 					if ( ! (yy_did_buffer_switch_on_eof) )
 						YY_NEW_FILE;
@@ -1770,17 +1778,6 @@ static void yy_load_buffer_state  (void)
 	yyfree((void *) b  );
 }
 
-/* %if-c-only */
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-    
-/* %endif */
-
-/* %if-c++-only */
-/* %endif */
-
 /* Initializes or reinitializes a buffer.
  * This function is sometimes called more than once on the same buffer,
  * such as during a yyrestart() or at EOF.
@@ -2021,8 +2018,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
 /* %if-c-only */
 /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */
@@ -2030,7 +2027,8 @@ YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len
 {
 	YY_BUFFER_STATE b;
 	char *buf;
-	yy_size_t n, i;
+	yy_size_t n;
+	yy_size_t i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = _yybytes_len + 2;

+ 8 - 8
src/lib/eval/lexer.ll

@@ -120,10 +120,17 @@ blank [ \t]
     return isc::eval::EvalParser::make_INTEGER(tmp, loc);
 }
 
+[A-Za-z]([-_A-Za-z0-9]*[A-Za-z0-9])?/{blank}*] {
+    // This string specifies option name starting with a letter
+    // and further containing letters, digits, hyphens and
+    // underscores and finishing by letters or digits.
+    return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc);
+}
+
 "=="        return isc::eval::EvalParser::make_EQUAL(loc);
 "option"    return isc::eval::EvalParser::make_OPTION(loc);
 "text"      return isc::eval::EvalParser::make_TEXT(loc);
-"hex"       return isc::eval::EvalParser::make_HEX(loc);
+"bin"       return isc::eval::EvalParser::make_BIN(loc);
 "substring" return isc::eval::EvalParser::make_SUBSTRING(loc);
 "all"       return isc::eval::EvalParser::make_ALL(loc);
 "."         return isc::eval::EvalParser::make_DOT(loc);
@@ -133,13 +140,6 @@ blank [ \t]
 "]"         return isc::eval::EvalParser::make_RBRACKET(loc);
 ","         return isc::eval::EvalParser::make_COMA(loc);
 
-[A-Za-z][A-Za-z0-9_\-]+/{blank}*] {
-    // This string specifies option name starting with a letter
-    // and further containing letters, digits, hyphens and
-    // underscores.
-    return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc);
-}
-
 .          driver.error (loc, "Invalid character: " + std::string(yytext));
 <<EOF>>    return isc::eval::EvalParser::make_END(loc);
 %%

+ 5 - 5
src/lib/eval/parser.cc

@@ -643,7 +643,7 @@ namespace isc { namespace eval {
 #line 134 "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));
+                      TokenPtr opt(new TokenOption(numeric_code, TokenOption::BINARY));
                       ctx.expression.push_back(opt);
                   }
 #line 650 "parser.cc" // lalr1.cc:859
@@ -659,7 +659,7 @@ namespace isc { namespace eval {
                                                        TokenOption::TEXTUAL));
                           ctx.expression.push_back(opt);
 
-                      } catch (const std::exception& ex) {
+                      } catch (const isc::BadValue& ex) {
                           ctx.error(yystack_[3].location, ex.what());
                       }
                   }
@@ -673,10 +673,10 @@ namespace isc { namespace eval {
                           // This may result in exception if the specified
                           // name is unknown.
                           TokenPtr opt(new TokenOption(yystack_[3].value.as< std::string > (), option_universe,
-                                                       TokenOption::HEXADECIMAL));
+                                                       TokenOption::BINARY));
                           ctx.expression.push_back(opt);
 
-                      } catch (const std::exception& ex) {
+                      } catch (const isc::BadValue& ex) {
                           ctx.error(yystack_[3].location, ex.what());
                       }
                   }
@@ -1058,7 +1058,7 @@ namespace isc { namespace eval {
   const EvalParser::yytname_[] =
   {
   "\"end of file\"", "error", "$undefined", "\"==\"", "\"option\"",
-  "\"substring\"", "\"text\"", "\"hex\"", "\"all\"", "\".\"", "\",\"",
+  "\"substring\"", "\"text\"", "\"bin\"", "\"all\"", "\".\"", "\",\"",
   "\"(\"", "\")\"", "\"[\"", "\"]\"", "\"constant string\"", "\"integer\"",
   "\"constant hexstring\"", "\"option name\"", "TOKEN", "$accept",
   "expression", "bool_expr", "string_expr", "start_expr", "length_expr", YY_NULLPTR

+ 4 - 4
src/lib/eval/parser.h

@@ -328,7 +328,7 @@ namespace isc { namespace eval {
         TOKEN_OPTION = 259,
         TOKEN_SUBSTRING = 260,
         TOKEN_TEXT = 261,
-        TOKEN_HEX = 262,
+        TOKEN_BIN = 262,
         TOKEN_ALL = 263,
         TOKEN_DOT = 264,
         TOKEN_COMA = 265,
@@ -469,7 +469,7 @@ namespace isc { namespace eval {
 
     static inline
     symbol_type
-    make_HEX (const location_type& l);
+    make_BIN (const location_type& l);
 
     static inline
     symbol_type
@@ -1021,9 +1021,9 @@ namespace isc { namespace eval {
   }
 
   EvalParser::symbol_type
-  EvalParser::make_HEX (const location_type& l)
+  EvalParser::make_BIN (const location_type& l)
   {
-    return symbol_type (token::TOKEN_HEX, l);
+    return symbol_type (token::TOKEN_BIN, l);
   }
 
   EvalParser::symbol_type

+ 7 - 7
src/lib/eval/parser.yy

@@ -51,7 +51,7 @@ using namespace isc::eval;
   OPTION "option"
   SUBSTRING "substring"
   TEXT "text"
-  HEX "hex"
+  BIN "bin"
   ALL "all"
   DOT "."
   COMA ","
@@ -130,10 +130,10 @@ string_expr : STRING
                       TokenPtr opt(new TokenOption(numeric_code, TokenOption::TEXTUAL));
                       ctx.expression.push_back(opt);
                   }
-            | OPTION "[" INTEGER "]" DOT HEX
+            | OPTION "[" INTEGER "]" DOT BIN
                   {
                       uint16_t numeric_code = convert_option_code($3, @3, ctx);
-                      TokenPtr opt(new TokenOption(numeric_code, TokenOption::HEXADECIMAL));
+                      TokenPtr opt(new TokenOption(numeric_code, TokenOption::BINARY));
                       ctx.expression.push_back(opt);
                   }
             | OPTION "[" OPTION_NAME "]" DOT TEXT
@@ -145,20 +145,20 @@ string_expr : STRING
                                                        TokenOption::TEXTUAL));
                           ctx.expression.push_back(opt);
 
-                      } catch (const std::exception& ex) {
+                      } catch (const isc::BadValue& ex) {
                           ctx.error(@3, ex.what());
                       }
                   }
-            | OPTION "[" OPTION_NAME "]" DOT HEX
+            | OPTION "[" OPTION_NAME "]" DOT BIN
                   {
                       try {
                           // This may result in exception if the specified
                           // name is unknown.
                           TokenPtr opt(new TokenOption($3, option_universe,
-                                                       TokenOption::HEXADECIMAL));
+                                                       TokenOption::BINARY));
                           ctx.expression.push_back(opt);
 
-                      } catch (const std::exception& ex) {
+                      } catch (const isc::BadValue& ex) {
                           ctx.error(@3, ex.what());
                       }
                   }

+ 12 - 3
src/lib/eval/tests/context_unittest.cc

@@ -227,11 +227,11 @@ TEST_F(EvalContextTest, optionWithNameAndWhitespace) {
     checkTokenOption(eval.expression.at(0), 12);
 }
 
-// Test parsing of an option represented as hexadecimal string.
-TEST_F(EvalContextTest, optionHex) {
+// Test parsing of an option represented as binary string.
+TEST_F(EvalContextTest, optionBin) {
     EvalContext eval(Option::V4);
 
-    EXPECT_NO_THROW(parsed_ = eval.parseString("option[123].hex == 0x666F6F"));
+    EXPECT_NO_THROW(parsed_ = eval.parseString("option[123].bin == 0x666F6F"));
     EXPECT_TRUE(parsed_);
     ASSERT_EQ(3, eval.expression.size());
     checkTokenOption(eval.expression.at(0), 123);
@@ -292,6 +292,11 @@ TEST_F(EvalContextTest, scanParseErrors) {
                " expecting .");
     checkError("option[123].text < 'foo'", "<string>:1.18: Invalid"
                " character: <");
+    checkError("option[-ab].text", "<string>:1.8: Invalid character: -");
+    checkError("option[0ab].text",
+               "<string>:1.9-10: syntax error, unexpected option name, "
+               "expecting ]");
+    checkError("option[ab_].bin", "<string>:1.8: Invalid character: a");
     checkError("substring('foo',12345678901234567890,1)",
                "<string>:1.17-36: Failed to convert 12345678901234567890 "
                "to an integer.");
@@ -311,6 +316,10 @@ TEST_F(EvalContextTest, parseErrors) {
     checkError("option(10) == 'ab'",
                "<string>:1.7: syntax error, "
                "unexpected (, expecting [");
+    checkError("option['ab'].text == 'foo'",
+               "<string>:1.8-11: syntax error, "
+               "unexpected constant string, "
+               "expecting integer or option name");
     checkError("option[ab].text == 'foo'",
                "<string>:1.8-9: option 'ab' is not defined");
     checkError("option[0xa].text == 'ab'",

+ 2 - 2
src/lib/eval/tests/evaluate_unittest.cc

@@ -209,13 +209,13 @@ TEST_F(EvaluateTest, packet) {
     EXPECT_FALSE(result_);
 }
 
-// A test which compares option value represented in hexadecimal format.
+// A test which compares option value represented in binary format.
 TEST_F(EvaluateTest, optionHex) {
     TokenPtr toption;
     TokenPtr tstring;
     TokenPtr tequal;
 
-    ASSERT_NO_THROW(toption.reset(new TokenOption(100, TokenOption::HEXADECIMAL)));
+    ASSERT_NO_THROW(toption.reset(new TokenOption(100, TokenOption::BINARY)));
     e_.push_back(toption);
     ASSERT_NO_THROW(tstring.reset(new TokenString("hundred4")));
     e_.push_back(tstring);

+ 14 - 14
src/lib/eval/tests/token_unittest.cc

@@ -325,14 +325,14 @@ TEST_F(TokenTest, optionWithNameString4) {
 
 // This test checks if a token representing option value is able to extract
 // the option from an IPv4 packet and properly store its value in a
-// hexadecimal format.
-TEST_F(TokenTest, optionHexString4) {
+// binary format.
+TEST_F(TokenTest, optionBinString4) {
     TokenPtr found;
     TokenPtr not_found;
 
     // The packets we use have option 100 with a string in them.
-    ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::HEXADECIMAL)));
-    ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::HEXADECIMAL)));
+    ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::BINARY)));
+    ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::BINARY)));
 
     // This should evaluate to the content of the option 100 (i.e. "hundred4")
     ASSERT_NO_THROW(found->evaluate(*pkt4_, values_));
@@ -354,8 +354,8 @@ TEST_F(TokenTest, optionHexString4) {
 
 // This test checks if a token representing an option identified by name is
 // able to extract this option from an IPv4 packet and properly store its
-// value in the hexadecimal format.
-TEST_F(TokenTest, optionWithNameHexString4) {
+// value in the binary format.
+TEST_F(TokenTest, optionWithNameBinString4) {
     // Create definition of option 100 to provide a mapping between option
     // code and option name.
     ASSERT_NO_THROW(createOptionDefinitions4());
@@ -364,7 +364,7 @@ TEST_F(TokenTest, optionWithNameHexString4) {
     // map the option name to its code.
     TokenPtr token;
     ASSERT_NO_THROW(token.reset(new TokenOption("name-hundred4", Option::V4,
-                                                TokenOption::HEXADECIMAL)));
+                                                TokenOption::BINARY)));
 
     // Evaluate option in the packet.
     ASSERT_NO_THROW(token->evaluate(*pkt4_, values_));
@@ -426,15 +426,15 @@ TEST_F(TokenTest, optionWithNameString6) {
 
 
 // This test checks if a token representing an option value is able to extract
-// the option from an IPv6 packet and properly store its value in hexadecimal
+// the option from an IPv6 packet and properly store its value in binary
 // format.
-TEST_F(TokenTest, optionHexString6) {
+TEST_F(TokenTest, optionBinString6) {
     TokenPtr found;
     TokenPtr not_found;
 
     // The packets we use have option 100 with a string in them.
-    ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::HEXADECIMAL)));
-    ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::HEXADECIMAL)));
+    ASSERT_NO_THROW(found.reset(new TokenOption(100, TokenOption::BINARY)));
+    ASSERT_NO_THROW(not_found.reset(new TokenOption(101, TokenOption::BINARY)));
 
     // This should evaluate to the content of the option 100 (i.e. "hundred6")
     ASSERT_NO_THROW(found->evaluate(*pkt6_, values_));
@@ -456,8 +456,8 @@ TEST_F(TokenTest, optionHexString6) {
 
 // This test checks if a token representing an option identified by name is
 // able to extract this option from an IPv6 packet and properly store its
-// value in the hexadecimal format.
-TEST_F(TokenTest, optionWithNameHexString6) {
+// value in the binary format.
+TEST_F(TokenTest, optionWithNameBinString6) {
     // Create definition of option 100 to provide a mapping between option
     // code and option name.
     ASSERT_NO_THROW(createOptionDefinitions6());
@@ -466,7 +466,7 @@ TEST_F(TokenTest, optionWithNameHexString6) {
     // map the option name to its code.
     TokenPtr token;
     ASSERT_NO_THROW(token.reset(new TokenOption("name-hundred6", Option::V6,
-                                                TokenOption::HEXADECIMAL)));
+                                                TokenOption::BINARY)));
 
     // Evaluate option in the packet.
     ASSERT_NO_THROW(token->evaluate(*pkt6_, values_));

+ 4 - 1
src/lib/eval/token.cc

@@ -93,7 +93,10 @@ TokenOption::evaluate(const Pkt& pkt, ValueStack& values) {
             opt_str = opt->toString();
         } else {
             std::vector<uint8_t> binary = opt->toBinary();
-            opt_str.assign(binary.begin(), binary.end());
+            opt_str.resize(binary.size());
+            if (!binary.empty()) {
+                memmove(&opt_str[0], &binary[0], binary.size());
+            }
         }
     }
 

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

@@ -153,13 +153,13 @@ public:
     /// @brief Token representation type.
     ///
     /// There are many possible ways in which option can be presented.
-    /// Currently the textual and hexadecimal representations are
+    /// Currently the textual and binary representations are
     /// supported. The type of representation is specified in the
     /// constructor and it affects the value generated by the
     /// @c TokenOption::evaluate function.
     enum RepresentationType {
         TEXTUAL,
-        HEXADECIMAL
+        BINARY
     };
 
     /// @brief Constructor that takes an option code as a parameter
@@ -177,6 +177,7 @@ public:
     /// @param option_name Name of the option to be represented.
     /// @param option_universe Option universe: DHCPv4 or DHCPv6.
     /// @param rep_type Token representation type.
+    /// @throw BadValue when the option_name cannot be resolved
     TokenOption(const std::string& option_name,
                 const Option::Universe& option_universe,
                 const RepresentationType& rep_type);