]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[master] Merge branch 'trac4271' (vendor options support in classification)
authorTomek Mrugalski <tomasz@isc.org>
Thu, 18 Aug 2016 21:40:27 +0000 (23:40 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Thu, 18 Aug 2016 21:40:27 +0000 (23:40 +0200)
# Conflicts:
# src/lib/eval/lexer.cc
# src/lib/eval/lexer.ll
# src/lib/eval/location.hh
# src/lib/eval/parser.cc
# src/lib/eval/parser.h
# src/lib/eval/parser.yy
# src/lib/eval/position.hh
# src/lib/eval/stack.hh
# src/lib/eval/tests/context_unittest.cc
# src/lib/eval/tests/token_unittest.cc
# src/lib/eval/token.cc
# src/lib/eval/token.h

12 files changed:
1  2 
doc/guide/classify.xml
src/lib/eval/eval_context.cc
src/lib/eval/eval_messages.mes
src/lib/eval/lexer.cc
src/lib/eval/lexer.ll
src/lib/eval/parser.cc
src/lib/eval/parser.h
src/lib/eval/parser.yy
src/lib/eval/tests/context_unittest.cc
src/lib/eval/tests/token_unittest.cc
src/lib/eval/token.cc
src/lib/eval/token.h

Simple merge
index ca27893092c058d7b52bee279bec54749714c136,b1f4dbf443fe6974e43da0639df233c4ce513d77..4ede1dbc428ed33b38f7e67635709985dfa70606
@@@ -97,17 -98,12 +98,12 @@@ uint8_
  EvalContext::convertNestLevelNumber(const std::string& nest_level,
                                      const isc::eval::location& loc)
  {
-     int n = 0;
-     try {
-         n  = boost::lexical_cast<int>(nest_level);
-     } catch (const boost::bad_lexical_cast &) {
-         error(loc, "Nest level has invalid value in " + nest_level);
-     }
+     uint8_t n = convertUint8(nest_level, loc);
      if (option_universe_ == Option::V6) {
-         if (n < 0 || n >= HOP_COUNT_LIMIT) {
+         if (n >= HOP_COUNT_LIMIT) {
              error(loc, "Nest level has invalid value in "
                        + nest_level + ". Allowed range: 0..31");
 -      }
 +        }
      } else {
          error(loc, "Nest level invalid for DHCPv4 packets");
      }
Simple merge
index 6ba140daf27eff61fa9d764e4c843c220ad764a1,6b6a1e32f6e84d72e4dbb145d98e8ddcf0185080..69757ba1b3a1efc9e71f1a0c8faaed47838ec66d
@@@ -483,8 -483,8 +483,8 @@@ static void yy_fatal_error (yyconst cha
        (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 46
--#define YY_END_OF_BUFFER 47
++#define YY_NUM_RULES 51
++#define YY_END_OF_BUFFER 52
  /* This struct is not used in this scanner,
     but its presence is necessary. */
  struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
- static yyconst flex_int16_t yy_acclist[248] =
 -static yyconst flex_int16_t yy_acclist[262] =
++static yyconst flex_int16_t yy_acclist[280] =
      {   0,
--       47,   45,   46,    1,   45,   46,    2,   46,   45,   46,
-        40,   45,   46,   41,   45,   46,   44,   45,   46,   45,
-        46,   39,   45,   46,    5,   45,   46,    5,   45,   46,
-        45,   46,   45,   46,   45,   46,16390,   45,   46,16390,
-        42,   45,   46,   43,   45,   46,   45,   46,16390,   45,
 -       32,   45,   46,   33,   45,   46,   37,   45,   46,   36,
 -       45,   46,   45,   46,   31,   45,   46,    5,   45,   46,
 -        5,   45,   46,   45,   46,   45,   46,   45,   46,16390,
 -       45,   46,16390,   34,   45,   46,   35,   45,   46,   45,
--       46,16390,   45,   46,16390,   45,   46,16390,   45,   46,
--    16390,   45,   46,16390,   45,   46,16390,   45,   46,16390,
--       45,   46,16390,   45,   46,16390,   45,   46,16390,   45,
--       46,16390,   45,   46,16390,   45,   46,16390,   45,   46,
-     16390,   45,   46,16390,    1,    2,    3,    5,    5,    7,
 -    16390,   45,   46,16390,   45,   46,16390,    1,    2,    3,
--
-         8,16390,16390, 8198,16390,16390,16390,16390,16390,16390,
 -        5,    5,    7,    8,16390,16390, 8198,16390,16390,16390,
++       52,   50,   51,    1,   50,   51,    2,   51,   50,   51,
++       44,   50,   51,   45,   50,   51,   49,   50,   51,   48,
++       50,   51,   50,   51,   43,   50,   51,    5,   50,   51,
++        5,   50,   51,   50,   51,   50,   51,   50,   51,16390,
++       50,   51,16390,   46,   50,   51,   47,   50,   51,   50,
++       51,16390,   50,   51,16390,   50,   51,16390,   50,   51,
++    16390,   50,   51,16390,   50,   51,16390,   50,   51,16390,
++       50,   51,16390,   50,   51,16390,   50,   51,16390,   50,
++       51,16390,   50,   51,16390,   50,   51,16390,   50,   51,
++    16390,   50,   51,16390,   50,   51,16390,   50,   51,16390,
++
++        1,    2,    3,    5,    5,    7,    8,16390,16390, 8198,
      16390,16390,16390,16390,16390,16390,16390,16390,16390,16390,
-     16390,   38,16390,16390,16390,16390,16390,16390,16390,16390,
-     16390,16390,    4,    7,   34,16390,   37,16390,16390,16390,
-        20,16390,16390,16390,   15,16390,16390,16390,16390,   21,
-     16390,16390,   23,16390,16390,   36,16390,16390,16390,   17,
 -    16390,16390,16390,   30,16390,16390,16390,16390,16390,16390,
 -    16390,16390,16390,16390,    4,    7,   26,16390,   29,16390,
 -    16390,16390,16390,16390,16390,16390,   15,16390,16390,16390,
 -    16390,   18,16390,16390,   28,16390,16390,16390,16390,16390,
 -    16390,16390,16390,16390,16390,16390,16390,16390,   43,16390,
--    16390,16390,16390,   19,16390,16390,16390,16390,16390,16390,
-     16390,16390,16390,   24,16390,16390,16390,16390,16390,16390,
-     16390,   22,16390,   30,16390,16390,16390,16390,   14,16390,
-     16390,16390,16390,16390,16390,16390,   25,16390,   18,16390,
 -       17,16390,   38,16390,16390,16390,16390,   14,16390,16390,
 -    16390,16390,16390,16390,16390,16390,16390,   20,16390,16390,
--
-     16390,16390,16390,16390,16390,16390,16390,16390,16390,   26,
-     16390,   35,16390,   16,16390,   27,16390,16390,16390,    9,
-     16390,16390,   10,16390,   11,16390,   29,16390,16390,16390,
-        28,16390,    7,16390,   31,16390,16390,16390,   32,16390,
-        13,16390,   12,16390,16390,   33,16390
 -    16390,16390,16390,16390,16390,16390,16390,16390,16390,   21,
 -    16390,   27,16390,16390,   16,16390,   22,16390,16390,16390,
 -        9,16390,16390,   10,16390,   11,16390,   24,16390,16390,
 -    16390,   41,16390,   23,16390,    7,16390,16390,   39,16390,
 -    16390,16390,   40,16390,16390,   13,16390,   12,16390,16390,
 -    16390,16390,   25,16390,16390,   44,16390,16390,16390,   42,
 -    16390
++    16390,16390,16390,16390,16390,16390,16390,16390,16390,   42,
++    16390,16390,16390,16390,16390,16390,16390,16390,16390,16390,
++    16390,    4,    7,   38,16390,   41,16390,16390,16390,16390,
++       20,16390,16390,16390,16390,   15,16390,16390,16390,16390,
++       21,16390,16390,   23,16390,16390,   40,16390,16390,16390,
++       17,16390,16390,16390,   19,16390,16390,16390,16390,16390,
++    16390,16390,16390,   35,16390,16390,16390,16390,   24,16390,
++    16390,16390,16390,16390,16390,16390,   22,16390,   30,16390,
++
++    16390,16390,16390,   14,16390,16390,16390,16390,16390,16390,
++    16390,16390,16390,   25,16390,   18,16390,16390,16390,16390,
++    16390,16390,16390,16390,16390,16390,16390,   26,16390,   39,
++    16390,16390,   16,16390,   27,16390,16390,16390,    9,16390,
++    16390,   10,16390,   11,16390,   29,16390,16390,16390,   33,
++    16390,   28,16390,    7,16390,16390,   31,16390,16390,16390,
++       32,16390,16390,   13,16390,   12,16390,16390,16390,16390,
++       37,16390,16390,   36,16390,16390,16390,   34,16390
      } ;
  
- static yyconst flex_int16_t yy_accept[174] =
 -static yyconst flex_int16_t yy_accept[188] =
++static yyconst flex_int16_t yy_accept[199] =
      {   0,
          1,    1,    1,    2,    4,    7,    9,   11,   14,   17,
-        20,   22,   25,   28,   31,   33,   35,   38,   41,   44,
+        20,   23,   25,   28,   31,   34,   36,   38,   41,   44,
         47,   50,   53,   56,   59,   62,   65,   68,   71,   74,
-        77,   80,   83,   86,   89,   92,   95,   96,   97,   97,
-        98,   99,   99,  100,  100,  100,  100,  100,  101,  102,
-       102,  102,  103,  104,  105,  106,  107,  108,  109,  110,
-       111,  112,  113,  114,  115,  116,  117,  118,  119,  120,
-       121,  122,  124,  125,  126,  127,  128,  129,  130,  131,
-       132,  133,  133,  134,  135,  137,  139,  140,  141,  143,
-       144,  145,  147,  148,  149,  150,  152,  153,  155,  156,
 -       77,   80,   83,   86,   89,   92,   95,   98,   99,  100,
 -      100,  101,  102,  102,  103,  103,  103,  103,  103,  104,
 -      105,  105,  105,  106,  107,  108,  109,  110,  111,  112,
 -      113,  114,  115,  116,  117,  118,  119,  120,  121,  122,
 -      123,  124,  126,  127,  128,  129,  130,  131,  132,  133,
 -      134,  135,  135,  136,  137,  139,  141,  142,  143,  144,
 -      145,  146,  147,  149,  150,  151,  152,  154,  155,  157,
--
-       158,  159,  160,  162,  163,  164,  166,  167,  168,  169,
-       170,  170,  171,  172,  173,  174,  176,  177,  178,  179,
-       180,  181,  182,  184,  186,  187,  188,  189,  191,  192,
-       193,  193,  194,  195,  196,  197,  199,  201,  202,  203,
-       204,  205,  206,  207,  208,  209,  210,  210,  212,  214,
-       216,  218,  219,  220,  222,  223,  225,  227,  229,  230,
-       231,  233,  234,  235,  237,  238,  239,  241,  243,  245,
-       246,  248,  248
 -      158,  159,  160,  161,  162,  163,  164,  165,  166,  167,
 -      167,  168,  169,  171,  172,  173,  174,  176,  177,  178,
 -      179,  180,  181,  183,  185,  186,  187,  188,  190,  191,
 -      192,  193,  193,  194,  195,  196,  197,  198,  200,  201,
 -      202,  203,  204,  205,  206,  207,  208,  209,  210,  210,
 -      212,  214,  215,  217,  219,  220,  221,  223,  224,  226,
 -      228,  230,  231,  232,  234,  236,  237,  238,  239,  241,
 -      242,  243,  245,  245,  246,  248,  250,  251,  252,  253,
 -      255,  256,  258,  259,  260,  262,  262
++       77,   80,   83,   86,   89,   92,   95,   98,  101,  102,
++      103,  103,  104,  105,  105,  106,  106,  106,  106,  106,
++      107,  108,  108,  108,  109,  110,  111,  112,  113,  114,
++      115,  116,  117,  118,  119,  120,  121,  122,  123,  124,
++      125,  126,  127,  128,  129,  130,  132,  133,  134,  135,
++      136,  137,  138,  139,  140,  141,  142,  142,  143,  144,
++      146,  148,  149,  150,  151,  153,  154,  155,  156,  158,
++
++      159,  160,  161,  163,  164,  166,  167,  169,  170,  171,
++      173,  174,  175,  177,  178,  179,  180,  181,  182,  182,
++      183,  184,  186,  187,  188,  189,  191,  192,  193,  194,
++      195,  196,  197,  199,  201,  202,  203,  204,  206,  207,
++      208,  209,  209,  210,  211,  212,  213,  214,  216,  218,
++      219,  220,  221,  222,  223,  224,  225,  226,  227,  228,
++      228,  230,  232,  233,  235,  237,  238,  239,  241,  242,
++      244,  246,  248,  249,  250,  252,  254,  255,  256,  257,
++      259,  260,  261,  263,  263,  264,  266,  268,  269,  270,
++      271,  273,  274,  276,  277,  278,  280,  280
++
      } ;
  
  static yyconst YY_CHAR yy_ec[256] =
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
          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,   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,   27,   28,   29,   30,   17,   31,   32,   33,   34,
-        35,   36,   17,   37,   38,   39,   40,   17,   17,   41,
-        42,   17,    1,    1,    1,    1,    1,    1,    1,    1,
+         6,    7,    1,    8,    9,   10,    1,   11,   12,   12,
+        12,   13,   12,   14,   12,   12,   12,   15,    1,    1,
+        16,    1,    1,    1,   17,   17,   17,   17,   17,   17,
+        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+        18,   18,   18,   18,   18,   18,   18,   19,   18,   18,
+        20,    1,   21,    1,   22,    1,   23,   24,   25,   26,
 -       27,   17,   28,   29,   30,   18,   31,   32,   33,   34,
 -       35,   36,   18,   37,   38,   39,   40,   41,   18,   42,
 -       43,   18,    1,    1,    1,    1,    1,    1,    1,    1,
++       27,   28,   29,   30,   31,   18,   32,   33,   34,   35,
++       36,   37,   18,   38,   39,   40,   41,   42,   18,   43,
++       44,   18,    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,
          1,    1,    1,    1,    1
      } ;
  
- static yyconst YY_CHAR yy_meta[43] =
 -static yyconst YY_CHAR yy_meta[44] =
++static yyconst YY_CHAR yy_meta[45] =
      {   0,
-         1,    1,    2,    1,    1,    1,    1,    1,    3,    4,
-         4,    4,    4,    5,    1,    4,    1,    1,    1,    1,
-         1,    4,    4,    4,    4,    4,    4,    1,    1,    1,
+         1,    1,    2,    1,    1,    1,    1,    1,    1,    3,
+         4,    4,    4,    4,    5,    1,    4,    1,    1,    1,
 -        1,    1,    4,    4,    4,    4,    4,    1,    1,    1,
++        1,    1,    4,    4,    4,    4,    4,    4,    1,    1,
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-         1,    1
 -        1,    1,    1
++        1,    1,    1,    1
      } ;
  
- static yyconst flex_uint16_t yy_base[178] =
 -static yyconst flex_uint16_t yy_base[192] =
++static yyconst flex_uint16_t yy_base[203] =
      {   0,
-         0,    0,  281,  282,  278,  276,  274,  282,  282,  282,
-        33,  282,   38,   35,  263,  261,   78,  111,  282,  282,
-        23,   36,  237,  233,  243,   43,  245,   42,   36,  236,
-        41,  100,  244,  102,   33,  239,  266,  264,  262,  282,
-       133,  137,  110,  251,  250,    0,  249,    0,  282,  138,
-       150,    0,    0,  282,  230,  236,  238,  225,  219,  227,
-       234,  214,  228,  211,  230,  217,  216,  225,  220,  208,
-       207,    0,  219,  205,  211,  220,  217,  217,  198,  216,
-       215,  150,    0,    0,    0,    0,  211,  211,    0,  196,
-       208,    0,  198,  195,  206,    0,  198,    0,  189,    0,
 -        0,    0,  296,  297,  293,  291,  289,  297,  297,  297,
 -      297,   33,  297,   38,   35,  277,  275,   79,  112,  297,
 -      297,   24,   36,  267,   25,  259,   46,  258,   37,  252,
 -       32,   43,  259,   46,   52,  258,  254,  281,  279,  277,
 -      297,  119,  129,   53,  265,  264,    0,  263,    0,  297,
 -      142,  144,    0,    0,  297,  245,  250,  252,  240,  234,
 -      233,  241,  247,  227,  241,  224,  232,  240,  236,  224,
 -      223,    0,  234,  221,  227,  235,  233,  214,  232,  220,
 -      230,  138,    0,    0,    0,    0,  226,  226,  227,  222,
 -      210,  221,    0,  212,  209,  213,    0,  204,    0,  212,
--
-       197,  189,   71,  203,  199,    0,  185,  183,  187,  195,
-       144,  194,  196,  178,  191,    0,  189,  188,  191,  170,
-       176,  188,    0,    0,  167,  183,  168,    0,  168,  180,
-       155,  167,  164,  164,  164,    0,    0,  175,  163,  164,
-       172,  117,  159,  158,  164,  156,  161,    0,    0,    0,
-         0,  167,  165,    0,  155,    0,    0,    0,  139,   72,
-         0,  165,   56,    0,   50,   51,    0,    0,    0,   45,
-         0,  282,  178,  180,  182,   63,  185
 -      204,   70,  217,  213,  200,  198,  202,  209,  208,  142,
 -      207,  209,    0,  194,  191,  203,    0,  201,  204,  183,
 -      190,  201,    0,    0,  180,  196,  182,    0,  182,  184,
 -      192,  147,  180,  177,  179,  176,  176,    0,  186,  165,
 -      164,  171,  153,  159,  157,  163,  155,  154,  157,    0,
 -        0,  153,    0,    0,  163,  161,    0,  161,    0,    0,
 -        0,  156,  159,  175,    0,  161,  153,  145,    0,  144,
 -      146,    0,  174,  141,    0,    0,  150,  132,  135,    0,
 -      111,    0,   90,   61,    0,  297,  199,  201,  203,   83,
 -      206
 -
++        0,    0,  310,  311,  307,  305,  303,  311,  311,  311,
++      311,   34,  311,   39,   36,  291,  289,   81,  115,  311,
++      311,   24,   37,   37,   26,  273,   45,  275,   43,   48,
++      266,   43,   59,  274,  106,   50,  273,  268,  296,  294,
++      292,  311,  122,  137,  112,  280,  279,    0,  278,    0,
++      311,  143,  150,    0,    0,  311,  259,  265,  267,  254,
++      248,  247,  246,  254,  261,  240,  255,  237,  257,  244,
++      243,  252,  247,  235,  234,    0,  246,  232,  238,  247,
++      244,  244,  224,  243,  230,  241,  146,    0,    0,    0,
++        0,  237,  237,  238,    0,  233,  220,  232,    0,  222,
++
++      219,  230,    0,  222,    0,  213,    0,  221,  213,  148,
++      227,  223,    0,  209,  207,  211,  219,  218,  154,  217,
++      219,    0,  203,  200,  213,    0,  211,  210,  213,  191,
++      198,  210,    0,    0,  188,  205,  190,    0,  190,  192,
++      201,  162,  188,  185,  187,  184,  184,    0,    0,  195,
++      173,  172,  180,  156,  167,  165,  171,  163,  162,  166,
++        0,    0,  161,    0,    0,  172,  170,    0,  170,    0,
++        0,    0,  164,  168,  184,    0,  170,  161,  153,    0,
++      152,  154,    0,  183,  149,    0,    0,  158,  130,  127,
++        0,   78,    0,   58,   50,    0,  311,  208,  210,  212,
++
++       71,  215
      } ;
  
- static yyconst flex_int16_t yy_def[178] =
 -static yyconst flex_int16_t yy_def[192] =
++static yyconst flex_int16_t yy_def[203] =
      {   0,
-       172,    1,  172,  172,  172,  172,  173,  172,  172,  172,
-       172,  172,  172,   13,  174,  172,  172,   17,  172,  172,
-        17,   17,   17,   17,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,  172,  172,  173,  172,
-       172,  172,   13,  174,  175,  176,  174,  177,  172,  172,
-        18,   17,   18,  172,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,  172,  176,  177,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-       172,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-       172,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,  172,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,  172,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,    0,  172,  172,  172,  172,  172
 -      186,    1,  186,  186,  186,  186,  187,  186,  186,  186,
 -      186,  186,  186,  186,   14,  188,  186,  186,   18,  186,
 -      186,   18,   18,   18,   18,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,   19,   19,  186,  186,  187,
 -      186,  186,  186,   14,  188,  189,  190,  188,  191,  186,
 -      186,   19,   18,   19,  186,   19,   19,   19,   19,   18,
++      197,    1,  197,  197,  197,  197,  198,  197,  197,  197,
++      197,  197,  197,  197,   14,  199,  197,  197,   18,  197,
++      197,   18,   18,   18,   18,   19,   19,   19,   19,   19,
++       19,   19,   19,   19,   19,   19,   19,   19,  197,  197,
++      198,  197,  197,  197,   14,  199,  200,  201,  199,  202,
++      197,  197,   19,   18,   19,  197,   19,   19,   19,   19,
++       18,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,  186,  190,  191,   19,   19,   19,   19,   19,   19,
++       19,   19,   19,   19,   19,   19,  197,  201,  202,   19,
+        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,   19,   19,   19,   19,  186,
++       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
++       19,   19,   19,   19,   19,   19,   19,   19,  197,   19,
+        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,  186,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,   19,   19,   19,  186,   19,
++       19,  197,   19,   19,   19,   19,   19,   19,   19,   19,
++       19,   19,   19,   19,   19,   19,   19,   19,   19,  197,
+        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,  186,   19,   19,   19,   19,
++       19,   19,   19,   19,   19,   19,  197,   19,   19,   19,
+        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,    0,  186,  186,  186,  186,
 -      186
++       19,   19,   19,   19,   19,   19,    0,  197,  197,  197,
++      197,  197
      } ;
  
- static yyconst flex_uint16_t yy_nxt[325] =
 -static yyconst flex_uint16_t yy_nxt[341] =
++static yyconst flex_uint16_t yy_nxt[356] =
      {   0,
          4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-        14,   14,   14,   15,   16,   17,   18,   18,   19,   20,
-         4,   21,   17,   22,   23,   24,   17,   25,   26,   27,
-        18,   28,   29,   30,   31,   32,   33,   34,   35,   18,
-        18,   36,   41,   41,   41,   41,   42,   43,   43,   43,
-        43,   44,  172,   45,   55,   46,   56,   68,   79,   45,
-        45,   45,   45,   45,   45,   57,   83,   66,   62,   80,
-        58,   67,  171,   69,   63,  172,   71,   72,   46,   50,
-        50,   64,  123,  124,  170,   51,  169,   52,   52,   52,
-        52,   44,  168,   52,   53,   53,  167,   54,   51,   52,
-        52,   52,   52,   52,   52,   53,   53,   53,   53,   53,
-        53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-        53,   53,   53,   53,  172,   73,   53,  172,  156,  157,
-        74,   76,   53,   53,   53,   53,   53,   53,   77,   50,
-        50,   78,   41,   41,   41,   41,   82,   82,   82,   82,
-       172,  172,  172,  131,  131,  131,  131,   54,  111,   82,
-        82,   82,   82,  147,  131,  131,  131,  131,  166,  172,
-       162,  162,  162,  162,  162,  162,  162,  162,   39,  165,
-        39,   39,   39,   47,   47,   45,   45,   84,   84,   84,
-       164,  163,  161,  160,  159,  158,  155,  154,  153,  152,
-       151,  150,  149,  148,  146,  145,  144,  143,  142,  141,
-       140,  139,  138,  137,  136,  135,  134,  133,  132,  130,
-       129,  128,  127,  126,  125,  122,  121,  120,  119,  118,
-       117,  116,  115,  114,  113,  112,  110,  109,  108,  107,
-       106,  105,  104,  103,  102,  101,  100,   99,   98,   97,
-        96,   95,   94,   93,   92,   91,   90,   89,   88,   87,
-        86,   85,   48,   44,   48,   40,   38,   37,   81,   75,
-        70,   65,   61,   60,   59,   49,   48,   40,   38,   37,
-       172,    3,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172
+        14,   15,   15,   15,   16,   17,   18,   19,   19,   20,
 -       21,    4,   22,   18,   23,   24,   25,   26,   27,   19,
 -       19,   28,   29,   30,   31,   32,   33,   34,   35,   19,
 -       36,   19,   37,   42,   42,   42,   42,   43,   44,   44,
 -       44,   44,   45,  186,   46,   56,   47,   57,   61,   68,
 -       46,   46,   46,   46,   46,   58,   62,   71,   72,   73,
 -       59,  186,   64,   74,   69,   76,  186,   65,   78,   47,
 -       51,   51,  123,  124,   66,   77,   83,   52,   79,   53,
 -       53,   53,   53,   45,  186,   53,   54,   54,  185,   55,
 -
 -       52,   53,   53,   53,   53,   53,   54,   54,   54,   54,
 -       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
 -       54,   54,   54,   54,   54,   54,  186,  184,   54,   42,
 -       42,   42,   42,  183,   54,   54,   54,   54,   54,   82,
 -       82,   82,   82,   51,   51,  186,  186,  110,   82,   82,
 -       82,   82,  132,  132,  132,  132,  149,  132,  132,  132,
 -      132,  182,   55,  181,  186,  159,  160,  166,  166,  166,
 -      166,  166,  166,  166,  166,  186,  186,  180,  179,  177,
 -      176,  175,  174,  173,  172,  171,  170,  169,  168,  167,
 -      165,  164,  163,  162,  186,  161,  158,  157,  178,   40,
 -
 -      156,   40,   40,   40,   48,   48,   46,   46,   84,   84,
 -       84,  155,  154,  153,  152,  151,  150,  148,  147,  146,
 -      145,  144,  143,  142,  141,  140,  139,  138,  137,  136,
 -      135,  134,  133,  131,  130,  129,  128,  127,  126,  125,
 -      122,  121,  120,  119,  118,  117,  116,  115,  114,  113,
 -      112,  111,  109,  108,  107,  106,  105,  104,  103,  102,
++       21,    4,   22,   18,   23,   24,   25,   18,   26,   27,
++       28,   19,   29,   30,   31,   32,   33,   34,   35,   36,
++       19,   37,   19,   38,   43,   43,   43,   43,   44,   45,
++       45,   45,   45,   46,  197,   47,   57,   48,   58,   61,
++       63,   47,   47,   47,   47,   47,   47,   59,   64,   70,
++       72,   66,   60,   71,   88,   62,   83,   67,  197,   75,
++       76,   48,   52,   52,   68,   77,   73,   84,  196,   53,
++       78,   54,   54,   54,   54,   46,  195,   54,   55,   55,
++
++      194,   56,   53,   54,   54,   54,   54,   54,   54,   55,
++       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
++       55,   55,   55,   55,   55,   55,   55,   55,   55,  197,
++      197,   55,   43,   43,   43,   43,   80,   55,   55,   55,
++       55,   55,   55,   81,   52,   52,   82,   87,   87,   87,
++       87,  197,  197,  193,  197,  119,   87,   87,   87,   87,
++      133,  134,  192,   56,  142,  142,  142,  142,  170,  171,
++      197,  160,  142,  142,  142,  142,  177,  177,  177,  177,
++      177,  177,  177,  177,  197,  197,  191,  190,  188,  187,
++      186,  185,  184,  183,  182,  181,  180,  179,  178,  176,
++
++      175,  174,  173,  197,  172,  169,  168,  189,   41,  167,
++       41,   41,   41,   49,   49,   47,   47,   89,   89,   89,
++      166,  165,  164,  163,  162,  161,  159,  158,  157,  156,
++      155,  154,  153,  152,  151,  150,  149,  148,  147,  146,
++      145,  144,  143,  141,  140,  139,  138,  137,  136,  135,
++      132,  131,  130,  129,  128,  127,  126,  125,  124,  123,
++      122,  121,  120,  118,  117,  116,  115,  114,  113,  112,
++      111,  110,  109,  108,  107,  106,  105,  104,  103,  102,
+       101,  100,   99,   98,   97,   96,   95,   94,   93,   92,
 -       91,   90,   89,   88,   87,   86,   85,   49,   45,   49,
 -       41,   39,   38,   81,   80,   75,   70,   67,   63,   60,
 -       50,   49,   41,   39,   38,  186,    3,  186,  186,  186,
 -
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186
++       91,   90,   50,   46,   50,   42,   40,   39,   86,   85,
++
++       79,   74,   69,   65,   51,   50,   42,   40,   39,  197,
++        3,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197
      } ;
  
- static yyconst flex_int16_t yy_chk[325] =
 -static yyconst flex_int16_t yy_chk[341] =
++static yyconst flex_int16_t yy_chk[356] =
      {   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,    1,    1,
-         1,    1,   11,   11,   11,   11,   13,   13,   13,   13,
-        13,   13,   14,   13,   21,   13,   21,   29,   35,   13,
-        13,   13,   13,   13,   13,   22,  176,   28,   26,   35,
-        22,   28,  170,   29,   26,   14,   31,   31,   13,   17,
-        17,   26,  103,  103,  166,   17,  165,   17,   17,   17,
-        17,   17,  163,   17,   17,   17,  160,   17,   17,   17,
-        17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-        17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-        18,   18,   18,   18,   18,   32,   18,   43,  142,  142,
-        32,   34,   18,   18,   18,   18,   18,   18,   34,   50,
-        50,   34,   41,   41,   41,   41,   42,   42,   42,   42,
-        43,   51,   51,  111,  111,  111,  111,   50,   82,   82,
-        82,   82,   82,  131,  131,  131,  131,  131,  159,   51,
-       147,  147,  147,  147,  162,  162,  162,  162,  173,  155,
-       173,  173,  173,  174,  174,  175,  175,  177,  177,  177,
-       153,  152,  146,  145,  144,  143,  141,  140,  139,  138,
-       135,  134,  133,  132,  130,  129,  127,  126,  125,  122,
-       121,  120,  119,  118,  117,  115,  114,  113,  112,  110,
-       109,  108,  107,  105,  104,  102,  101,   99,   97,   95,
-        94,   93,   91,   90,   88,   87,   81,   80,   79,   78,
-        77,   76,   75,   74,   73,   71,   70,   69,   68,   67,
-        66,   65,   64,   63,   62,   61,   60,   59,   58,   57,
-        56,   55,   47,   45,   44,   39,   38,   37,   36,   33,
-        30,   27,   25,   24,   23,   16,   15,    7,    6,    5,
-         3,  172,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172,  172,  172,  172,  172,  172,  172,
 -        1,    1,    1,   12,   12,   12,   12,   14,   14,   14,
 -       14,   14,   14,   15,   14,   22,   14,   22,   25,   29,
 -       14,   14,   14,   14,   14,   23,   25,   31,   31,   32,
 -       23,   44,   27,   32,   29,   34,   15,   27,   35,   14,
 -       18,   18,  102,  102,   27,   34,  190,   18,   35,   18,
 -       18,   18,   18,   18,   44,   18,   18,   18,  184,   18,
--
-       172,  172,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172,  172,  172,  172,  172,  172,  172,
-       172,  172,  172,  172
++        1,    1,    1,    1,   12,   12,   12,   12,   14,   14,
++       14,   14,   14,   14,   15,   14,   22,   14,   22,   24,
++       25,   14,   14,   14,   14,   14,   14,   23,   25,   29,
++       30,   27,   23,   29,  201,   24,   36,   27,   15,   32,
++       32,   14,   18,   18,   27,   33,   30,   36,  195,   18,
++       33,   18,   18,   18,   18,   18,  194,   18,   18,   18,
++
++      192,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 -       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
 -       18,   18,   19,   19,   19,   19,   19,  183,   19,   42,
 -       42,   42,   42,  181,   19,   19,   19,   19,   19,   43,
 -       43,   43,   43,   51,   51,   52,   52,   82,   82,   82,
 -       82,   82,  110,  110,  110,  110,  132,  132,  132,  132,
 -      132,  179,   51,  178,   52,  143,  143,  149,  149,  149,
 -      149,  166,  166,  166,  166,  173,  173,  177,  174,  171,
 -      170,  168,  167,  164,  163,  162,  158,  156,  155,  152,
 -      148,  147,  146,  145,  173,  144,  142,  141,  173,  187,
 -
 -      140,  187,  187,  187,  188,  188,  189,  189,  191,  191,
 -      191,  139,  137,  136,  135,  134,  133,  131,  130,  129,
 -      127,  126,  125,  122,  121,  120,  119,  118,  116,  115,
 -      114,  112,  111,  109,  108,  107,  106,  105,  104,  103,
 -      101,  100,   98,   96,   95,   94,   92,   91,   90,   89,
 -       88,   87,   81,   80,   79,   78,   77,   76,   75,   74,
 -       73,   71,   70,   69,   68,   67,   66,   65,   64,   63,
 -       62,   61,   60,   59,   58,   57,   56,   48,   46,   45,
 -       40,   39,   38,   37,   36,   33,   30,   28,   26,   24,
 -       17,   16,    7,    6,    5,    3,  186,  186,  186,  186,
 -
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186,
 -      186,  186,  186,  186,  186,  186,  186,  186,  186,  186
++       18,   18,   18,   18,   18,   19,   19,   19,   19,   19,
++       45,   19,   43,   43,   43,   43,   35,   19,   19,   19,
++       19,   19,   19,   35,   52,   52,   35,   44,   44,   44,
++       44,   53,   53,  190,   45,   87,   87,   87,   87,   87,
++      110,  110,  189,   52,  119,  119,  119,  119,  154,  154,
++       53,  142,  142,  142,  142,  142,  160,  160,  160,  160,
++      177,  177,  177,  177,  184,  184,  188,  185,  182,  181,
++      179,  178,  175,  174,  173,  169,  167,  166,  163,  159,
++
++      158,  157,  156,  184,  155,  153,  152,  184,  198,  151,
++      198,  198,  198,  199,  199,  200,  200,  202,  202,  202,
++      150,  147,  146,  145,  144,  143,  141,  140,  139,  137,
++      136,  135,  132,  131,  130,  129,  128,  127,  125,  124,
++      123,  121,  120,  118,  117,  116,  115,  114,  112,  111,
++      109,  108,  106,  104,  102,  101,  100,   98,   97,   96,
++       94,   93,   92,   86,   85,   84,   83,   82,   81,   80,
++       79,   78,   77,   75,   74,   73,   72,   71,   70,   69,
++       68,   67,   66,   65,   64,   63,   62,   61,   60,   59,
++       58,   57,   49,   47,   46,   41,   40,   39,   38,   37,
++
++       34,   31,   28,   26,   17,   16,    7,    6,    5,    3,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197,  197,  197,  197,  197,  197,
++      197,  197,  197,  197,  197
      } ;
  
  /* Table of booleans, true if rule could match eol. */
--static yyconst flex_int32_t yy_rule_can_match_eol[47] =
++static yyconst flex_int32_t yy_rule_can_match_eol[52] =
      {   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, 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[46] =
++static yyconst flex_int16_t yy_rule_linenum[51] =
      {   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,  161,  162,  163,  164,  165,
 -      166,  167,  168,  169,  170,  171,  172,  174,  175,  176,
 -      177,  178,  179,  180,  182
 +      166,  167,  168,  169,  170,  171,  172,  173,  174,  175,
-       176,  177,  178,  179,  181
++      176,  177,  178,  179,  180,  181,  182,  183,  184,  185
      } ;
  
  static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@@ -808,7 -819,7 +828,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 812 "lexer.cc"
 -#line 823 "lexer.cc"
++#line 832 "lexer.cc"
  
  #define INITIAL 0
  
@@@ -1105,7 -1116,7 +1125,7 @@@ YY_DEC
      loc.step();
  
  
- #line 1109 "lexer.cc"
 -#line 1120 "lexer.cc"
++#line 1129 "lexer.cc"
  
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@@ -1133,14 -1144,14 +1153,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 >= 173 )
 -                              if ( yy_current_state >= 187 )
++                              if ( yy_current_state >= 198 )
                                        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 != 172 );
 -              while ( yy_current_state != 186 );
++              while ( yy_current_state != 197 );
  
  yy_find_action:
  /* %% [10.0] code to find the action number goes here */
@@@ -1203,13 -1214,13 +1223,13 @@@ do_action:   /* This label is used only t
                        {
                        if ( yy_act == 0 )
                                fprintf( stderr, "--scanner backing up\n" );
--                      else if ( yy_act < 46 )
++                      else if ( yy_act < 51 )
                                fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
                                         (long)yy_rule_linenum[yy_act], yytext );
--                      else if ( yy_act == 46 )
++                      else if ( yy_act == 51 )
                                fprintf( stderr, "--accepting default rule (\"%s\")\n",
                                         yytext );
--                      else if ( yy_act == 47 )
++                      else if ( yy_act == 52 )
                                fprintf( stderr, "--(end of buffer or a NUL)\n" );
                        else
                                fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@@ -1431,78 -1442,78 +1451,103 @@@ return isc::eval::EvalParser::make_TRAN
  case 33:
  YY_RULE_SETUP
  #line 168 "lexer.ll"
- return isc::eval::EvalParser::make_SUBSTRING(loc);
 -return isc::eval::EvalParser::make_RPAREN(loc);
++return isc::eval::EvalParser::make_VENDOR(loc);
        YY_BREAK
  case 34:
  YY_RULE_SETUP
  #line 169 "lexer.ll"
- return isc::eval::EvalParser::make_ALL(loc);
 -return isc::eval::EvalParser::make_LBRACKET(loc);
++return isc::eval::EvalParser::make_VENDOR_CLASS(loc);
        YY_BREAK
  case 35:
  YY_RULE_SETUP
  #line 170 "lexer.ll"
- return isc::eval::EvalParser::make_CONCAT(loc);
 -return isc::eval::EvalParser::make_RBRACKET(loc);
++return isc::eval::EvalParser::make_DATA(loc);
        YY_BREAK
  case 36:
  YY_RULE_SETUP
  #line 171 "lexer.ll"
- return isc::eval::EvalParser::make_NOT(loc);
 -return isc::eval::EvalParser::make_COMA(loc);
++return isc::eval::EvalParser::make_ENTERPRISE(loc);
        YY_BREAK
  case 37:
  YY_RULE_SETUP
  #line 172 "lexer.ll"
- return isc::eval::EvalParser::make_AND(loc);
 -return isc::eval::EvalParser::make_ANY(loc);
++return isc::eval::EvalParser::make_SUBSTRING(loc);
        YY_BREAK
  case 38:
  YY_RULE_SETUP
 -#line 174 "lexer.ll"
 -return isc::eval::EvalParser::make_PKT6(loc);
 +#line 173 "lexer.ll"
- return isc::eval::EvalParser::make_OR(loc);
++return isc::eval::EvalParser::make_ALL(loc);
        YY_BREAK
  case 39:
  YY_RULE_SETUP
 -#line 175 "lexer.ll"
 -return isc::eval::EvalParser::make_MSGTYPE(loc);
 +#line 174 "lexer.ll"
- return isc::eval::EvalParser::make_DOT(loc);
++return isc::eval::EvalParser::make_CONCAT(loc);
        YY_BREAK
  case 40:
  YY_RULE_SETUP
 -#line 176 "lexer.ll"
 -return isc::eval::EvalParser::make_TRANSID(loc);
 +#line 175 "lexer.ll"
- return isc::eval::EvalParser::make_LPAREN(loc);
++return isc::eval::EvalParser::make_NOT(loc);
        YY_BREAK
  case 41:
  YY_RULE_SETUP
 -#line 177 "lexer.ll"
 -return isc::eval::EvalParser::make_VENDOR(loc);
 +#line 176 "lexer.ll"
- return isc::eval::EvalParser::make_RPAREN(loc);
++return isc::eval::EvalParser::make_AND(loc);
        YY_BREAK
  case 42:
  YY_RULE_SETUP
 -#line 178 "lexer.ll"
 -return isc::eval::EvalParser::make_VENDOR_CLASS(loc);
 +#line 177 "lexer.ll"
- return isc::eval::EvalParser::make_LBRACKET(loc);
++return isc::eval::EvalParser::make_OR(loc);
        YY_BREAK
  case 43:
  YY_RULE_SETUP
 -#line 179 "lexer.ll"
 -return isc::eval::EvalParser::make_DATA(loc);
 +#line 178 "lexer.ll"
- return isc::eval::EvalParser::make_RBRACKET(loc);
++return isc::eval::EvalParser::make_DOT(loc);
        YY_BREAK
  case 44:
  YY_RULE_SETUP
 -#line 180 "lexer.ll"
 -return isc::eval::EvalParser::make_ENTERPRISE(loc);
 +#line 179 "lexer.ll"
- return isc::eval::EvalParser::make_COMA(loc);
++return isc::eval::EvalParser::make_LPAREN(loc);
        YY_BREAK
  case 45:
  YY_RULE_SETUP
++#line 180 "lexer.ll"
++return isc::eval::EvalParser::make_RPAREN(loc);
++      YY_BREAK
++case 46:
++YY_RULE_SETUP
 +#line 181 "lexer.ll"
++return isc::eval::EvalParser::make_LBRACKET(loc);
++      YY_BREAK
++case 47:
++YY_RULE_SETUP
+ #line 182 "lexer.ll"
++return isc::eval::EvalParser::make_RBRACKET(loc);
++      YY_BREAK
++case 48:
++YY_RULE_SETUP
++#line 183 "lexer.ll"
++return isc::eval::EvalParser::make_COMA(loc);
++      YY_BREAK
++case 49:
++YY_RULE_SETUP
++#line 184 "lexer.ll"
++return isc::eval::EvalParser::make_ANY(loc);
++      YY_BREAK
++case 50:
++YY_RULE_SETUP
++#line 185 "lexer.ll"
  driver.error (loc, "Invalid character: " + std::string(yytext));
        YY_BREAK
  case YY_STATE_EOF(INITIAL):
- #line 182 "lexer.ll"
 -#line 183 "lexer.ll"
++#line 186 "lexer.ll"
  return isc::eval::EvalParser::make_END(loc);
        YY_BREAK
--case 46:
++case 51:
  YY_RULE_SETUP
- #line 183 "lexer.ll"
 -#line 184 "lexer.ll"
++#line 187 "lexer.ll"
  ECHO;
        YY_BREAK
- #line 1506 "lexer.cc"
 -#line 1517 "lexer.cc"
++#line 1551 "lexer.cc"
  
        case YY_END_OF_BUFFER:
                {
@@@ -1787,7 -1798,7 +1832,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 >= 173 )
 -                      if ( yy_current_state >= 187 )
++                      if ( yy_current_state >= 198 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
        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 >= 173 )
 -              if ( yy_current_state >= 187 )
++              if ( yy_current_state >= 198 )
                        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 == 172);
 -      yy_is_jam = (yy_current_state == 186);
++      yy_is_jam = (yy_current_state == 197);
        if ( ! yy_is_jam )
                *(yy_state_ptr)++ = yy_current_state;
  
@@@ -2585,7 -2596,7 +2630,7 @@@ void yyfree (void * ptr 
  
  /* %ok-for-header */
  
- #line 183 "lexer.ll"
 -#line 184 "lexer.ll"
++#line 187 "lexer.ll"
  
  
  
index f7e489b33965069b89b09de9bb6f6624f0087414,7cb52ee349fbc2b078e30764eb83dbcb5523add1..fdefcecd6386a4c84ec26477eb8e796962b649e9
@@@ -140,46 -140,47 +140,50 @@@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a
      return isc::eval::EvalParser::make_IP_ADDRESS(yytext, loc);
  }
  
- "=="        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);
- "pkt"       return isc::eval::EvalParser::make_PKT(loc);
- "iface"     return isc::eval::EvalParser::make_IFACE(loc);
- "src"       return isc::eval::EvalParser::make_SRC(loc);
- "dst"       return isc::eval::EvalParser::make_DST(loc);
- "len"       return isc::eval::EvalParser::make_LEN(loc);
- "pkt4"      return isc::eval::EvalParser::make_PKT4(loc);
- "mac"       return isc::eval::EvalParser::make_CHADDR(loc);
- "hlen"      return isc::eval::EvalParser::make_HLEN(loc);
- "htype"     return isc::eval::EvalParser::make_HTYPE(loc);
- "ciaddr"    return isc::eval::EvalParser::make_CIADDR(loc);
- "giaddr"    return isc::eval::EvalParser::make_GIADDR(loc);
- "yiaddr"    return isc::eval::EvalParser::make_YIADDR(loc);
- "siaddr"    return isc::eval::EvalParser::make_SIADDR(loc);
- "pkt6"      return isc::eval::EvalParser::make_PKT6(loc);
- "msgtype"   return isc::eval::EvalParser::make_MSGTYPE(loc);
- "transid"   return isc::eval::EvalParser::make_TRANSID(loc);
- "substring" return isc::eval::EvalParser::make_SUBSTRING(loc);
- "all"       return isc::eval::EvalParser::make_ALL(loc);
- "concat"    return isc::eval::EvalParser::make_CONCAT(loc);
- "not"       return isc::eval::EvalParser::make_NOT(loc);
- "and"       return isc::eval::EvalParser::make_AND(loc);
- "or"        return isc::eval::EvalParser::make_OR(loc);
- "."         return isc::eval::EvalParser::make_DOT(loc);
- "("         return isc::eval::EvalParser::make_LPAREN(loc);
- ")"         return isc::eval::EvalParser::make_RPAREN(loc);
- "["         return isc::eval::EvalParser::make_LBRACKET(loc);
- "]"         return isc::eval::EvalParser::make_RBRACKET(loc);
- ","         return isc::eval::EvalParser::make_COMA(loc);
+ "=="           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);
++"pkt"          return isc::eval::EvalParser::make_PKT(loc);
++"iface"        return isc::eval::EvalParser::make_IFACE(loc);
++"src"          return isc::eval::EvalParser::make_SRC(loc);
++"dst"          return isc::eval::EvalParser::make_DST(loc);
++"len"          return isc::eval::EvalParser::make_LEN(loc);
+ "pkt4"         return isc::eval::EvalParser::make_PKT4(loc);
+ "mac"          return isc::eval::EvalParser::make_CHADDR(loc);
+ "hlen"         return isc::eval::EvalParser::make_HLEN(loc);
+ "htype"        return isc::eval::EvalParser::make_HTYPE(loc);
+ "ciaddr"       return isc::eval::EvalParser::make_CIADDR(loc);
+ "giaddr"       return isc::eval::EvalParser::make_GIADDR(loc);
+ "yiaddr"       return isc::eval::EvalParser::make_YIADDR(loc);
+ "siaddr"       return isc::eval::EvalParser::make_SIADDR(loc);
++"pkt6"         return isc::eval::EvalParser::make_PKT6(loc);
++"msgtype"      return isc::eval::EvalParser::make_MSGTYPE(loc);
++"transid"      return isc::eval::EvalParser::make_TRANSID(loc);
++"vendor"       return isc::eval::EvalParser::make_VENDOR(loc);
++"vendor-class" return isc::eval::EvalParser::make_VENDOR_CLASS(loc);
++"data"         return isc::eval::EvalParser::make_DATA(loc);
++"enterprise"   return isc::eval::EvalParser::make_ENTERPRISE(loc);
+ "substring"    return isc::eval::EvalParser::make_SUBSTRING(loc);
+ "all"          return isc::eval::EvalParser::make_ALL(loc);
+ "concat"       return isc::eval::EvalParser::make_CONCAT(loc);
+ "not"          return isc::eval::EvalParser::make_NOT(loc);
+ "and"          return isc::eval::EvalParser::make_AND(loc);
+ "or"           return isc::eval::EvalParser::make_OR(loc);
+ "."            return isc::eval::EvalParser::make_DOT(loc);
+ "("            return isc::eval::EvalParser::make_LPAREN(loc);
+ ")"            return isc::eval::EvalParser::make_RPAREN(loc);
+ "["            return isc::eval::EvalParser::make_LBRACKET(loc);
+ "]"            return isc::eval::EvalParser::make_RBRACKET(loc);
+ ","            return isc::eval::EvalParser::make_COMA(loc);
+ "*"            return isc::eval::EvalParser::make_ANY(loc);
 -
 -"pkt6"         return isc::eval::EvalParser::make_PKT6(loc);
 -"msgtype"      return isc::eval::EvalParser::make_MSGTYPE(loc);
 -"transid"      return isc::eval::EvalParser::make_TRANSID(loc);
 -"vendor"       return isc::eval::EvalParser::make_VENDOR(loc);
 -"vendor-class" return isc::eval::EvalParser::make_VENDOR_CLASS(loc);
 -"data"         return isc::eval::EvalParser::make_DATA(loc);
 -"enterprise"   return isc::eval::EvalParser::make_ENTERPRISE(loc);
 -
 -.              driver.error (loc, "Invalid character: " + std::string(yytext));
 -<<EOF>>        return isc::eval::EvalParser::make_END(loc);
 +.          driver.error (loc, "Invalid character: " + std::string(yytext));
 +<<EOF>>    return isc::eval::EvalParser::make_END(loc);
  %%
  
  using namespace isc::eval;
index fdcbab31c958b196853f47f6edb5567bade68c50,542df8239487a634d262f996e5c8bd19830be56c..8504c3d485adb1b7690da5d0c315e2f4aaf7661a
@@@ -251,39 -251,39 +251,43 @@@ namespace isc { namespace eval 
    {
        switch (that.type_get ())
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          value.move< TokenOption::RepresentationType > (that.value);
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          value.move< TokenPkt4::FieldType > (that.value);
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          value.move< TokenPkt6::FieldType > (that.value);
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        value.move< TokenPkt::MetadataType > (that.value);
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          value.move< TokenRelay6Field::FieldType > (that.value);
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          value.move< std::string > (that.value);
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          value.move< uint16_t > (that.value);
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         value.move< uint32_t > (that.value);
+         break;
+       case 56: // nest_level
          value.move< uint8_t > (that.value);
          break;
  
      state = that.state;
        switch (that.type_get ())
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          value.copy< TokenOption::RepresentationType > (that.value);
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          value.copy< TokenPkt4::FieldType > (that.value);
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          value.copy< TokenPkt6::FieldType > (that.value);
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        value.copy< TokenPkt::MetadataType > (that.value);
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          value.copy< TokenRelay6Field::FieldType > (that.value);
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          value.copy< std::string > (that.value);
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          value.copy< uint16_t > (that.value);
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         value.copy< uint32_t > (that.value);
+         break;
+       case 56: // nest_level
          value.copy< uint8_t > (that.value);
          break;
  
          << yysym.location << ": ";
      switch (yytype)
      {
--            case 40: // "constant string"
++            case 45: // "constant string"
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
--#line 382 "parser.cc" // lalr1.cc:636
++#line 390 "parser.cc" // lalr1.cc:636
          break;
  
--      case 41: // "integer"
++      case 46: // "integer"
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
--#line 389 "parser.cc" // lalr1.cc:636
++#line 397 "parser.cc" // lalr1.cc:636
          break;
  
--      case 42: // "constant hexstring"
++      case 47: // "constant hexstring"
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
--#line 396 "parser.cc" // lalr1.cc:636
++#line 404 "parser.cc" // lalr1.cc:636
          break;
  
--      case 43: // "option name"
++      case 48: // "option name"
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
--#line 403 "parser.cc" // lalr1.cc:636
++#line 411 "parser.cc" // lalr1.cc:636
          break;
  
--      case 44: // "ip address"
++      case 49: // "ip address"
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
--#line 410 "parser.cc" // lalr1.cc:636
++#line 418 "parser.cc" // lalr1.cc:636
          break;
  
--      case 49: // option_code
++      case 54: // option_code
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< uint16_t > (); }
--#line 417 "parser.cc" // lalr1.cc:636
++#line 425 "parser.cc" // lalr1.cc:636
          break;
  
--      case 50: // option_repr_type
++      case 55: // option_repr_type
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
--#line 424 "parser.cc" // lalr1.cc:636
++#line 432 "parser.cc" // lalr1.cc:636
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 56: // nest_level
  
--#line 97 "parser.yy" // lalr1.cc:636
 -        { yyoutput << yysym.value.template as< uint32_t > (); }
 -#line 431 "parser.cc" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< uint8_t > (); }
- #line 431 "parser.cc" // lalr1.cc:636
++#line 439 "parser.cc" // lalr1.cc:636
          break;
  
-       case 52: // pkt_metadata
 -      case 52: // pkt4_field
++      case 57: // pkt_metadata
  
--#line 97 "parser.yy" // lalr1.cc:636
 -        { yyoutput << yysym.value.template as< TokenPkt4::FieldType > (); }
 -#line 438 "parser.cc" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< TokenPkt::MetadataType > (); }
- #line 438 "parser.cc" // lalr1.cc:636
++#line 446 "parser.cc" // lalr1.cc:636
          break;
  
-       case 53: // pkt4_field
 -      case 55: // relay6_field
++      case 58: // enterprise_id
  
--#line 97 "parser.yy" // lalr1.cc:636
 -        { yyoutput << yysym.value.template as< TokenRelay6Field::FieldType > (); }
 -#line 445 "parser.cc" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
++        { yyoutput << yysym.value.template as< uint32_t > (); }
++#line 453 "parser.cc" // lalr1.cc:636
+         break;
 -      case 56: // nest_level
++      case 59: // pkt4_field
 -#line 97 "parser.yy" // lalr1.cc:636
 -        { yyoutput << yysym.value.template as< uint8_t > (); }
 -#line 452 "parser.cc" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< TokenPkt4::FieldType > (); }
- #line 445 "parser.cc" // lalr1.cc:636
++#line 460 "parser.cc" // lalr1.cc:636
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
  
--#line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< TokenPkt6::FieldType > (); }
- #line 452 "parser.cc" // lalr1.cc:636
 -#line 459 "parser.cc" // lalr1.cc:636
++#line 467 "parser.cc" // lalr1.cc:636
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
 +
- #line 97 "parser.yy" // lalr1.cc:636
++#line 103 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< TokenRelay6Field::FieldType > (); }
- #line 459 "parser.cc" // lalr1.cc:636
++#line 474 "parser.cc" // lalr1.cc:636
          break;
  
  
           when using variants.  */
          switch (yyr1_[yyn])
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          yylhs.value.build< TokenOption::RepresentationType > ();
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          yylhs.value.build< TokenPkt4::FieldType > ();
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          yylhs.value.build< TokenPkt6::FieldType > ();
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        yylhs.value.build< TokenPkt::MetadataType > ();
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          yylhs.value.build< TokenRelay6Field::FieldType > ();
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          yylhs.value.build< std::string > ();
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          yylhs.value.build< uint16_t > ();
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         yylhs.value.build< uint32_t > ();
+         break;
+       case 56: // nest_level
          yylhs.value.build< uint8_t > ();
          break;
  
            switch (yyn)
              {
    case 4:
--#line 111 "parser.yy" // lalr1.cc:859
++#line 117 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenNot());
                      ctx.expression.push_back(neg);
                  }
--#line 718 "parser.cc" // lalr1.cc:859
++#line 737 "parser.cc" // lalr1.cc:859
      break;
  
    case 5:
--#line 116 "parser.yy" // lalr1.cc:859
++#line 122 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenAnd());
                      ctx.expression.push_back(neg);
                  }
--#line 727 "parser.cc" // lalr1.cc:859
++#line 746 "parser.cc" // lalr1.cc:859
      break;
  
    case 6:
--#line 121 "parser.yy" // lalr1.cc:859
++#line 127 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenOr());
                      ctx.expression.push_back(neg);
                  }
--#line 736 "parser.cc" // lalr1.cc:859
++#line 755 "parser.cc" // lalr1.cc:859
      break;
  
    case 7:
--#line 126 "parser.yy" // lalr1.cc:859
++#line 132 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr eq(new TokenEqual());
                      ctx.expression.push_back(eq);
                  }
--#line 745 "parser.cc" // lalr1.cc:859
++#line 764 "parser.cc" // lalr1.cc:859
      break;
  
    case 8:
--#line 131 "parser.yy" // lalr1.cc:859
++#line 137 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
                      ctx.expression.push_back(opt);
                  }
--#line 754 "parser.cc" // lalr1.cc:859
++#line 773 "parser.cc" // lalr1.cc:859
      break;
  
    case 9:
--#line 136 "parser.yy" // lalr1.cc:859
++#line 142 "parser.yy" // lalr1.cc:859
      {
                     switch (ctx.getUniverse()) {
                     case Option::V4:
                         error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                     }
                  }
--#line 778 "parser.cc" // lalr1.cc:859
++#line 797 "parser.cc" // lalr1.cc:859
      break;
  
    case 10:
--#line 156 "parser.yy" // lalr1.cc:859
++#line 162 "parser.yy" // lalr1.cc:859
      {
                      switch (ctx.getUniverse()) {
                      case Option::V6:
                          error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
                      }
                  }
--#line 796 "parser.cc" // lalr1.cc:859
++#line 815 "parser.cc" // lalr1.cc:859
      break;
  
    case 11:
- #line 172 "parser.yy" // lalr1.cc:859
 -#line 170 "parser.yy" // lalr1.cc:859
++#line 176 "parser.yy" // lalr1.cc:859
+     {
 -              // Expression: vendor-class[1234].exists
 -              //
 -              // This token will find option 124 (DHCPv4) or 16 (DHCPv6), and will check
 -              // if enterprise-id equals specified value.
 -              TokenPtr exist(new TokenVendorClass(ctx.getUniverse(), yystack_[3].value.as< uint32_t > (), TokenOption::EXISTS));
 -              ctx.expression.push_back(exist);
 -          }
 -#line 809 "parser.cc" // lalr1.cc:859
++                  // Expression: vendor-class[1234].exists
++                  //
++                  // This token will find option 124 (DHCPv4) or 16 (DHCPv6),
++                  // and will check if enterprise-id equals specified value.
++                  TokenPtr exist(new TokenVendorClass(ctx.getUniverse(), yystack_[3].value.as< uint32_t > (), TokenOption::EXISTS));
++                  ctx.expression.push_back(exist);
++              }
++#line 828 "parser.cc" // lalr1.cc:859
+     break;
+   case 12:
 -#line 179 "parser.yy" // lalr1.cc:859
++#line 185 "parser.yy" // lalr1.cc:859
+     {
 -              // Expression: vendor[1234].exists
 -              //
 -              // This token will find option 125 (DHCPv4) or 17 (DHCPv6), and will check
 -              // if enterprise-id equals specified value.
 -              TokenPtr exist(new TokenVendor(ctx.getUniverse(), yystack_[3].value.as< uint32_t > (), TokenOption::EXISTS));
 -              ctx.expression.push_back(exist);
 -
 -          }
 -#line 823 "parser.cc" // lalr1.cc:859
++                  // Expression: vendor[1234].exists
++                  //
++                  // This token will find option 125 (DHCPv4) or 17 (DHCPv6),
++                  // and will check if enterprise-id equals specified value.
++                  TokenPtr exist(new TokenVendor(ctx.getUniverse(), yystack_[3].value.as< uint32_t > (), TokenOption::EXISTS));
++                  ctx.expression.push_back(exist);
++              }
++#line 841 "parser.cc" // lalr1.cc:859
+     break;
+   case 13:
 -#line 189 "parser.yy" // lalr1.cc:859
++#line 194 "parser.yy" // lalr1.cc:859
+     {
 -              // Expression vendor[1234].option[123].exists
 -              //
 -              // This token will check if specified vendor option exists, has specified
 -              // enterprise-id and if has specified suboption.
 -              TokenPtr exist(new TokenVendor(ctx.getUniverse(), yystack_[8].value.as< uint32_t > (), TokenOption::EXISTS, yystack_[3].value.as< uint16_t > ()));
 -              ctx.expression.push_back(exist);
 -          }
 -#line 836 "parser.cc" // lalr1.cc:859
++                  // Expression vendor[1234].option[123].exists
++                  //
++                  // This token will check if specified vendor option
++                  // exists, has specified enterprise-id and if has
++                  // specified suboption.
++                  TokenPtr exist(new TokenVendor(ctx.getUniverse(), yystack_[8].value.as< uint32_t > (), TokenOption::EXISTS, yystack_[3].value.as< uint16_t > ()));
++                  ctx.expression.push_back(exist);
++               }
++#line 855 "parser.cc" // lalr1.cc:859
+     break;
+   case 14:
 -#line 200 "parser.yy" // lalr1.cc:859
++#line 206 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(str);
                    }
- #line 805 "parser.cc" // lalr1.cc:859
 -#line 845 "parser.cc" // lalr1.cc:859
++#line 864 "parser.cc" // lalr1.cc:859
      break;
  
-   case 12:
- #line 177 "parser.yy" // lalr1.cc:859
+   case 15:
 -#line 205 "parser.yy" // lalr1.cc:859
++#line 211 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(hex);
                    }
- #line 814 "parser.cc" // lalr1.cc:859
 -#line 854 "parser.cc" // lalr1.cc:859
++#line 873 "parser.cc" // lalr1.cc:859
      break;
  
-   case 13:
- #line 182 "parser.yy" // lalr1.cc:859
+   case 16:
 -#line 210 "parser.yy" // lalr1.cc:859
++#line 216 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(ip);
                    }
- #line 823 "parser.cc" // lalr1.cc:859
 -#line 863 "parser.cc" // lalr1.cc:859
++#line 882 "parser.cc" // lalr1.cc:859
      break;
  
-   case 14:
- #line 187 "parser.yy" // lalr1.cc:859
+   case 17:
 -#line 215 "parser.yy" // lalr1.cc:859
++#line 221 "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 832 "parser.cc" // lalr1.cc:859
 -#line 872 "parser.cc" // lalr1.cc:859
++#line 891 "parser.cc" // lalr1.cc:859
      break;
  
-   case 15:
- #line 192 "parser.yy" // lalr1.cc:859
+   case 18:
 -#line 220 "parser.yy" // lalr1.cc:859
++#line 226 "parser.yy" // lalr1.cc:859
      {
                       switch (ctx.getUniverse()) {
                       case Option::V4:
                           error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                       }
                    }
- #line 856 "parser.cc" // lalr1.cc:859
 -#line 896 "parser.cc" // lalr1.cc:859
++#line 915 "parser.cc" // lalr1.cc:859
      break;
  
-   case 16:
- #line 213 "parser.yy" // lalr1.cc:859
+   case 19:
 -#line 241 "parser.yy" // lalr1.cc:859
++#line 247 "parser.yy" // lalr1.cc:859
      {
                       switch (ctx.getUniverse()) {
                       case Option::V6:
                           error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
                       }
                    }
- #line 874 "parser.cc" // lalr1.cc:859
 -#line 914 "parser.cc" // lalr1.cc:859
++#line 933 "parser.cc" // lalr1.cc:859
      break;
  
-   case 17:
- #line 228 "parser.yy" // lalr1.cc:859
+   case 20:
 -#line 256 "parser.yy" // lalr1.cc:859
++#line 262 "parser.yy" // lalr1.cc:859
 +    {
 +                      TokenPtr pkt_metadata(new TokenPkt(yystack_[0].value.as< TokenPkt::MetadataType > ()));
 +                      ctx.expression.push_back(pkt_metadata);
 +                  }
- #line 883 "parser.cc" // lalr1.cc:859
++#line 942 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 18:
- #line 233 "parser.yy" // lalr1.cc:859
++  case 21:
++#line 267 "parser.yy" // lalr1.cc:859
      {
                       switch (ctx.getUniverse()) {
 -                     case Option::V6:
 +                     case Option::V4:
                       {
 -                         TokenPtr relay6field(new TokenRelay6Field(yystack_[3].value.as< uint8_t > (), yystack_[0].value.as< TokenRelay6Field::FieldType > ()));
 -                         ctx.expression.push_back(relay6field);
 +                         TokenPtr pkt4_field(new TokenPkt4(yystack_[0].value.as< TokenPkt4::FieldType > ()));
 +                         ctx.expression.push_back(pkt4_field);
                           break;
                       }
 -                     case Option::V4:
 -                         // For now we only use relay6 in DHCPv6.
 -                         error(yystack_[5].location, "relay6 can only be used in DHCPv6.");
 +                     case Option::V6:
 +                         // For now we only use pkt4 in DHCPv4.
 +                         error(yystack_[2].location, "pkt4 can only be used in DHCPv4.");
                       }
                    }
- #line 901 "parser.cc" // lalr1.cc:859
 -#line 932 "parser.cc" // lalr1.cc:859
++#line 960 "parser.cc" // lalr1.cc:859
      break;
  
-   case 19:
- #line 247 "parser.yy" // lalr1.cc:859
 -  case 21:
 -#line 271 "parser.yy" // lalr1.cc:859
++  case 22:
++#line 281 "parser.yy" // lalr1.cc:859
      {
 -                      TokenPtr pkt4_field(new TokenPkt4(yystack_[0].value.as< TokenPkt4::FieldType > ()));
 -                      ctx.expression.push_back(pkt4_field);
 +                     switch (ctx.getUniverse()) {
 +                     case Option::V6:
 +                     {
 +                         TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
 +                         ctx.expression.push_back(pkt6_field);
 +                         break;
 +                     }
 +                     case Option::V4:
 +                         // For now we only use pkt6 in DHCPv6.
 +                         error(yystack_[2].location, "pkt6 can only be used in DHCPv6.");
 +                     }
                    }
- #line 919 "parser.cc" // lalr1.cc:859
 -#line 941 "parser.cc" // lalr1.cc:859
++#line 978 "parser.cc" // lalr1.cc:859
      break;
  
-   case 20:
- #line 261 "parser.yy" // lalr1.cc:859
 -  case 22:
 -#line 276 "parser.yy" // lalr1.cc:859
++  case 23:
++#line 295 "parser.yy" // lalr1.cc:859
      {
 -                      TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
 -                      ctx.expression.push_back(pkt6_field);
 +                     switch (ctx.getUniverse()) {
 +                     case Option::V6:
 +                     {
 +                         TokenPtr relay6field(new TokenRelay6Field(yystack_[3].value.as< uint8_t > (), yystack_[0].value.as< TokenRelay6Field::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 937 "parser.cc" // lalr1.cc:859
 -#line 950 "parser.cc" // lalr1.cc:859
++#line 996 "parser.cc" // lalr1.cc:859
      break;
  
-   case 21:
- #line 276 "parser.yy" // lalr1.cc:859
 -  case 23:
 -#line 281 "parser.yy" // lalr1.cc:859
++  case 24:
++#line 310 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr sub(new TokenSubstring());
                        ctx.expression.push_back(sub);
                    }
- #line 946 "parser.cc" // lalr1.cc:859
 -#line 959 "parser.cc" // lalr1.cc:859
++#line 1005 "parser.cc" // lalr1.cc:859
      break;
  
-   case 22:
- #line 281 "parser.yy" // lalr1.cc:859
 -  case 24:
 -#line 286 "parser.yy" // lalr1.cc:859
++  case 25:
++#line 315 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr conc(new TokenConcat());
                        ctx.expression.push_back(conc);
                    }
- #line 955 "parser.cc" // lalr1.cc:859
 -#line 968 "parser.cc" // lalr1.cc:859
 -    break;
 -
 -  case 25:
 -#line 291 "parser.yy" // lalr1.cc:859
 -    {
 -              // expression: vendor.enterprise
 -              //
 -              // This token will return enterprise-id number of received vendor option.
 -              TokenPtr vendor(new TokenVendor(ctx.getUniverse(), 0, TokenVendor::ENTERPRISE_ID));
 -              ctx.expression.push_back(vendor);
 -          }
 -#line 980 "parser.cc" // lalr1.cc:859
++#line 1014 "parser.cc" // lalr1.cc:859
      break;
  
-   case 23:
- #line 288 "parser.yy" // lalr1.cc:859
+   case 26:
 -#line 299 "parser.yy" // lalr1.cc:859
++#line 320 "parser.yy" // lalr1.cc:859
+     {
 -              // expression: vendor-class.enterprise
 -              //
 -              // This token will return enterprise-id number of received vendor class option.
 -              TokenPtr vendor(new TokenVendorClass(ctx.getUniverse(), 0,
 -                                                   TokenVendor::ENTERPRISE_ID));
 -              ctx.expression.push_back(vendor);
 -          }
 -#line 993 "parser.cc" // lalr1.cc:859
++                    // expression: vendor.enterprise
++                    //
++                    // This token will return enterprise-id number of
++                    // received vendor option.
++                    TokenPtr vendor(new TokenVendor(ctx.getUniverse(), 0, TokenVendor::ENTERPRISE_ID));
++                    ctx.expression.push_back(vendor);
++                }
++#line 1027 "parser.cc" // lalr1.cc:859
+     break;
+   case 27:
 -#line 308 "parser.yy" // lalr1.cc:859
++#line 329 "parser.yy" // lalr1.cc:859
+     {
 -              // expression: vendor[1234].option[56].exists
 -              // expression: vendor[1234].option[56].hex
 -              //
 -              // This token will search for vendor option with specified enterprise-id.
 -              // If found, will search for specified suboption and finally will return
 -              // if it exists ('exists') or its content ('hex')
 -              TokenPtr opt(new TokenVendor(ctx.getUniverse(), yystack_[8].value.as< uint32_t > (), yystack_[0].value.as< TokenOption::RepresentationType > (), yystack_[3].value.as< uint16_t > ()));
 -              ctx.expression.push_back(opt);
 -          }
 -#line 1008 "parser.cc" // lalr1.cc:859
++                    // expression: vendor-class.enterprise
++                    //
++                    // This token will return enterprise-id number of
++                    // received vendor class option.
++                    TokenPtr vendor(new TokenVendorClass(ctx.getUniverse(), 0,
++                                                         TokenVendor::ENTERPRISE_ID));
++                    ctx.expression.push_back(vendor);
++                }
++#line 1041 "parser.cc" // lalr1.cc:859
+     break;
+   case 28:
 -#line 319 "parser.yy" // lalr1.cc:859
++#line 339 "parser.yy" // lalr1.cc:859
+     {
 -              // expression: vendor-class[1234].data
 -              //
 -              // Vendor class option does not have suboptions, but chunks of data (typically 1,
 -              // but the option structure allows multiple of them). If chunk offset is not
 -              // specified, we assume the first (0th) is requested.
 -              TokenPtr vendor_class(new TokenVendorClass(ctx.getUniverse(), yystack_[3].value.as< uint32_t > (),
 -                                                         TokenVendor::DATA, 0));
 -              ctx.expression.push_back(vendor_class);
 -          }
 -#line 1023 "parser.cc" // lalr1.cc:859
++                    // This token will search for vendor option with
++                    // specified enterprise-id.  If found, will search
++                    // for specified suboption and finally will return
++                    // its content.
++                    TokenPtr opt(new TokenVendor(ctx.getUniverse(), yystack_[8].value.as< uint32_t > (), yystack_[0].value.as< TokenOption::RepresentationType > (), yystack_[3].value.as< uint16_t > ()));
++                    ctx.expression.push_back(opt);
++                }
++#line 1054 "parser.cc" // lalr1.cc:859
+     break;
+   case 29:
 -#line 330 "parser.yy" // lalr1.cc:859
++#line 348 "parser.yy" // lalr1.cc:859
+     {
 -              // expression: vendor-class[1234].data[5]
 -              //
 -              // Vendor class option does not have suboptions, but chunks of data (typically 1,
 -              // but the option structure allows multiple of them). This syntax specifies
 -              // which data chunk (tuple) we want.
 -              uint8_t index = ctx.convertUint8(yystack_[1].value.as< std::string > (), yystack_[1].location);
 -              TokenPtr vendor_class(new TokenVendorClass(ctx.getUniverse(), yystack_[6].value.as< uint32_t > (),
 -                                                         TokenVendor::DATA, index));
 -              ctx.expression.push_back(vendor_class);
 -          }
 -#line 1039 "parser.cc" // lalr1.cc:859
++                    // expression: vendor-class[1234].data
++                    //
++                    // Vendor class option does not have suboptions,
++                    // but chunks of data (typically 1, but the option
++                    // structure allows multiple of them). If chunk
++                    // offset is not specified, we assume the first (0th)
++                    // is requested.
++                    TokenPtr vendor_class(new TokenVendorClass(ctx.getUniverse(), yystack_[3].value.as< uint32_t > (),
++                                                               TokenVendor::DATA, 0));
++                    ctx.expression.push_back(vendor_class);
++                }
++#line 1071 "parser.cc" // lalr1.cc:859
+     break;
+   case 30:
 -#line 344 "parser.yy" // lalr1.cc:859
++#line 361 "parser.yy" // lalr1.cc:859
+     {
 -                     yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
 -                 }
 -#line 1047 "parser.cc" // lalr1.cc:859
++                    // expression: vendor-class[1234].data[5]
++                    //
++                    // Vendor class option does not have suboptions,
++                    // but chunks of data (typically 1, but the option
++                    // structure allows multiple of them). This syntax
++                    // specifies which data chunk (tuple) we want.
++                    uint8_t index = ctx.convertUint8(yystack_[1].value.as< std::string > (), yystack_[1].location);
++                    TokenPtr vendor_class(new TokenVendorClass(ctx.getUniverse(), yystack_[6].value.as< uint32_t > (),
++                                                               TokenVendor::DATA, index));
++                    ctx.expression.push_back(vendor_class);
++                }
++#line 1088 "parser.cc" // lalr1.cc:859
+     break;
+   case 31:
 -#line 348 "parser.yy" // lalr1.cc:859
++#line 376 "parser.yy" // lalr1.cc:859
      {
 -                     yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
 +                     yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
                   }
- #line 963 "parser.cc" // lalr1.cc:859
 -#line 1055 "parser.cc" // lalr1.cc:859
++#line 1096 "parser.cc" // lalr1.cc:859
      break;
  
-   case 24:
- #line 292 "parser.yy" // lalr1.cc:859
+   case 32:
 -#line 354 "parser.yy" // lalr1.cc:859
++#line 380 "parser.yy" // lalr1.cc:859
      {
 -                          yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
 -                      }
 -#line 1063 "parser.cc" // lalr1.cc:859
 +                     yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
 +                 }
- #line 971 "parser.cc" // lalr1.cc:859
++#line 1104 "parser.cc" // lalr1.cc:859
      break;
  
-   case 25:
- #line 298 "parser.yy" // lalr1.cc:859
+   case 33:
 -#line 358 "parser.yy" // lalr1.cc:859
++#line 386 "parser.yy" // lalr1.cc:859
      {
 -                          yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
 +                          yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                        }
- #line 979 "parser.cc" // lalr1.cc:859
 -#line 1071 "parser.cc" // lalr1.cc:859
++#line 1112 "parser.cc" // lalr1.cc:859
      break;
  
-   case 26:
- #line 302 "parser.yy" // lalr1.cc:859
+   case 34:
 -#line 364 "parser.yy" // lalr1.cc:859
++#line 390 "parser.yy" // lalr1.cc:859
      {
 -    yylhs.value.as< uint32_t > () = ctx.convertUint32(yystack_[0].value.as< std::string > (), yystack_[0].location);
 -}
 -#line 1079 "parser.cc" // lalr1.cc:859
 +                          yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
 +                      }
- #line 987 "parser.cc" // lalr1.cc:859
++#line 1120 "parser.cc" // lalr1.cc:859
      break;
  
-   case 27:
- #line 308 "parser.yy" // lalr1.cc:859
+   case 35:
 -#line 368 "parser.yy" // lalr1.cc:859
++#line 396 "parser.yy" // lalr1.cc:859
      {
 -    yylhs.value.as< uint32_t > () = 0;
 -}
 -#line 1087 "parser.cc" // lalr1.cc:859
 +                     yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location);
 +                 }
- #line 995 "parser.cc" // lalr1.cc:859
++#line 1128 "parser.cc" // lalr1.cc:859
      break;
  
-   case 28:
- #line 317 "parser.yy" // lalr1.cc:859
+   case 36:
 -#line 373 "parser.yy" // lalr1.cc:859
++#line 405 "parser.yy" // lalr1.cc:859
      {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CHADDR;
 -                }
 -#line 1095 "parser.cc" // lalr1.cc:859
 +                      yylhs.value.as< TokenPkt::MetadataType > () = TokenPkt::IFACE;
 +                  }
- #line 1003 "parser.cc" // lalr1.cc:859
++#line 1136 "parser.cc" // lalr1.cc:859
      break;
  
-   case 29:
- #line 321 "parser.yy" // lalr1.cc:859
+   case 37:
 -#line 377 "parser.yy" // lalr1.cc:859
++#line 409 "parser.yy" // lalr1.cc:859
      {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HLEN;
 -                }
 -#line 1103 "parser.cc" // lalr1.cc:859
 +                      yylhs.value.as< TokenPkt::MetadataType > () = TokenPkt::SRC;
 +                  }
- #line 1011 "parser.cc" // lalr1.cc:859
++#line 1144 "parser.cc" // lalr1.cc:859
      break;
  
-   case 30:
- #line 325 "parser.yy" // lalr1.cc:859
+   case 38:
 -#line 381 "parser.yy" // lalr1.cc:859
++#line 413 "parser.yy" // lalr1.cc:859
      {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HTYPE;
 -                }
 -#line 1111 "parser.cc" // lalr1.cc:859
 +                      yylhs.value.as< TokenPkt::MetadataType > () = TokenPkt::DST;
 +                  }
- #line 1019 "parser.cc" // lalr1.cc:859
++#line 1152 "parser.cc" // lalr1.cc:859
      break;
  
-   case 31:
- #line 329 "parser.yy" // lalr1.cc:859
+   case 39:
 -#line 385 "parser.yy" // lalr1.cc:859
++#line 417 "parser.yy" // lalr1.cc:859
      {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CIADDR;
 -                }
 -#line 1119 "parser.cc" // lalr1.cc:859
 +                      yylhs.value.as< TokenPkt::MetadataType > () = TokenPkt::LEN;
 +                  }
- #line 1027 "parser.cc" // lalr1.cc:859
++#line 1160 "parser.cc" // lalr1.cc:859
      break;
  
-   case 32:
- #line 335 "parser.yy" // lalr1.cc:859
+   case 40:
 -#line 389 "parser.yy" // lalr1.cc:859
++#line 423 "parser.yy" // lalr1.cc:859
+     {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::GIADDR;
 -                }
 -#line 1127 "parser.cc" // lalr1.cc:859
++                       yylhs.value.as< uint32_t > () = ctx.convertUint32(yystack_[0].value.as< std::string > (), yystack_[0].location);
++                   }
++#line 1168 "parser.cc" // lalr1.cc:859
+     break;
+   case 41:
 -#line 393 "parser.yy" // lalr1.cc:859
++#line 427 "parser.yy" // lalr1.cc:859
+     {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::YIADDR;
 -                }
 -#line 1135 "parser.cc" // lalr1.cc:859
++                       yylhs.value.as< uint32_t > () = 0;
++                   }
++#line 1176 "parser.cc" // lalr1.cc:859
+     break;
+   case 42:
 -#line 397 "parser.yy" // lalr1.cc:859
++#line 433 "parser.yy" // lalr1.cc:859
      {
 -                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::SIADDR;
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CHADDR;
                  }
- #line 1035 "parser.cc" // lalr1.cc:859
 -#line 1143 "parser.cc" // lalr1.cc:859
++#line 1184 "parser.cc" // lalr1.cc:859
      break;
  
-   case 33:
- #line 339 "parser.yy" // lalr1.cc:859
+   case 43:
 -#line 403 "parser.yy" // lalr1.cc:859
++#line 437 "parser.yy" // lalr1.cc:859
      {
 -                     TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
 -                     ctx.expression.push_back(str);
 -                 }
 -#line 1152 "parser.cc" // lalr1.cc:859
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HLEN;
 +                }
- #line 1043 "parser.cc" // lalr1.cc:859
++#line 1192 "parser.cc" // lalr1.cc:859
      break;
  
-   case 34:
- #line 343 "parser.yy" // lalr1.cc:859
+   case 44:
 -#line 410 "parser.yy" // lalr1.cc:859
++#line 441 "parser.yy" // lalr1.cc:859
      {
 -                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
 -                      ctx.expression.push_back(str);
 -                  }
 -#line 1161 "parser.cc" // lalr1.cc:859
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HTYPE;
 +                }
- #line 1051 "parser.cc" // lalr1.cc:859
++#line 1200 "parser.cc" // lalr1.cc:859
      break;
  
-   case 35:
- #line 347 "parser.yy" // lalr1.cc:859
+   case 45:
 -#line 415 "parser.yy" // lalr1.cc:859
++#line 445 "parser.yy" // lalr1.cc:859
      {
 -                     TokenPtr str(new TokenString("all"));
 -                     ctx.expression.push_back(str);
 -                 }
 -#line 1170 "parser.cc" // lalr1.cc:859
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CIADDR;
 +                }
- #line 1059 "parser.cc" // lalr1.cc:859
++#line 1208 "parser.cc" // lalr1.cc:859
      break;
  
-   case 36:
- #line 351 "parser.yy" // lalr1.cc:859
+   case 46:
 -#line 421 "parser.yy" // lalr1.cc:859
 -    { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR; }
 -#line 1176 "parser.cc" // lalr1.cc:859
++#line 449 "parser.yy" // lalr1.cc:859
 +    {
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::GIADDR;
 +                }
- #line 1067 "parser.cc" // lalr1.cc:859
++#line 1216 "parser.cc" // lalr1.cc:859
      break;
  
-   case 37:
- #line 355 "parser.yy" // lalr1.cc:859
+   case 47:
 -#line 422 "parser.yy" // lalr1.cc:859
 -    { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR; }
 -#line 1182 "parser.cc" // lalr1.cc:859
++#line 453 "parser.yy" // lalr1.cc:859
 +    {
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::YIADDR;
 +                }
- #line 1075 "parser.cc" // lalr1.cc:859
++#line 1224 "parser.cc" // lalr1.cc:859
      break;
  
-   case 38:
- #line 359 "parser.yy" // lalr1.cc:859
+   case 48:
 -#line 426 "parser.yy" // lalr1.cc:859
++#line 457 "parser.yy" // lalr1.cc:859
      {
 -                 yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location);
 -                 }
 -#line 1190 "parser.cc" // lalr1.cc:859
 +                    yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::SIADDR;
 +                }
- #line 1083 "parser.cc" // lalr1.cc:859
++#line 1232 "parser.cc" // lalr1.cc:859
      break;
  
-   case 39:
- #line 365 "parser.yy" // lalr1.cc:859
+   case 49:
 -#line 434 "parser.yy" // lalr1.cc:859
 -    { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE; }
 -#line 1196 "parser.cc" // lalr1.cc:859
++#line 463 "parser.yy" // lalr1.cc:859
 +    {
 +                     yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE;
 +                 }
- #line 1091 "parser.cc" // lalr1.cc:859
++#line 1240 "parser.cc" // lalr1.cc:859
      break;
  
-   case 40:
- #line 369 "parser.yy" // lalr1.cc:859
+   case 50:
 -#line 435 "parser.yy" // lalr1.cc:859
 -    { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID; }
 -#line 1202 "parser.cc" // lalr1.cc:859
++#line 467 "parser.yy" // lalr1.cc:859
 +    {
 +                     yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID;
 +                 }
- #line 1099 "parser.cc" // lalr1.cc:859
++#line 1248 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 41:
- #line 375 "parser.yy" // lalr1.cc:859
++  case 51:
++#line 473 "parser.yy" // lalr1.cc:859
 +    {
 +                       yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR;
 +                   }
- #line 1107 "parser.cc" // lalr1.cc:859
++#line 1256 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 42:
- #line 379 "parser.yy" // lalr1.cc:859
++  case 52:
++#line 477 "parser.yy" // lalr1.cc:859
 +    {
 +                       yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR;
 +                   }
- #line 1115 "parser.cc" // lalr1.cc:859
++#line 1264 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 43:
- #line 385 "parser.yy" // lalr1.cc:859
++  case 53:
++#line 483 "parser.yy" // lalr1.cc:859
 +    {
-                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
-                      ctx.expression.push_back(str);
-                  }
- #line 1124 "parser.cc" // lalr1.cc:859
++                    TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
++                    ctx.expression.push_back(str);
++                }
++#line 1273 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 44:
- #line 392 "parser.yy" // lalr1.cc:859
++  case 54:
++#line 490 "parser.yy" // lalr1.cc:859
 +    {
-                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
-                       ctx.expression.push_back(str);
-                   }
- #line 1133 "parser.cc" // lalr1.cc:859
++                     TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
++                     ctx.expression.push_back(str);
++                 }
++#line 1282 "parser.cc" // lalr1.cc:859
      break;
  
-   case 45:
- #line 397 "parser.yy" // lalr1.cc:859
++  case 55:
++#line 495 "parser.yy" // lalr1.cc:859
 +    {
 +                     TokenPtr str(new TokenString("all"));
 +                     ctx.expression.push_back(str);
 +                 }
- #line 1142 "parser.cc" // lalr1.cc:859
++#line 1291 "parser.cc" // lalr1.cc:859
 +    break;
  
 -#line 1206 "parser.cc" // lalr1.cc:859
 +
- #line 1146 "parser.cc" // lalr1.cc:859
++#line 1295 "parser.cc" // lalr1.cc:859
              default:
                break;
              }
    }
  
  
-   const signed char EvalParser::yypact_ninf_ = -70;
 -  const signed char EvalParser::yypact_ninf_ = -82;
++  const signed char EvalParser::yypact_ninf_ = -89;
  
    const signed char EvalParser::yytable_ninf_ = -1;
  
-   const signed char
+   const short int
    EvalParser::yypact_[] =
    {
-       15,    15,    15,   -13,     7,    14,    -9,    25,    34,    53,
-       67,   -70,   -70,   -70,    58,    37,    75,    32,   -70,   -12,
-      -12,    45,    42,   -17,   -18,    51,    51,   -70,    15,    15,
-       51,   -70,   -70,   -70,    73,    74,   -70,    77,   -70,   -70,
-      -70,   -70,   -70,   -70,   -70,   -70,   -70,   -70,   -70,   -70,
-      -70,   -70,   -70,   -70,    61,    80,    82,    59,    62,   -70,
-       92,   -70,    83,    85,    86,   -12,   -12,    45,    64,    51,
-       50,    60,    10,    88,    89,    91,   -70,    69,   104,   -70,
-      -70,   -70,   -70,   -70,   -70,    95,   -70,   -70,   -70,    94,
-       96,    97,    -7,   -70,   -12,    55,    55,    40,   -70,   -70,
-      107,    99,   101,   -70,   100,   -12,    63,   102,   -70,   -70,
-      103,    55
 -      65,    65,    65,    -4,    -1,     7,    29,    47,    66,    41,
 -       2,    24,   -82,   -82,   -82,    84,    92,    83,    40,   -82,
 -      45,    45,    67,    56,    -3,    -3,    69,   -11,    75,   -11,
 -      77,   -82,    65,    65,    -3,   -82,   -82,   -82,    80,    91,
 -     -82,   100,   -82,   -82,   -82,   -82,   -82,   -82,   -82,   -82,
 -     103,   104,   105,    73,    76,    90,    94,   -82,   -82,   -82,
 -     -82,   -82,   106,   -82,   107,   -82,   -82,   117,   -82,   109,
 -     110,   111,    45,    45,    67,   -11,   -11,    87,    -3,   113,
 -     114,    36,    43,    11,   116,   118,   119,   120,   121,   -82,
 -     102,   133,   -16,     0,   -82,   -82,   -82,   -82,   -82,   -82,
 -     124,   -82,   -82,   -82,   123,   125,   126,   127,   128,   -14,
 -     -82,   -82,   131,   132,   -82,    45,    93,    93,    22,   112,
 -     138,   -82,   -82,   136,   108,    45,   137,   134,   139,   -82,
 -     140,   141,   135,    45,    45,   -82,   142,    46,   144,   145,
 -      54,   -82,   -82,   146,   147,   -82,   -82,    93,    93
++       4,     4,     4,    11,    18,    46,    69,    70,    93,    94,
++      85,    -6,    36,   -89,   -89,   -89,   105,    32,   100,    77,
++     -89,    58,    58,    71,    67,    48,    62,    62,    26,   -11,
++      72,   -11,    76,   -89,     4,     4,    62,   -89,   -89,   -89,
++     106,   107,   -89,   108,   -89,   -89,   -89,   -89,   -89,   -89,
++     -89,   -89,   -89,   -89,   -89,   -89,   -89,   110,   111,   112,
++      98,    99,    92,    95,   -89,   -89,   -89,   -89,   -89,   113,
++     -89,   114,   -89,   -89,   125,   -89,   116,   117,   118,    58,
++      58,    71,   -11,   -11,    89,    62,   120,   121,     1,    29,
++      14,   123,   124,   126,   127,   128,   -89,   109,   136,   -15,
++      -3,   -89,   -89,   -89,   -89,   -89,   -89,   131,   -89,   -89,
++     -89,   130,   132,   133,   134,   135,   -29,   -89,   -89,   138,
++     139,   -89,    58,    25,    25,    21,   104,   145,   -89,   -89,
++     151,   115,    58,   141,   143,   144,   -89,   147,   148,   149,
++      58,    58,   -89,   150,    51,   152,   153,    75,   -89,   -89,
++     154,   155,   -89,   -89,    25,    25
    };
  
    const unsigned char
    EvalParser::yydefact_[] =
    {
         0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-        0,    11,    12,    13,     0,     2,     0,     0,     4,     0,
-        0,     0,     0,     0,     0,     0,     0,     1,     0,     0,
-        0,     3,    23,    24,     0,     0,    27,     0,    28,    29,
-       30,    31,    17,    32,    33,    34,    35,    36,    37,    38,
-       18,    39,    40,    19,     0,     0,     0,     0,     0,     5,
-        6,     7,     0,     0,     0,     0,     0,     0,     0,     0,
-        0,     0,     0,     0,     0,     0,    43,     0,     0,    25,
-       26,     8,    14,     9,    15,     0,    41,    42,    20,     0,
-        0,     0,     0,    22,     0,     0,     0,     0,    45,    44,
-        0,     0,     0,    21,     0,     0,     0,     0,    10,    16,
-        0,     0
 -       0,     0,    14,    15,    16,     0,     2,     0,     0,     4,
 -       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 -       0,     1,     0,     0,     0,     3,    30,    31,     0,     0,
 -      48,     0,    36,    37,    38,    39,    40,    41,    42,    21,
 -       0,     0,     0,     0,     0,     0,     0,    49,    50,    22,
 -      35,    34,     0,    26,     0,    25,     5,     6,     7,     0,
++       0,     0,     0,    14,    15,    16,     0,     2,     0,     0,
++       4,     0,     0,     0,     0,     0,     0,     0,     0,     0,
++       0,     0,     0,     1,     0,     0,     0,     3,    31,    32,
++       0,     0,    35,     0,    36,    37,    38,    39,    20,    42,
++      43,    44,    45,    46,    47,    48,    21,     0,     0,     0,
++       0,     0,     0,     0,    49,    50,    22,    41,    40,     0,
++      27,     0,    26,     5,     6,     7,     0,     0,     0,     0,
+        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 -       0,     0,     0,     0,     0,     0,     0,     0,     0,    43,
 -       0,     0,     0,     0,    32,    33,     8,    17,     9,    18,
 -       0,    46,    47,    20,     0,     0,     0,     0,     0,     0,
 -      24,    11,    28,     0,    12,     0,     0,     0,     0,     0,
 -       0,    45,    44,     0,     0,     0,     0,     0,     0,    23,
 -       0,     0,     0,     0,     0,    29,     0,     0,     0,     0,
 -       0,    10,    19,     0,     0,    13,    27,     0,     0
++       0,     0,     0,     0,     0,     0,    53,     0,     0,     0,
++       0,    33,    34,     8,    17,     9,    18,     0,    51,    52,
++      23,     0,     0,     0,     0,     0,     0,    25,    11,    29,
++       0,    12,     0,     0,     0,     0,     0,     0,    55,    54,
++       0,     0,     0,     0,     0,     0,    24,     0,     0,     0,
++       0,     0,    30,     0,     0,     0,     0,     0,    10,    19,
++       0,     0,    13,    28,     0,     0
    };
  
    const signed char
    EvalParser::yypgoto_[] =
    {
-      -70,   -70,     4,   -22,   -20,   -69,    54,   -70,   -70,   -70,
-      -70,   -70,   -70
 -     -82,   -82,    10,   -20,   -21,   -81,   -27,   -82,   -82,   -82,
 -     -82,    95,   -82
++     -89,   -89,    20,   -24,   -22,   -88,    78,   -89,   -20,   -89,
++     -89,   -89,   -89,   -89
    };
  
--  const signed char
++  const short int
    EvalParser::yydefgoto_[] =
    {
-       -1,    14,    15,    16,    34,    82,    37,    42,    50,    53,
-       88,    77,   100
 -      -1,    15,    16,    17,    38,    97,    62,    49,    90,   123,
 -     103,    41,    59
++      -1,    16,    17,    18,    40,   104,    43,    48,    69,    56,
++      66,   110,    97,   130
    };
  
    const unsigned char
    EvalParser::yytable_[] =
    {
-       35,    19,    84,    57,    58,    17,    18,    22,    61,    43,
-       44,    45,    46,    47,    48,    49,    51,    52,     1,    85,
-        2,    20,    86,    87,     3,     4,     5,    84,    21,    32,
-       98,    33,    59,    60,    99,     6,    31,   109,    28,    29,
-        7,    23,   109,    28,    29,    73,    74,    78,     8,   102,
-       24,     9,    86,    87,    10,    11,    25,    12,    27,    13,
-       54,    55,    56,    38,    39,    40,    41,    79,    80,    81,
-       26,     6,    79,    80,   101,    65,     7,    79,    80,    83,
-       79,    80,   108,    30,     8,   107,    36,     9,    62,    63,
-       10,    11,    64,    12,    66,    13,    67,    68,    28,    70,
-       69,    71,    72,    89,    90,    76,    91,    92,    93,    94,
-       95,   103,    96,    97,   104,   105,   106,   110,     0,   111,
-        0,    75
 -      39,    99,    64,   111,    55,    56,    50,    51,    52,   113,
 -      20,    18,    19,    21,    68,   121,    27,     6,    28,   114,
 -     100,    22,   112,   101,   102,     7,    60,   122,     8,     9,
 -      61,   127,    53,    54,   101,   102,    99,    12,    29,    13,
 -      30,    14,    66,    67,    35,    23,    32,    33,    87,    88,
 -      24,    84,    85,    94,    95,    96,   142,    26,    91,   146,
 -      94,    95,    98,    94,    95,   141,   142,   146,     1,    25,
 -       2,    94,    95,   145,     3,     4,     5,    42,    43,    44,
 -      45,    46,    47,    48,    31,     6,    36,    75,    37,    28,
 -      76,    34,    30,     7,   126,    69,     8,     9,    32,    33,
 -      10,    11,    57,    58,   131,    12,    70,    13,    40,    14,
 -      94,    95,   138,   139,    63,    71,    65,    72,    73,    74,
 -      77,    79,    80,    32,    78,    81,    82,    83,    89,    92,
 -      93,   104,   109,   105,   106,   107,   108,   110,   115,   116,
 -     129,   117,   118,   119,   120,   124,   125,   128,   133,   130,
 -     112,   137,   132,   134,     0,   135,   136,     0,   140,   143,
 -     144,     0,   147,   148,     0,     0,     0,     0,     0,    86
++      41,   106,    62,    63,   118,   128,   120,     1,    29,     2,
++      30,    71,    75,     3,     4,     5,   121,   129,   101,   102,
++     103,    19,    20,   107,     6,    21,   108,   109,   119,     7,
++     134,    67,    22,   108,   109,    68,   106,     8,    34,    35,
++       9,    10,   101,   102,    11,    12,   101,   102,   105,    13,
++      31,    14,    32,    15,    73,    74,   149,    91,    92,   153,
++      23,    98,    94,    95,    64,    65,   149,   153,   101,   102,
++     148,    57,    58,    59,    49,    50,    51,    52,    53,    54,
++      55,    37,     6,    34,    35,    24,    25,     7,    44,    45,
++      46,    47,   101,   102,   152,     8,    26,    27,     9,    10,
++     133,    28,    60,    61,    38,    33,    39,    13,    36,    14,
++     138,    15,    82,    83,    30,    32,    70,    42,   145,   146,
++      72,    76,    77,    78,    79,    80,    81,    84,    86,    87,
++      85,    34,    88,    89,    90,    96,    99,   100,   111,   112,
++     117,   113,   114,   115,   116,   122,   123,   119,   124,   125,
++     126,   127,   131,   132,   135,   136,   139,   140,   141,    93,
++       0,   137,   142,   143,     0,   144,   147,   150,   151,     0,
++     154,   155
    };
  
-   const signed char
+   const short int
    EvalParser::yycheck_[] =
    {
-       20,    14,    71,    25,    26,     1,     2,    16,    30,    26,
-       27,    28,    29,    30,    31,    32,    34,    35,     3,     9,
-        5,    14,    12,    13,     9,    10,    11,    96,    14,    41,
-       37,    43,    28,    29,    41,    20,     4,   106,     6,     7,
-       25,    16,   111,     6,     7,    65,    66,    69,    33,     9,
-       16,    36,    12,    13,    39,    40,     3,    42,     0,    44,
-        9,    10,    11,    21,    22,    23,    24,    17,    18,    19,
-        3,    20,    17,    18,    94,    14,    25,    17,    18,    19,
-       17,    18,    19,     8,    33,   105,    41,    36,    15,    15,
-       39,    40,    15,    42,    14,    44,    14,    38,     6,    16,
-       38,    16,    16,    15,    15,    41,    15,    38,     4,    14,
-       16,     4,    16,    16,    15,    14,    16,    15,    -1,    16,
-       -1,    67
 -      21,    82,    29,    19,    24,    25,     9,    10,    11,     9,
 -      14,     1,     2,    14,    34,    29,    14,    20,    16,    19,
 -       9,    14,    38,    12,    13,    28,    37,    41,    31,    32,
 -      41,     9,    35,    36,    12,    13,   117,    40,    14,    42,
 -      16,    44,    32,    33,     4,    16,     6,     7,    75,    76,
 -       3,    72,    73,    17,    18,    19,   137,    16,    78,   140,
 -      17,    18,    19,    17,    18,    19,   147,   148,     3,     3,
 -       5,    17,    18,    19,     9,    10,    11,    21,    22,    23,
 -      24,    25,    26,    27,     0,    20,    41,    14,    43,    16,
 -      14,     8,    16,    28,   115,    15,    31,    32,     6,     7,
 -      35,    36,    33,    34,   125,    40,    15,    42,    41,    44,
 -      17,    18,   133,   134,    39,    15,    39,    14,    14,    14,
 -      30,    15,    15,     6,    30,    16,    16,    16,    41,    16,
 -      16,    15,    30,    15,    15,    15,    15,     4,    14,    16,
 -       4,    16,    16,    16,    16,    14,    14,     9,    14,    41,
 -      38,    16,    15,    14,    -1,    15,    15,    -1,    16,    15,
 -      15,    -1,    16,    16,    -1,    -1,    -1,    -1,    -1,    74
++      22,    89,    26,    27,    19,    34,     9,     3,    14,     5,
++      16,    31,    36,     9,    10,    11,    19,    46,    17,    18,
++      19,     1,     2,     9,    20,    14,    12,    13,    43,    25,
++       9,    42,    14,    12,    13,    46,   124,    33,     6,     7,
++      36,    37,    17,    18,    40,    41,    17,    18,    19,    45,
++      14,    47,    16,    49,    34,    35,   144,    79,    80,   147,
++      14,    85,    82,    83,    38,    39,   154,   155,    17,    18,
++      19,     9,    10,    11,    26,    27,    28,    29,    30,    31,
++      32,     4,    20,     6,     7,    16,    16,    25,    21,    22,
++      23,    24,    17,    18,    19,    33,     3,     3,    36,    37,
++     122,    16,    40,    41,    46,     0,    48,    45,     8,    47,
++     132,    49,    14,    14,    16,    16,    44,    46,   140,   141,
++      44,    15,    15,    15,    14,    14,    14,    35,    15,    15,
++      35,     6,    16,    16,    16,    46,    16,    16,    15,    15,
++       4,    15,    15,    15,    35,    14,    16,    43,    16,    16,
++      16,    16,    14,    14,     9,     4,    15,    14,    14,    81,
++      -1,    46,    15,    15,    -1,    16,    16,    15,    15,    -1,
++      16,    16
    };
  
    const unsigned char
    EvalParser::yystos_[] =
    {
 -       0,     3,     5,     9,    10,    11,    20,    28,    31,    32,
 -      35,    36,    40,    42,    44,    46,    47,    48,    47,    47,
 -      14,    14,    14,    16,     3,     3,    16,    14,    16,    14,
 -      16,     0,     6,     7,     8,     4,    41,    43,    49,    49,
 -      41,    56,    21,    22,    23,    24,    25,    26,    27,    52,
 -       9,    10,    11,    35,    36,    48,    48,    33,    34,    57,
 -      37,    41,    51,    39,    51,    39,    47,    47,    48,    15,
 -      15,    15,    14,    14,    14,    14,    14,    30,    30,    15,
 -      15,    16,    16,    16,    49,    49,    56,    51,    51,    41,
 -      53,    48,    16,    16,    17,    18,    19,    50,    19,    50,
 -       9,    12,    13,    55,    15,    15,    15,    15,    15,    30,
 -       4,    19,    38,     9,    19,    14,    16,    16,    16,    16,
 -      16,    29,    41,    54,    14,    14,    49,     9,     9,     4,
 -      41,    49,    15,    14,    14,    15,    15,    16,    49,    49,
 -      16,    19,    50,    15,    15,    19,    50,    16,    16
 +       0,     3,     5,     9,    10,    11,    20,    25,    33,    36,
-       39,    40,    42,    44,    46,    47,    48,    47,    47,    14,
-       14,    14,    16,    16,    16,     3,     3,     0,     6,     7,
-        8,     4,    41,    43,    49,    49,    41,    51,    21,    22,
-       23,    24,    52,    26,    27,    28,    29,    30,    31,    32,
-       53,    34,    35,    54,     9,    10,    11,    48,    48,    47,
-       47,    48,    15,    15,    15,    14,    14,    14,    38,    38,
-       16,    16,    16,    49,    49,    51,    41,    56,    48,    17,
-       18,    19,    50,    19,    50,     9,    12,    13,    55,    15,
-       15,    15,    38,     4,    14,    16,    16,    16,    37,    41,
-       57,    49,     9,     4,    15,    14,    16,    49,    19,    50,
-       15,    16
++      37,    40,    41,    45,    47,    49,    51,    52,    53,    52,
++      52,    14,    14,    14,    16,    16,     3,     3,    16,    14,
++      16,    14,    16,     0,     6,     7,     8,     4,    46,    48,
++      54,    54,    46,    56,    21,    22,    23,    24,    57,    26,
++      27,    28,    29,    30,    31,    32,    59,     9,    10,    11,
++      40,    41,    53,    53,    38,    39,    60,    42,    46,    58,
++      44,    58,    44,    52,    52,    53,    15,    15,    15,    14,
++      14,    14,    14,    14,    35,    35,    15,    15,    16,    16,
++      16,    54,    54,    56,    58,    58,    46,    62,    53,    16,
++      16,    17,    18,    19,    55,    19,    55,     9,    12,    13,
++      61,    15,    15,    15,    15,    15,    35,     4,    19,    43,
++       9,    19,    14,    16,    16,    16,    16,    16,    34,    46,
++      63,    14,    14,    54,     9,     9,     4,    46,    54,    15,
++      14,    14,    15,    15,    16,    54,    54,    16,    19,    55,
++      15,    15,    19,    55,    16,    16
    };
  
    const unsigned char
    EvalParser::yyr1_[] =
    {
--       0,    45,    46,    47,    47,    47,    47,    47,    47,    47,
-       47,    48,    48,    48,    48,    48,    48,    48,    48,    48,
-       48,    48,    48,    49,    49,    50,    50,    51,    52,    52,
-       52,    52,    53,    53,    53,    53,    53,    53,    53,    54,
-       54,    55,    55,    56,    57,    57
 -      47,    47,    47,    47,    48,    48,    48,    48,    48,    48,
 -      48,    48,    48,    48,    48,    48,    48,    48,    48,    48,
 -      49,    49,    50,    50,    51,    51,    52,    52,    52,    52,
 -      52,    52,    52,    53,    54,    54,    55,    55,    56,    57,
 -      57
++       0,    50,    51,    52,    52,    52,    52,    52,    52,    52,
++      52,    52,    52,    52,    53,    53,    53,    53,    53,    53,
++      53,    53,    53,    53,    53,    53,    53,    53,    53,    53,
++      53,    54,    54,    55,    55,    56,    57,    57,    57,    57,
++      58,    58,    59,    59,    59,    59,    59,    59,    59,    60,
++      60,    61,    61,    62,    63,    63
    };
  
    const unsigned char
    EvalParser::yyr2_[] =
    {
         0,     2,     1,     3,     2,     3,     3,     3,     6,     6,
-       11,     1,     1,     1,     6,     6,    11,     3,     3,     3,
-        6,     8,     6,     1,     1,     1,     1,     1,     1,     1,
+       11,     6,     6,    11,     1,     1,     1,     6,     6,    11,
 -       6,     3,     3,     8,     6,     3,     3,    11,     6,     9,
 -       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
++       3,     3,     3,     6,     8,     6,     3,     3,    11,     6,
++       9,     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
    };
  
  
    "\"end of file\"", "error", "$undefined", "\"(\"", "\")\"", "\"not\"",
    "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"relay6\"",
    "\"peeraddr\"", "\"linkaddr\"", "\"[\"", "\"]\"", "\".\"", "\"text\"",
 -  "\"hex\"", "\"exists\"", "\"pkt4\"", "\"mac\"", "\"hlen\"", "\"htype\"",
 -  "\"ciaddr\"", "\"giaddr\"", "\"yiaddr\"", "\"siaddr\"", "\"substring\"",
 -  "\"all\"", "\",\"", "\"concat\"", "\"pkt6\"", "\"msgtype\"",
 -  "\"transid\"", "\"vendor-class\"", "\"vendor\"", "\"*\"", "\"data\"",
 -  "\"enterprise\"", "\"constant string\"", "\"integer\"",
 -  "\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept",
 -  "expression", "bool_expr", "string_expr", "option_code",
 -  "option_repr_type", "enterprise_id", "pkt4_field", "start_expr",
 -  "length_expr", "relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
 +  "\"hex\"", "\"exists\"", "\"pkt\"", "\"iface\"", "\"src\"", "\"dst\"",
 +  "\"len\"", "\"pkt4\"", "\"mac\"", "\"hlen\"", "\"htype\"", "\"ciaddr\"",
-   "\"giaddr\"", "\"yiaddr\"", "\"siaddr\"", "\"pkt6\"", "\"msgtype\"",
-   "\"transid\"", "\"substring\"", "\"all\"", "\",\"", "\"concat\"",
++  "\"giaddr\"", "\"yiaddr\"", "\"siaddr\"", "\"substring\"", "\"all\"",
++  "\",\"", "\"concat\"", "\"pkt6\"", "\"msgtype\"", "\"transid\"",
++  "\"vendor-class\"", "\"vendor\"", "\"*\"", "\"data\"", "\"enterprise\"",
 +  "\"constant string\"", "\"integer\"", "\"constant hexstring\"",
 +  "\"option name\"", "\"ip address\"", "$accept", "expression",
 +  "bool_expr", "string_expr", "option_code", "option_repr_type",
-   "nest_level", "pkt_metadata", "pkt4_field", "pkt6_field", "relay6_field",
-   "start_expr", "length_expr", YY_NULLPTR
++  "nest_level", "pkt_metadata", "enterprise_id", "pkt4_field",
++  "pkt6_field", "relay6_field", "start_expr", "length_expr", YY_NULLPTR
    };
  
  #if YYDEBUG
    const unsigned short int
    EvalParser::yyrline_[] =
    {
--       0,   106,   106,   109,   110,   115,   120,   125,   130,   135,
-      155,   171,   176,   181,   186,   191,   212,   227,   232,   246,
-      260,   275,   280,   287,   291,   297,   301,   307,   316,   320,
-      324,   328,   334,   338,   342,   346,   350,   354,   358,   364,
-      368,   374,   378,   384,   391,   396
 -     155,   169,   178,   188,   199,   204,   209,   214,   219,   240,
 -     255,   270,   275,   280,   285,   290,   298,   307,   318,   329,
 -     343,   347,   353,   357,   363,   367,   372,   376,   380,   384,
 -     388,   392,   396,   402,   409,   414,   421,   422,   425,   434,
 -     435
++       0,   112,   112,   115,   116,   121,   126,   131,   136,   141,
++     161,   175,   184,   193,   205,   210,   215,   220,   225,   246,
++     261,   266,   280,   294,   309,   314,   319,   328,   338,   347,
++     360,   375,   379,   385,   389,   395,   404,   408,   412,   416,
++     422,   426,   432,   436,   440,   444,   448,   452,   456,   462,
++     466,   472,   476,   482,   489,   494
    };
  
    // Print the state stack on the debug stream.
  
  #line 13 "parser.yy" // lalr1.cc:1167
  } } // isc::eval
- #line 1590 "parser.cc" // lalr1.cc:1167
- #line 403 "parser.yy" // lalr1.cc:1168
 -#line 1670 "parser.cc" // lalr1.cc:1167
 -#line 438 "parser.yy" // lalr1.cc:1168
++#line 1765 "parser.cc" // lalr1.cc:1167
++#line 501 "parser.yy" // lalr1.cc:1168
  
  void
  isc::eval::EvalParser::error(const location_type& loc,
index fe72128758fc585bdc0767d0a97a750517e493c0,a4883dcfbfed43389d9b72cef5a51d23a3f926db..f61db8fff2ef129f731e744a8f1a2fe3f1873c33
@@@ -315,13 -312,16 +315,16 @@@ namespace isc { namespace eval 
        // "constant hexstring"
        // "option name"
        // "ip address"
 -      char dummy5[sizeof(std::string)];
 +      char dummy6[sizeof(std::string)];
  
        // option_code
 -      char dummy6[sizeof(uint16_t)];
 +      char dummy7[sizeof(uint16_t)];
  
 -      char dummy7[sizeof(uint32_t)];
+       // enterprise_id
++      char dummy8[sizeof(uint32_t)];
        // nest_level
--      char dummy8[sizeof(uint8_t)];
++      char dummy9[sizeof(uint8_t)];
  };
  
      /// Symbol semantic values.
          TOKEN_TEXT = 272,
          TOKEN_HEX = 273,
          TOKEN_EXISTS = 274,
 -        TOKEN_PKT4 = 275,
 -        TOKEN_CHADDR = 276,
 -        TOKEN_HLEN = 277,
 -        TOKEN_HTYPE = 278,
 -        TOKEN_CIADDR = 279,
 -        TOKEN_GIADDR = 280,
 -        TOKEN_YIADDR = 281,
 -        TOKEN_SIADDR = 282,
 -        TOKEN_SUBSTRING = 283,
 -        TOKEN_ALL = 284,
 -        TOKEN_COMA = 285,
 -        TOKEN_CONCAT = 286,
 -        TOKEN_PKT6 = 287,
 -        TOKEN_MSGTYPE = 288,
 -        TOKEN_TRANSID = 289,
 -        TOKEN_VENDOR_CLASS = 290,
 -        TOKEN_VENDOR = 291,
 -        TOKEN_ANY = 292,
 -        TOKEN_DATA = 293,
 -        TOKEN_ENTERPRISE = 294,
 -        TOKEN_STRING = 295,
 -        TOKEN_INTEGER = 296,
 -        TOKEN_HEXSTRING = 297,
 -        TOKEN_OPTION_NAME = 298,
 -        TOKEN_IP_ADDRESS = 299
 +        TOKEN_PKT = 275,
 +        TOKEN_IFACE = 276,
 +        TOKEN_SRC = 277,
 +        TOKEN_DST = 278,
 +        TOKEN_LEN = 279,
 +        TOKEN_PKT4 = 280,
 +        TOKEN_CHADDR = 281,
 +        TOKEN_HLEN = 282,
 +        TOKEN_HTYPE = 283,
 +        TOKEN_CIADDR = 284,
 +        TOKEN_GIADDR = 285,
 +        TOKEN_YIADDR = 286,
 +        TOKEN_SIADDR = 287,
-         TOKEN_PKT6 = 288,
-         TOKEN_MSGTYPE = 289,
-         TOKEN_TRANSID = 290,
-         TOKEN_SUBSTRING = 291,
-         TOKEN_ALL = 292,
-         TOKEN_COMA = 293,
-         TOKEN_CONCAT = 294,
-         TOKEN_STRING = 295,
-         TOKEN_INTEGER = 296,
-         TOKEN_HEXSTRING = 297,
-         TOKEN_OPTION_NAME = 298,
-         TOKEN_IP_ADDRESS = 299
++        TOKEN_SUBSTRING = 288,
++        TOKEN_ALL = 289,
++        TOKEN_COMA = 290,
++        TOKEN_CONCAT = 291,
++        TOKEN_PKT6 = 292,
++        TOKEN_MSGTYPE = 293,
++        TOKEN_TRANSID = 294,
++        TOKEN_VENDOR_CLASS = 295,
++        TOKEN_VENDOR = 296,
++        TOKEN_ANY = 297,
++        TOKEN_DATA = 298,
++        TOKEN_ENTERPRISE = 299,
++        TOKEN_STRING = 300,
++        TOKEN_INTEGER = 301,
++        TOKEN_HEXSTRING = 302,
++        TOKEN_OPTION_NAME = 303,
++        TOKEN_IP_ADDRESS = 304
        };
      };
  
    static const signed char yypgoto_[];
  
    // YYDEFGOTO[NTERM-NUM].
--  static const signed char yydefgoto_[];
++  static const short int yydefgoto_[];
  
    // YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
    // positive, shift that token.  If negative, reduce the rule whose
      enum
      {
        yyeof_ = 0,
-       yylast_ = 121,     ///< Last index in yytable_.
 -      yylast_ = 169,     ///< Last index in yytable_.
--      yynnts_ = 13,  ///< Number of nonterminal symbols.
-       yyfinal_ = 27, ///< Termination state number.
 -      yyfinal_ = 31, ///< Termination state number.
++      yylast_ = 171,     ///< Last index in yytable_.
++      yynnts_ = 14,  ///< Number of nonterminal symbols.
++      yyfinal_ = 33, ///< Termination state number.
        yyterror_ = 1,
        yyerrcode_ = 256,
--      yyntokens_ = 45  ///< Number of tokens.
++      yyntokens_ = 50  ///< Number of tokens.
      };
  
  
         5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
        15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
        25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
--      35,    36,    37,    38,    39,    40,    41,    42,    43,    44
++      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
++      45,    46,    47,    48,    49
      };
--    const unsigned int user_token_number_max_ = 299;
++    const unsigned int user_token_number_max_ = 304;
      const token_number_type undef_token_ = 2;
  
      if (static_cast<int>(t) <= yyeof_)
    {
        switch (other.type_get ())
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          value.copy< TokenOption::RepresentationType > (other.value);
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          value.copy< TokenPkt4::FieldType > (other.value);
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          value.copy< TokenPkt6::FieldType > (other.value);
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        value.copy< TokenPkt::MetadataType > (other.value);
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          value.copy< TokenRelay6Field::FieldType > (other.value);
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          value.copy< std::string > (other.value);
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          value.copy< uint16_t > (other.value);
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         value.copy< uint32_t > (other.value);
+         break;
+       case 56: // nest_level
          value.copy< uint8_t > (other.value);
          break;
  
      (void) v;
        switch (this->type_get ())
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          value.copy< TokenOption::RepresentationType > (v);
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          value.copy< TokenPkt4::FieldType > (v);
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          value.copy< TokenPkt6::FieldType > (v);
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        value.copy< TokenPkt::MetadataType > (v);
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          value.copy< TokenRelay6Field::FieldType > (v);
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          value.copy< std::string > (v);
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          value.copy< uint16_t > (v);
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         value.copy< uint32_t > (v);
+         break;
+       case 56: // nest_level
          value.copy< uint8_t > (v);
          break;
  
      // Type destructor.
      switch (yytype)
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          value.template destroy< TokenOption::RepresentationType > ();
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          value.template destroy< TokenPkt4::FieldType > ();
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          value.template destroy< TokenPkt6::FieldType > ();
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        value.template destroy< TokenPkt::MetadataType > ();
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          value.template destroy< TokenRelay6Field::FieldType > ();
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          value.template destroy< std::string > ();
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          value.template destroy< uint16_t > ();
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         value.template destroy< uint32_t > ();
+         break;
+       case 56: // nest_level
          value.template destroy< uint8_t > ();
          break;
  
      super_type::move(s);
        switch (this->type_get ())
      {
--      case 50: // option_repr_type
++      case 55: // option_repr_type
          value.move< TokenOption::RepresentationType > (s.value);
          break;
  
-       case 53: // pkt4_field
 -      case 52: // pkt4_field
++      case 59: // pkt4_field
          value.move< TokenPkt4::FieldType > (s.value);
          break;
  
-       case 54: // pkt6_field
 -      case 57: // pkt6_field
++      case 60: // pkt6_field
          value.move< TokenPkt6::FieldType > (s.value);
          break;
  
-       case 52: // pkt_metadata
 -      case 55: // relay6_field
++      case 57: // pkt_metadata
 +        value.move< TokenPkt::MetadataType > (s.value);
 +        break;
 +
-       case 55: // relay6_field
++      case 61: // relay6_field
          value.move< TokenRelay6Field::FieldType > (s.value);
          break;
  
--      case 40: // "constant string"
--      case 41: // "integer"
--      case 42: // "constant hexstring"
--      case 43: // "option name"
--      case 44: // "ip address"
++      case 45: // "constant string"
++      case 46: // "integer"
++      case 47: // "constant hexstring"
++      case 48: // "option name"
++      case 49: // "ip address"
          value.move< std::string > (s.value);
          break;
  
--      case 49: // option_code
++      case 54: // option_code
          value.move< uint16_t > (s.value);
          break;
  
-       case 51: // nest_level
 -      case 51: // enterprise_id
++      case 58: // enterprise_id
+         value.move< uint32_t > (s.value);
+         break;
+       case 56: // nest_level
          value.move< uint8_t > (s.value);
          break;
  
       265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
       275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
       285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
--     295,   296,   297,   298,   299
++     295,   296,   297,   298,   299,   300,   301,   302,   303,   304
      };
      return static_cast<token_type> (yytoken_number_[type]);
    }
  
  #line 13 "parser.yy" // lalr1.cc:377
  } } // isc::eval
--#line 1580 "parser.h" // lalr1.cc:377
++#line 1664 "parser.h" // lalr1.cc:377
  
  
  
index 92bdbbc865a88fdb0df8fea3af816f809ec4026e,d27ab66c12ed2a2854c92aad8a2ba505e02dc5ff..62a6bd270cac88aa1f102063788b6bc092ce2672
@@@ -304,33 -363,16 +392,43 @@@ option_repr_type : TEX
                        }
                   ;
  
 +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.
 +           ;
 +
 +pkt_metadata : IFACE
 +                  {
 +                      $$ = TokenPkt::IFACE;
 +                  }
 +             | SRC
 +                  {
 +                      $$ = TokenPkt::SRC;
 +                  }
 +             | DST
 +                  {
 +                      $$ = TokenPkt::DST;
 +                  }
 +             | LEN
 +                  {
 +                      $$ = TokenPkt::LEN;
 +                  }
 +             ;
 +
+ enterprise_id : INTEGER
+                    {
+                        $$ = ctx.convertUint32($1, @1);
+                    }
+               | "*"
+                    {
+                        $$ = 0;
+                    }
+               ;
  pkt4_field : CHADDR
                  {
                      $$ = TokenPkt4::CHADDR;
                  }
             ;
  
 +pkt6_field : MSGTYPE
 +                 {
 +                     $$ = TokenPkt6::MSGTYPE;
 +                 }
 +           | TRANSID
 +                 {
 +                     $$ = TokenPkt6::TRANSID;
 +                 }
 +           ;
 +
 +relay6_field : PEERADDR
 +                   {
 +                       $$ = TokenRelay6Field::PEERADDR;
 +                   }
 +             | LINKADDR
 +                   {
 +                       $$ = TokenRelay6Field::LINKADDR;
 +                   }
 +             ;
 +
  start_expr : INTEGER
+                 {
+                     TokenPtr str(new TokenString($1));
+                     ctx.expression.push_back(str);
+                 }
+            ;
+ length_expr : INTEGER
                   {
                       TokenPtr str(new TokenString($1));
                       ctx.expression.push_back(str);
index b278ed9a81d4c4203c2019d65d9bfd1c14015880,b8a6954c960c6c3a231e8dd85923ad9537342a75..d8811d1ffef50e5d6707ee9dba241bfb78375b76
@@@ -417,46 -340,223 +417,227 @@@ public
          universe_ = universe;
      }
  
-     Option::Universe universe_;
 -    /// @brief Test that verifies access to the DHCPv6 packet fields.
 -    ///
 -    /// This test attempts to parse the expression, will check if the number
 -    /// of tokens is exactly as planned and then will try to verify if the
 -    /// first token represents expected the field in DHCPv6 packet.
 -    ///
 -    /// @param expr expression to be parsed
 -    /// @param exp_type expected field type to be parsed
 -    /// @param exp_tokens expected number of tokens
 -    void testPkt6Field(std::string expr, TokenPkt6::FieldType exp_type,
 -                       int exp_tokens) {
 -        EvalContext eval(Option::V6);
 -
 -        // Parse the expression.
 -        try {
 -            parsed_ = eval.parseString(expr);
 -        }
 -        catch (const EvalParseError& ex) {
 -            FAIL() << "Exception thrown: " << ex.what();
 -            return;
 -        }
 -
 -        // Parsing should succeed and return a token.
 -        EXPECT_TRUE(parsed_);
 -
 -        // There should be the requested number of tokens
 -        ASSERT_EQ(exp_tokens, eval.expression.size());
 -
 -        // Check that the first token is TokenPkt6 instance and has correct type.
 -        checkTokenPkt6(eval.expression.at(0), exp_type);
 -    }
 -
 -
+     /// @brief Checks if the given token is TokenVendor and has expected characteristics
+     /// @param token token to be checked
+     /// @param exp_vendor_id expected vendor-id (aka enterprise number)
+     /// @param exp_repr expected representation (either 'exists' or 'hex')
+     /// @param exp_option_code expected option code (ignored if 0)
+     void checkTokenVendor(const TokenPtr& token, uint32_t exp_vendor_id,
+                           uint16_t exp_option_code,
+                           TokenOption::RepresentationType exp_repr) {
+         ASSERT_TRUE(token);
+         boost::shared_ptr<TokenVendor> vendor =
+             boost::dynamic_pointer_cast<TokenVendor>(token);
+         ASSERT_TRUE(vendor);
+         EXPECT_EQ(exp_vendor_id, vendor->getVendorId());
+         EXPECT_EQ(exp_repr, vendor->getRepresentation());
+         EXPECT_EQ(exp_option_code, vendor->getCode());
+     }
+     /// @brief Tests if specified token vendor expression can be parsed
+     ///
+     /// This test assumes the first token will be token vendor. Any additional
+     /// tokens are ignored. Tests expressions:
+     /// vendor[1234].option[234].hex
+     /// vendor[1234].option[234].exists
+     ///
+     /// @param expr expression to be parsed
+     /// @param u universe (V4 or V6)
+     /// @param vendor_id expected vendor-id (aka enterprise number)
+     /// @param option_code expected option code (ignored if 0)
+     /// @param expected_repr expected representation (either 'exists' or 'hex')
+     void testVendor(std::string expr, Option::Universe u, uint32_t vendor_id,
+                     uint16_t option_code, TokenOption::RepresentationType expected_repr) {
+         EvalContext eval(u);
+         EXPECT_NO_THROW(parsed_ = eval.parseString(expr));
+         EXPECT_TRUE(parsed_);
+         // We need at least one token, we will evaluate the first one.
+         ASSERT_FALSE(eval.expression.empty());
+         checkTokenVendor(eval.expression.at(0), vendor_id, option_code, expected_repr);
+     }
+     /// @brief Checks if token is really a TokenVendor, that the vendor_id was
+     /// stored properly and that it has expected representation
+     ///
+     /// This test is able to handle expressions similar to:
+     /// vendor[4491].option[1].hex
+     /// vendor[4491].option[1].exists
+     /// vendor[4491].exists
+     /// vendor[*].exists
+     ///
+     /// @param expr expression to be parsed
+     /// @param u universe (V4 or V6)
+     /// @param vendor_id expected vendor-id (aka enterprise number)
+     /// @param expected_repr expected representation (either 'exists' or 'hex')
+     void testVendor(std::string expr, Option::Universe u, uint32_t vendor_id,
+                     TokenOption::RepresentationType expected_repr) {
+         testVendor(expr, u, vendor_id, 0, expected_repr);
+     }
+     /// @brief Tests if the expression parses into token vendor that returns enterprise-id
+     ///
+     /// This test is able to handle expressions similar to:
+     /// vendor.enterprise
+     ///
+     /// @param expr expression to be parsed
+     /// @param u universe (V4 or V6)
+     void testVendorEnterprise(std::string expr, Option::Universe u) {
+         EvalContext eval(u);
+         EXPECT_NO_THROW(parsed_ = eval.parseString(expr));
+         EXPECT_TRUE(parsed_);
+         ASSERT_FALSE(eval.expression.empty());
+         boost::shared_ptr<TokenVendor> vendor =
+             boost::dynamic_pointer_cast<TokenVendor>(eval.expression.at(0));
+         ASSERT_TRUE(vendor);
+         EXPECT_EQ(TokenVendor::ENTERPRISE_ID, vendor->getField());
+     }
+     /// @brief This test checks if vendor-class token is correct
+     ///
+     /// This test checks if EXISTS representation is set correctly.
+     /// It covers cases like:
+     /// - vendor-class[4491].exists
+     /// - vendor-class[*].exists
+     ///
+     /// @param expr expression to be parsed
+     /// @param u universe (V4 or V6)
+     /// @param vendor_id expected vendor-id (aka enterprise number)
+     void testVendorClass(std::string expr, Option::Universe u, uint32_t vendor_id) {
+         EvalContext eval(u);
+         EXPECT_NO_THROW(parsed_ = eval.parseString(expr));
+         EXPECT_TRUE(parsed_);
+         ASSERT_EQ(1, eval.expression.size());
+         checkTokenVendorClass(eval.expression.at(0), vendor_id, 0, TokenOption::EXISTS,
+                               TokenVendor::EXISTS);
+     }
+     /// @brief Tests if specified token vendor class expression can be parsed
+     ///
+     /// This test assumes the first token will be token vendor-class.
+     /// Any additional tokens are ignored. Tests expressions:
+     /// - vendor-class[4491].exists
+     /// - vendor-class[*].exists
+     /// - vendor-class[4491].data
+     /// - vendor-class[4491].data[3]
+     ///
+     /// @param expr expression to be parsed
+     /// @param u universe (V4 or V6)
+     /// @param vendor_id expected vendor-id (aka enterprise number)
+     /// @param index expected data index
+     void testVendorClass(std::string expr, Option::Universe u, uint32_t vendor_id,
+                          uint16_t index) {
+         EvalContext eval(u);
+         EXPECT_NO_THROW(parsed_ = eval.parseString(expr));
+         EXPECT_TRUE(parsed_);
+         // Make sure there's at least one token
+         ASSERT_FALSE(eval.expression.empty());
+         // The first token should be TokenVendorClass, let's take a closer look.
+         checkTokenVendorClass(eval.expression.at(0), vendor_id, index,
+                               TokenOption::HEXADECIMAL, TokenVendor::DATA);
+     }
+     /// @brief Tests if the expression parses into vendor class token that
+     ///        returns enterprise-id.
+     ///
+     /// This test is able to handle expressions similar to:
+     /// - vendor-class.enterprise
+     ///
+     /// @param expr expression to be parsed
+     /// @param u universe (V4 or V6)
+     void testVendorClassEnterprise(std::string expr, Option::Universe u) {
+         EvalContext eval(u);
+         EXPECT_NO_THROW(parsed_ = eval.parseString(expr));
+         EXPECT_TRUE(parsed_);
+         // Make sure there's at least one token
+         ASSERT_FALSE(eval.expression.empty());
+         // The first token should be TokenVendorClass, let's take a closer look.
+         checkTokenVendorClass(eval.expression.at(0), 0, 0, TokenOption::HEXADECIMAL,
+                               TokenVendor::ENTERPRISE_ID);
+     }
+     /// @brief Checks if the given token is TokenVendorClass and has expected characteristics
+     ///
+     /// @param token token to be checked
+     /// @param vendor_id expected vendor-id (aka enterprise number)
+     /// @param index expected index (used for data field only)
+     /// @param repr expected representation (either 'exists' or 'hex')
+     /// @param field expected field (none, enterprise or data)
+     void checkTokenVendorClass(const TokenPtr& token, uint32_t vendor_id,
+                                uint16_t index, TokenOption::RepresentationType repr,
+                                TokenVendor::FieldType field) {
+         ASSERT_TRUE(token);
+         boost::shared_ptr<TokenVendorClass> vendor =
+             boost::dynamic_pointer_cast<TokenVendorClass>(token);
+         ASSERT_TRUE(vendor);
+         EXPECT_EQ(vendor_id, vendor->getVendorId());
+         EXPECT_EQ(index, vendor->getDataIndex());
+         EXPECT_EQ(repr, vendor->getRepresentation());
+         EXPECT_EQ(field, vendor->getField());
+     }
+     Option::Universe universe_; ///< Universe (V4 or V6)
      bool parsed_; ///< Parsing status
++
  };
  
 +// Test the error method without location
 +TEST_F(EvalContextTest, error) {
 +
 +    EvalContext eval(Option::V4);
 +
 +    EXPECT_THROW(eval.error("an error"), EvalParseError);
 +}
 +
 +// Test the fatal method
 +TEST_F(EvalContextTest, fatal) {
 +
 +    EvalContext eval(Option::V4);
 +
 +    EXPECT_THROW(eval.fatal("a fatal error"), isc::Unexpected);
 +}
 +
 +// Test the convertOptionCode method with an illegal input
 +TEST_F(EvalContextTest, badOptionCode) {
 +
 +    EvalContext eval(Option::V4);
 +
 +    // the option code must be a number
 +    EXPECT_THROW(eval.convertOptionCode("bad", location(position())),
 +                 EvalParseError);
 +}
 +
 +// Test the convertNestLevelNumber method with an illegal input
 +TEST_F(EvalContextTest, badNestLevelNumber) {
 +
 +    EvalContext eval(Option::V4);
 +
 +    // the nest level number must be a number
 +    EXPECT_THROW(eval.convertNestLevelNumber("bad", location(position())),
 +                 EvalParseError);
 +}
 +
  // Test the parsing of a basic expression
  TEST_F(EvalContextTest, basic) {
  
@@@ -711,81 -811,6 +892,80 @@@ TEST_F(EvalContextTest, relay4Error) 
                 "<string>:1.1-6: relay4 can only be used in DHCPv4.");
  }
  
-                "<string>:1.8-9: Nest level has invalid value in -1. "
-                "Allowed range: 0..31");
 +// Test the parsing of a relay6 option
 +TEST_F(EvalContextTest, relay6Option) {
 +    EvalContext eval(Option::V6);
 +
 +    testRelay6Option("relay6[0].option[123].text == 'foo'",
 +                     0, 123, TokenOption::TEXTUAL, 3);
 +}
 +
 +// Test the parsing of existence for a relay6 option
 +TEST_F(EvalContextTest, relay6OptionExists) {
 +    EvalContext eval(Option::V6);
 +
 +    testRelay6Option("relay6[1].option[75].exists",
 +                     1, 75, TokenOption::EXISTS, 1);
 +}
 +
 +// Test the parsing of hex for a relay6 option
 +TEST_F(EvalContextTest, relay6OptionHex) {
 +    EvalContext eval(Option::V6);
 +
 +    testRelay6Option("relay6[2].option[85].hex == 'foo'",
 +                     2, 85, TokenOption::HEXADECIMAL, 3);
 +}
 +
 +// Test the nest level of a relay6 option should be in [0..32[
 +TEST_F(EvalContextTest, relay6OptionLimits) {
 +    EvalContext eval(Option::V6);
 +
 +    // max nest level is hop count limit minus one so 31
 +    testRelay6Option("relay6[31].option[123].text == 'foo'",
 +                     31, 123, TokenOption::TEXTUAL, 3);
 +
 +    universe_ = Option::V6;
 +
 +    checkError("relay6[32].option[123].text == 'foo'",
 +               "<string>:1.8-9: Nest level has invalid value in 32. "
 +               "Allowed range: 0..31");
 +                     
 +    // next level must be a positive number
 +    checkError("relay6[-1].option[123].text == 'foo'",
++               "<string>:1.8-9: Invalid value in -1. Allowed range: 0..255");
 +}
 +
 +// Verify that relay6[13].option is not usable in v4
 +TEST_F(EvalContextTest, relay6OptionError) {
 +    universe_ = Option::V4;
 +
 +    // nest_level is reduced first so raises the error
 +    // (if we'd like to get a relay6 error we have to insert an
 +    //  intermediate action to check the universe)
 +    checkError("relay6[0].option[123].text == 'foo'",
 +               "<string>:1.8: Nest level invalid for DHCPv4 packets");
 +}
 +
 +// Tests whether iface metadata in DHCP can be accessed.
 +TEST_F(EvalContextTest, pktMetadataIface) {
 +    testPktMetadata("pkt.iface == 'eth0'", TokenPkt::IFACE, 3);
 +}
 +
 +// Tests whether src metadata in DHCP can be accessed.
 +TEST_F(EvalContextTest, pktMetadataSrc) {
 +    testPktMetadata("pkt.src == fe80::1", TokenPkt::SRC, 3);
 +}
 +
 +// Tests whether dst metadata in DHCP can be accessed.
 +TEST_F(EvalContextTest, pktMetadataDst) {
 +    testPktMetadata("pkt.dst == fe80::2", TokenPkt::DST, 3);
 +}
 +
 +// Tests whether len metadata in DHCP can be accessed.
 +TEST_F(EvalContextTest, pktMetadataLen) {
 +    testPktMetadata("pkt.len == 0x00000100", TokenPkt::LEN, 3);
 +}
 +
  // Tests whether chaddr field in DHCPv4 can be accessed.
  TEST_F(EvalContextTest, pkt4FieldChaddr) {
      testPkt4Field("pkt4.mac == 0x000102030405", TokenPkt4::CHADDR, 3);
Simple merge
index 918e4e9ae7dd55a8af7211e729437c1432225759,a130c35715415b4342873c20d5b329f03a453799..7ef16a034864c13d1402650bccd6fbb270650143
@@@ -7,11 -7,14 +7,15 @@@
  #include <eval/token.h>
  #include <eval/eval_log.h>
  #include <util/encode/hex.h>
 +#include <util/io_utilities.h>
  #include <asiolink/io_address.h>
  #include <dhcp/pkt4.h>
 -#include <boost/lexical_cast.hpp>
  #include <dhcp/pkt6.h>
 +#include <boost/lexical_cast.hpp>
+ #include <dhcp/dhcp4.h>
+ #include <dhcp/dhcp6.h>
+ #include <dhcp/option_vendor.h>
+ #include <dhcp/option_vendor_class.h>
  #include <cstring>
  #include <string>
  
@@@ -641,3 -482,358 +655,227 @@@ TokenOr::evaluate(Pkt& /*pkt*/, ValueSt
          .arg('\'' + op2 + '\'')
          .arg('\'' + values.top() + '\'');
  }
 -OptionPtr TokenRelay6Option::getOption(Pkt& pkt) {
 -
 -    try {
 -        // Check if it's a Pkt6.  If it's not the dynamic_cast will
 -        // throw std::bad_cast.
 -        Pkt6& pkt6 = dynamic_cast<Pkt6&>(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 out of range of the encapsulations, for example
 -            // if nest_level_ is 4 and there are only 2 encapsulations.
 -            // We return a NULL in that case.
 -           return (OptionPtr());
 -        }
 -
 -    } catch (const std::bad_cast&) {
 -        isc_throw(EvalTypeError, "Specified packet is not Pkt6");
 -    }
 -
 -}
 -
 -void
 -TokenRelay6Field::evaluate(Pkt& pkt, ValueStack& values) {
 -
 -    vector<uint8_t> binary;
 -    string type_str;
 -    try {
 -        // Check if it's a Pkt6.  If it's not the dynamic_cast will
 -        // throw std::bad_cast.
 -        const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
 -
 -        try {
 -        switch (type_) {
 -            // Now that we have the right type of packet we can
 -            // get the option and return it.
 -            case LINKADDR:
 -                type_str = "linkaddr";
 -                binary = pkt6.getRelay6LinkAddress(nest_level_).toBytes();
 -                break;
 -            case PEERADDR:
 -                type_str = "peeraddr";
 -                binary = pkt6.getRelay6PeerAddress(nest_level_).toBytes();
 -                break;
 -            }
 -        } catch (const isc::OutOfRange&) {
 -            // The only exception we expect is OutOfRange if the nest
 -            // level is invalid.  We push "" in that case.
 -            values.push("");
 -            // Log what we pushed
 -            LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_RELAY6_RANGE)
 -              .arg(type_str)
 -              .arg(unsigned(nest_level_))
 -              .arg("0x");
 -            return;
 -        }
 -    } catch (const std::bad_cast&) {
 -        isc_throw(EvalTypeError, "Specified packet is not Pkt6");
 -    }
 -
 -    string value;
 -    value.resize(binary.size());
 -    if (!binary.empty()) {
 -        memmove(&value[0], &binary[0], binary.size());
 -    }
 -    values.push(value);
 -
 -    // Log what we pushed
 -    LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_RELAY6)
 -        .arg(type_str)
 -        .arg(unsigned(nest_level_))
 -        .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value.begin(),
 -                                                                 value.end())));
 -}
 -
 -void
 -TokenPkt6::evaluate(Pkt& pkt, ValueStack& values) {
 -
 -    vector<uint8_t> binary;
 -    string type_str;
 -    try {
 -      // Check if it's a Pkt6.  If it's not the dynamic_cast will throw
 -      // std::bad_cast (failed dynamic_cast returns NULL for pointers and
 -      // throws for references).
 -      const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
 -
 -      switch (type_) {
 -      case MSGTYPE: {
 -          // msg type is an uint8_t integer.  We want a 4 byte string so 0 pad.
 -          binary.push_back(0);
 -          binary.push_back(0);
 -          binary.push_back(0);
 -          binary.push_back(pkt6.getType());
 -          type_str = "msgtype";
 -          break;
 -      }
 -      case TRANSID: {
 -          // transaction id is an uint32_t integer.  We want a 4 byte string so copy
 -          uint32_t transid = pkt6.getTransid();
 -          binary.push_back(transid >> 24);
 -          binary.push_back((transid >> 16) & 0xFF);
 -          binary.push_back((transid >> 8) & 0xFF);
 -          binary.push_back(transid & 0xFF);
 -          type_str = "transid";
 -          break;
 -      }
 -      default:
 -          isc_throw(EvalTypeError, "Bad field specified: "
 -                    << static_cast<int>(type_) );
 -      }
 -
 -    } catch (const std::bad_cast&) {
 -        isc_throw(EvalTypeError, "Specified packet is not Pkt6");
 -    }
 -
 -    string value;
 -    value.resize(binary.size());
 -    memmove(&value[0], &binary[0], binary.size());
 -    values.push(value);
 -
 -    // Log what we pushed
 -    LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_PKT6)
 -        .arg(type_str)
 -        .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value.begin(),
 -                                                                 value.end())));
 -}
 -
+ TokenVendor::TokenVendor(Option::Universe u, uint32_t vendor_id, RepresentationType repr,
+                          uint16_t option_code)
+     :TokenOption(option_code, repr), universe_(u), vendor_id_(vendor_id),
+      field_(option_code ? SUBOPTION : EXISTS)
+ {
+ }
+ TokenVendor::TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field)
+     :TokenOption(0, TokenOption::HEXADECIMAL), universe_(u), vendor_id_(vendor_id),
+      field_(field)
+ {
+     if (field_ == EXISTS) {
+         representation_type_ = TokenOption::EXISTS;
+     }
+ }
+ uint32_t TokenVendor::getVendorId() const {
+     return (vendor_id_);
+ }
+ TokenVendor::FieldType TokenVendor::getField() const {
+     return (field_);
+ }
+ void TokenVendor::evaluate(Pkt& pkt, ValueStack& values) {
+     // Get the option first.
+     uint16_t code = 0;
+     switch (universe_) {
+     case Option::V4:
+         code = DHO_VIVSO_SUBOPTIONS;
+         break;
+     case Option::V6:
+         code = D6O_VENDOR_OPTS;
+         break;
+     }
+     OptionPtr opt = pkt.getOption(code);
+     OptionVendorPtr vendor = boost::dynamic_pointer_cast<OptionVendor>(opt);
+     if (!vendor) {
+         // There's no vendor option, give up.
+         std::string txt = pushFailure(values);
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_NO_OPTION)
+             .arg(code)
+             .arg(txt);
+         return;
+     }
+     if (vendor_id_ && (vendor_id_ != vendor->getVendorId())) {
+         // There is vendor option, but it has other vendor-id value
+         // than we're looking for. (0 means accept any vendor-id)
+         std::string txt = pushFailure(values);
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_ENTERPRISE_ID_MISMATCH)
+             .arg(vendor_id_)
+             .arg(vendor->getVendorId())
+             .arg(txt);
+         return;
+     }
+     switch (field_) {
+     case ENTERPRISE_ID:
+     {
+         // Extract enterprise-id
+         string txt(sizeof(uint32_t), 0);
+         uint32_t value = htonl(vendor->getVendorId());
+         memcpy(&txt[0], &value, sizeof(uint32_t));
+         values.push(txt);
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_ENTERPRISE_ID)
+             .arg(vendor->getVendorId())
+             .arg(util::encode::encodeHex(std::vector<uint8_t>(txt.begin(),
+                                                               txt.end())));
+         return;
+     }
+     case SUBOPTION:
+         /// This is vendor[X].option[Y].exists, let's try to
+         /// extract the option
+         TokenOption::evaluate(pkt, values);
+         return;
+     case EXISTS:
+         // We already passed all the checks: the option is there and has specified
+         // enterprise-id.
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_EXISTS)
+             .arg(vendor->getVendorId())
+             .arg("true");
+         values.push("true");
+         return;
+     case DATA:
+         // This is for vendor-class option, we can skip it here.
+         isc_throw(EvalTypeError, "Field None is not valid for vendor-class");
+         return;
+     }
+ }
+ OptionPtr TokenVendor::getOption(Pkt& pkt) {
+    uint16_t code = 0;
+     switch (universe_) {
+     case Option::V4:
+         code = DHO_VIVSO_SUBOPTIONS;
+         break;
+     case Option::V6:
+         code = D6O_VENDOR_OPTS;
+         break;
+     }
+     OptionPtr opt = pkt.getOption(code);
+     if (!opt) {
+         // If vendor option is not found, return NULL
+         return (opt);
+     }
+     // If vendor option is found, try to return its
+     // encapsulated option.
+     return (opt->getOption(option_code_));
+ }
+ TokenVendorClass::TokenVendorClass(Option::Universe u, uint32_t vendor_id,
+                                    RepresentationType repr)
+     :TokenVendor(u, vendor_id, repr, 0), index_(0) {
+ }
+ TokenVendorClass::TokenVendorClass(Option::Universe u, uint32_t vendor_id,
+                                    FieldType field, uint16_t index)
+     :TokenVendor(u, vendor_id, TokenOption::HEXADECIMAL, 0), index_(index)
+ {
+     field_ = field;
+ }
+ uint16_t TokenVendorClass::getDataIndex() const {
+     return (index_);
+ }
+ void TokenVendorClass::evaluate(Pkt& pkt, ValueStack& values) {
+     // Get the option first.
+     uint16_t code = 0;
+     switch (universe_) {
+     case Option::V4:
+         code = DHO_VIVCO_SUBOPTIONS;
+         break;
+     case Option::V6:
+         code = D6O_VENDOR_CLASS;
+         break;
+     }
+     OptionPtr opt = pkt.getOption(code);
+     OptionVendorClassPtr vendor = boost::dynamic_pointer_cast<OptionVendorClass>(opt);
+     if (!vendor) {
+         // There's no vendor class option, give up.
+         std::string txt = pushFailure(values);
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_CLASS_NO_OPTION)
+             .arg(code)
+             .arg(txt);
+         return;
+     }
+     if (vendor_id_ && (vendor_id_ != vendor->getVendorId())) {
+         // There is vendor option, but it has other vendor-id value
+         // than we're looking for. (0 means accept any vendor-id)
+         std::string txt = pushFailure(values);
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID_MISMATCH)
+             .arg(vendor_id_)
+             .arg(vendor->getVendorId())
+             .arg(txt);
+         return;
+     }
+     switch (field_) {
+     case ENTERPRISE_ID:
+     {
+         // Extract enterprise-id
+         string txt(sizeof(uint32_t), 0);
+         uint32_t value = htonl(vendor->getVendorId());
+         memcpy(&txt[0], &value, sizeof(uint32_t));
+         values.push(txt);
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_CLASS_ENTERPRISE_ID)
+             .arg(vendor->getVendorId())
+             .arg(util::encode::encodeHex(std::vector<uint8_t>(txt.begin(),
+                                                               txt.end())));
+         return;
+     }
+     case SUBOPTION:
+         // Extract sub-options
+         isc_throw(EvalTypeError, "Field None is not valid for vendor-class");
+         return;
+     case EXISTS:
+         // We already passed all the checks: the option is there and has specified
+         // enterprise-id.
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_CLASS_EXISTS)
+             .arg(vendor->getVendorId())
+             .arg("true");
+         values.push("true");
+         return;
+     case DATA:
+     {
+         size_t max = vendor->getTuplesNum();
+         if (index_ + 1 > max) {
+             // The index specified is out of bounds, e.g. there are only
+             // 2 tuples and index specified is 5.
+             LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_CLASS_DATA_NOT_FOUND)
+                 .arg(index_)
+                 .arg(vendor->getVendorId())
+                 .arg(max)
+                 .arg("");
+             values.push("");
+             return;
+         }
+         OpaqueDataTuple tuple = vendor->getTuple(index_);
+         OpaqueDataTuple::Buffer buf = tuple.getData();
+         string txt(buf.begin(), buf.end());
+         LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_VENDOR_CLASS_DATA)
+             .arg(index_)
+             .arg(max)
+             .arg(txt);
+         values.push(txt);
+         return;
+     }
+     default:
+         isc_throw(EvalTypeError, "Invalid field specified." << field_);
+     }
+ }
index ff2e78c2cd3832debd3e02bb225fa449455a18b0,ea6c9cbdf7b48a9384e670ee3297a06542d8ff6e..aabca8439730cb8713caae88ceba2a500f052795
@@@ -728,6 -530,350 +736,191 @@@ public
      void evaluate(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(Pkt& pkt);
 -
 -    uint8_t nest_level_; ///< nesting level of the relay block to use
 -};
 -
 -/// @brief 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 TokenRelay6Field : 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.
 -    TokenRelay6Field(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(Pkt& pkt, ValueStack& values);
 -
 -    /// @brief Returns nest-level
 -    ///
 -    /// This method is used in testing to determine if the parser has
 -    /// instantiated TokenRelay6Field with correct parameters.
 -    ///
 -    /// @return nest-level of the relay block this token expects to use
 -    /// for extraction.
 -    uint8_t getNest() const {
 -        return (nest_level_);
 -    }
 -
 -    /// @brief Returns field type
 -    ///
 -    /// This method is used only in testing to determine if the parser has
 -    /// instantiated TokenRelay6Field 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
 -};
 -
 -/// @brief Token that represents fields of DHCPv6 packet.
 -///
 -/// For example in the expression pkt6.msgtype == 1
 -/// this token represents the message type of the DHCPv6 packet.
 -/// The integer values are placed on the value stack as 4 byte
 -/// strings.
 -///
 -/// Currently supported fields are:
 -/// - msgtype
 -/// - transid
 -class TokenPkt6 : public Token {
 -public:
 -    /// @brief enum value that determines the field.
 -    enum FieldType {
 -        MSGTYPE, ///< msg type
 -        TRANSID  ///< transaction id (integer but manipulated as a string)
 -    };
 -
 -    /// @brief Constructor (does nothing)
 -    TokenPkt6(const FieldType type)
 -        : type_(type) {}
 -
 -    /// @brief Gets a value of the specified packet.
 -    ///
 -    /// The evaluation uses fields that are availabe in the packet.  It does not
 -    /// require any values to be present on the stack.
 -    ///
 -    /// @throw EvalTypeError when called for a DHCPv4 packet
 -    ///
 -    /// @param pkt - packet from which to extract the fields
 -    /// @param values - stack of values, 1 result will be pushed
 -    void evaluate(Pkt& pkt, ValueStack& values);
 -
 -    /// @brief Returns field type
 -    ///
 -    /// This method is used only in tests.
 -    /// @return type of the field.
 -    FieldType getType() {
 -        return(type_);
 -    }
 -
 -private:
 -    /// @brief Specifies field of the DHCPv6 packet to get
 -    FieldType type_;
 -};
 -
+ /// @brief Token that represents vendor options in DHCPv4 and DHCPv6.
+ ///
+ /// It covers vendor independent vendor information option (125, DHCPv4)
+ /// and vendor option (17, DHCPv6). Since both of those options may have
+ /// suboptions, this class is derived from TokenOption and leverages its
+ /// ability to operate on sub-options. It also adds additional capabilities.
+ /// In particular, it allows retrieving enterprise-id.
+ ///
+ /// It can represent the following expressions:
+ /// vendor[4491].exists - if vendor option with enterprise-id = 4491 exists
+ /// vendor[*].exists - if any vendor option exists
+ /// vendor.enterprise - returns enterprise-id from vendor option
+ /// vendor[4491].option[1].exists - check if suboption 1 exists for vendor 4491
+ /// vendor[4491].option[1].hex - return content of suboption 1 for vendor 4491
+ class TokenVendor : public TokenOption {
+ public:
+     /// @brief Specifies a field of the vendor option
+     enum FieldType {
+         SUBOPTION,     ///< If this token fetches a suboption, not a field.
+         ENTERPRISE_ID, ///< enterprise-id field (vendor-info, vendor-class)
+         EXISTS,        ///< vendor[123].exists
+         DATA           ///< data chunk, used in derived vendor-class only
+     };
+     /// @brief Constructor used for accessing a field
+     ///
+     /// @param u universe (either V4 or V6)
+     /// @param vendor_id specifies enterprise-id (0 means any)
+     /// @param field specifies which field should be returned
+     TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field);
+     /// @brief Constructor used for accessing an option
+     ///
+     /// This constructor is used for accessing suboptions. In general
+     /// option_code is mandatory, except when repr is EXISTS. For
+     /// option_code = 0 and repr = EXISTS, the token will return true
+     /// if the whole option exists, not suboptions.
+     ///
+     /// @param u universe (either V4 or V6)
+     /// @param vendor_id specifies enterprise-id (0 means any)
+     /// @param repr representation type (hex or exists)
+     /// @param option_code sub-option code
+     TokenVendor(Option::Universe u, uint32_t vendor_id, RepresentationType repr,
+                 uint16_t option_code = 0);
+     /// @brief Returns enterprise-id
+     ///
+     /// Used in tests only.
+     ///
+     /// @return enterprise-id
+     uint32_t getVendorId() const;
+     /// @brief Returns field.
+     ///
+     /// Used in tests only.
+     ///
+     /// @return field type.
+     FieldType getField() const;
+     /// @brief This is a method for evaluating a packet.
+     ///
+     /// Depending on the value of vendor_id, field type, representation and
+     /// option code, it will attempt to return specified characteristic of the
+     /// vendor option
+     ///
+     /// If vendor-id is specified, check only option with that particular
+     /// enterprise-id. If vendor-id is 0, check any vendor option, regardless
+     /// of its enterprise-id value.
+     ///
+     /// If FieldType is NONE, get specified suboption represented by option_code
+     /// and represent it as specified by repr.
+     ///
+     /// If FieldType is ENTERPRISE_ID, return value of the enterprise-id field
+     /// or "" if there's no vendor option.
+     ///
+     /// @throw EvalTypeError for any other FieldType values.
+     ///
+     /// The parameters passed are:
+     ///
+     /// @param pkt - vendor options will be searched for here.
+     /// @param values - the evaluated value will be pushed here.
+     virtual void evaluate(Pkt& pkt, ValueStack& values);
+ protected:
+     /// @brief Attempts to get a suboption.
+     ///
+     /// This method overrides behavior of TokenOption method. It attempts to retrieve
+     /// the sub-option of the vendor option. Using derived method allows usage of
+     /// TokenOption routines.
+     ///
+     /// @param pkt vendor option will be searched here.
+     /// @return suboption of the vendor option (if exists)
+     virtual OptionPtr getOption(Pkt& pkt);
+     /// @brief Universe (V4 or V6)
+     ///
+     /// We need to remember it, because depending on the universe, the code needs
+     /// to retrieve either option 125 (DHCPv4) or 17 (DHCPv6).
+     Option::Universe universe_;
+     /// @brief Enterprise-id value
+     ///
+     /// Yeah, I know it technically should be called enterprise-id, but that's
+     /// too long and everyone calls it vendor-id.
+     uint32_t vendor_id_;
+     /// @brief Specifies which field should be accessed.
+     FieldType field_;
+ };
+ /// @brief Token that represents vendor class options in DHCPv4 and DHCPv6.
+ ///
+ /// It covers vendor independent vendor information option (124, DHCPv4)
+ /// and vendor option (16, DHCPv6). Contrary to vendor options, vendor class
+ /// options don't have suboptions, but have data chunks (tuples) instead.
+ /// Therefore they're not referenced by option codes, but by indexes.
+ /// The first data chunk is data[0], the second is data[1] etc.
+ ///
+ /// This class is derived from OptionVendor to take advantage of the
+ /// enterprise handling field and field type.
+ ///
+ /// It can represent the following expressions:
+ /// vendor-class[4491].exists
+ /// vendor-class[*].exists
+ /// vendor-class[*].enterprise
+ /// vendor-class[4491].data - content of the opaque-data of the first tuple
+ /// vendor-class[4491].data[3] - content of the opaque-data of the 4th tuple
+ class TokenVendorClass : public TokenVendor {
+ public:
+     /// @brief This constructor is used to access fields.
+     ///
+     /// @param u universe (V4 or V6)
+     /// @param vendor_id value of enterprise-id field (0 means any)
+     /// @param repr representation type (EXISTS or HEX)
+     TokenVendorClass(Option::Universe u, uint32_t vendor_id, RepresentationType repr);
+     /// @brief This constructor is used to access data chunks.
+     ///
+     /// @param u universe (V4 or V6)
+     /// @param vendor_id value of enterprise-id field (0 means any)
+     /// @param field type of the field (usually DATA or ENTERPRISE)
+     /// @param index specifies which data chunk to retrieve
+     TokenVendorClass(Option::Universe u, uint32_t vendor_id, FieldType field,
+                      uint16_t index = 0);
+     /// @brief Returns data index.
+     ///
+     /// Used in testing.
+     /// @return data index (specifies which data chunk to retrieve)
+     uint16_t getDataIndex() const;
+ protected:
+     /// @brief This is a method for evaluating a packet.
+     ///
+     /// Depending on the value of vendor_id, field type, representation and
+     /// option code, it will attempt to return specified characteristic of the
+     /// vendor option
+     ///
+     /// If vendor-id is specified, check only option with that particular
+     /// enterprise-id. If vendor-id is 0, check any vendor option, regardless
+     /// of its enterprise-id value.
+     ///
+     /// If FieldType is ENTERPRISE_ID, return value of the enterprise-id field
+     /// or "" if there's no vendor option.
+     ///
+     /// If FieldType is DATA, get specified data chunk represented by index_.
+     ///
+     /// If FieldType is EXISTS, return true if vendor-id matches.
+     ///
+     /// @throw EvalTypeError for any other FieldType values.
+     ///
+     /// The parameters passed are:
+     ///
+     /// @param pkt - vendor options will be searched for here.
+     /// @param values - the evaluated value will be pushed here.
+     void evaluate(Pkt& pkt, ValueStack& values);
+     /// @brief Data chunk index.
+     uint16_t index_;
+ };
  }; // end of isc::dhcp namespace
  }; // end of isc namespace