]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
Merge branch 'trac4269' Merge 4269 after updates to fix conflicts
authorShawn Routhier <sar@isc.org>
Fri, 15 Apr 2016 03:45:08 +0000 (03:45 +0000)
committerShawn Routhier <sar@isc.org>
Fri, 15 Apr 2016 03:45:08 +0000 (03:45 +0000)
1  2 
ChangeLog
doc/guide/classify.xml
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

diff --cc ChangeLog
index 93756ef67adce1057505715cbaf6f2955f58a3f3,1b6f5b8485b4099da84bfa377c75ab8cca9f87d9..7d9ddcb18b8bd3067b2f1a79c3653e2acc3dda70
+++ b/ChangeLog
@@@ -1,90 -1,8 +1,95 @@@
 -10xx. [func]          sar
++1106. [func]          sar
+       Added support for accessing DHCPv6 packet fields message type
+       and transaction id in a classification expression.
+       (Trac #4269, git <tbd>)
 +1105. [bug]           pallotron
 +      perfdhcp uses the same transaction id throughout the DORA
 +      exchange to adhere with RFC 2131.
 +      (github #19, git d260a70d6aa0baecd68131bc35f58f097aa77bcc)
 +
 +1104. [func]          tmark
 +      The DDNS parameter, replace-client-name, has been changed from a boolean
-       to list of modes, which provides greater flexibility in when the Kea 
++      to list of modes, which provides greater flexibility in when the Kea
 +      servers replace or supply DNS names for clients.  This is supported both
 +      kea-dhcp4 and kea-dhcp6.
 +      (Trac #4529, git 45e56d7aa0d4a6224a1a28941f6cb11575391222)
 +
 +1103. [func]          marcin
 +      "circuit-id" can be specified as host identifier in host
 +      host reservations. However, the server ignores the reservations
 +      by "circuit-id" at this point.
 +      (Trac #4301, git cf56fc2a2e0e821a17dd95de49a43755745682fb)
 +
 +1102. [func]          sar
 +      Added access to the peer address, link address and option
 +      information added by relays in a DHCPv6 message.
-       (Trac $4269, git bb00d9d205ee047961ba70417d7ce02c37d80ce7)
++      (Trac $4265, git bb00d9d205ee047961ba70417d7ce02c37d80ce7)
 +
 +1101. [bug]           stephen
 +      Made DHCPSRV_MEMFILE_LFC_UNREGISTER_TIMER_FAILED a debug message as the
 +      condition leading to it (trying to unregister a timer that is not
 +      registered) does not have an adverse effect on the operation of Kea.
 +      (Trac #4293, git 06204c5d347d0df359af69974c155d0fa9725b44)
 +
 +1100. [bug]           tmark
 +      Wrapped asio/asio.hpp with logic to suppress optimization when building
 +      under GCC 5.2.0 through 5.3.1 and BOOST_ERROR_CODE_HEADER only is defined.
 +      This avoids an issue in the asio socket layer that was incorrectly
 +      reporting socket read errors causing unit tests to fail and kea-dhcp-ddns
 +      to loop logger calls in the error handler (aka double errors).
 +      (Trac #4243, git 082f846f37cb32964c876b2bff5fcac82d1eaaf0)
 +
 +1099. [func]          marcin
 +      Updated Host Manager API to allow for retrieving host reservations
 +      by any type of host identifier. Previously it was only possible
 +      to retrieve host reservations by hardware address or DUID.
 +      (Trac #4302, git 3979656c918164e3c39e0e8fb78b2862a2b5e95a)
 +
 +1098. [func]          kalmus, marcin
 +      Implemented IPv6 address/prefix reservations in MySQL.
 +      (Trac #4212, git 79481043935789fc6898d4743bede1606f82eb75)
 +
 +1097. [func]          fdupont
 +      Reorganized the DHCPv4 and DHCPv6 services into run() (service
 +      loop), run_one() (receive, call next routine and send) and
 +      processPacket() (internal core processing of an incoming packet).
 +      (Trac #4108,#4266,#4267, git ba24bd770d1a1791f8fdc3df7f2e41f9f0c851ec)
 +
 +1096. [func]          tmark
 +      Both kea-dhcp4 and kea-dhcp6, now log the primary lease events (e.g.
 +      grants, renewals, releases, declines) at the INFO log level to the
 +      lease4_logger and lease6_logger repsectively.  Prior to this these
 +      events were logged at the DEBUG log level.
 +      (Trac #4316, git 9beca27e3d76d0ccec925125f23074227db08869)
 +
 +1095. [bug]           fdupont
 +      Fixed some minor Coverity-detected issues.
 +      (Trac #4326, git ad1f442ee4382b354dc8be84ba77785e565aa86b)
 +
 +1094. [bug]           marcin
 +      libdhcpsrv: Fixed issues with lease indexing in Memfile
 +      database backend.
 +      (Trac #4339, git a065144663ac716b1fa1c8c224a88aa176da9630)
 +
 +1093. [bug]           fdupont
 +      Fixed Coverity-detected overflows in pkt4::setFile() and setName().
 +      (Trac #4306, git 0b7388891eaab39fe727b076468d672551126796)
 +
 +1092. [func]          marcin
 +      DHCP option values can be specified within host reservations
 +      in the configuration file.
 +      (Trac #4319, git 069dd7c248afcfcb7e4d958f20faa32e946e74ce)
 +
 +1091. [bug]           fdupont
 +      Fixed Coverity-detected exception-handling issues.
 +      (Trac #4307, git 3e1050749d9684144e1bd17552af7e4abf3c0d17)
 +
 +1090. [func]          fdupont
 +      Added support for IP address (IPv4 and IPv6) literals in
 +      classification expressions.
 +      (Trac #4232, git b98cc019b172a4903a2121e910f3cee4eaca2d51)
 +
  1089. [func]          fdupont
        Added relay4[X].exists method in classifications that checks
        whether a sub-option is present in theDHCPv4 RAI (Relay Agent
index 77c4981e32bf641edb5101135e98ada46fb9bc55,bb9f7a06ae03349fdd46156e86f5427c67cb3ceb..76c310641b633292aab4121f43d117648b4faeb7
  sub-option</entry><entry>relay4[code].hex</entry><entry>The value of
  sub-option with code "code" from the DHCPv4 Relay Agent Information option
  (option 82)</entry></row>
 +<row>
 +  <entry>DHCPv6 Relay Options</entry>
 +  <entry>relay6[nest].option[code].hex</entry>
 +<!--  <entry>Value of the option</entry> -->
 +  <entry>The value of the option with code "code" from the relay encapsulation "nest"</entry>
 +</row>
 +<row>
 +  <entry>DHCPv6 Relay Peer Address</entry>
 +  <entry>relay6[nest].peeraddr</entry>
 +<!-- <entry>2001:DB8::1</entry> -->n
 +  <entry>The value of the peer address field from the relay encapsulation "nest"</entry>
 +</row>
 +<row>
 +  <entry>DHCPv6 Relay Link Address</entry>
 +  <entry>relay6[nest].linkaddr</entry>
 +<!-- <entry>2001:DB8::1</entry> -->n
 +  <entry>The value of the link address field from the relay encapsulation "nest"</entry>
++</row>
+ <row>
+   <entry>Message Type in DHCPv6 packet</entry>
+   <entry>pkt6.msgtype</entry>
+ <!--  <entry>1</entry>
+ -->
+   <entry>The value of the message type field in the DHCPv6 packet.</entry>
+ </row>
+ <row>
+   <entry>Transaction ID in DHCPv6 packet</entry>
+   <entry>pkt6.transid</entry>
+ <!--  <entry>12345</entry>
+ -->
+   <entry>The value of the transaction id in the DHCPv6 packet.</entry>
  </row>
            </tbody>
            </tgroup>
         instance "relay4[code].exists" is supported.
        </para>
  
 +      <para>
 +       "relay6[nest]" allows access to the encapsulations used by any DHCPv6
 +       relays that forwarded the packet.  The "nest" level specifies the relay
 +       from which to extract the information, with a value of 0 indicating
 +       the relay closest to the DHCPv6 server.  If the requested encapsulation
 +       doesn't exist an empty string "" is returned.  This expression is
 +       allowed in DHCPv6 only.
 +      </para>
 +
 +      <para>
 +       "relay6[nest].option[code]" shares the same representation types as
 +       "option", for instance "relay6[nest].option[code].exists" is supported.
 +      </para>
 +
+       <para>
+        "pkt6" refers to information from the client request.  To access any
+        information from an intermediate relay use "relay6".  "pkt6.msgtype"
+        and "pkt6.transid" output a 4 byte binary string for the message type
+        or transaction id.  For example the message type SOLICIT will be
+        "0x00000001" or simply 1 as in "pkt6.msgtype == 1".
+       </para>
        <para>
          <table frame="all" id="classification-expressions-list">
            <title>List of Classification Expressions</title>
index 25ba5f1f2ce59e49ecb043aa15b778b2231e9367,7a99903c3987066de3a63392ae90658b5490b57f..02ea9fa38801dcda66015dca36c07bf1a4c2031a
@@@ -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 30
- #define YY_END_OF_BUFFER 31
 -#define YY_NUM_RULES 29
 -#define YY_END_OF_BUFFER 30
++#define YY_NUM_RULES 33
++#define YY_END_OF_BUFFER 34
  /* 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[162] =
 -static yyconst flex_int16_t yy_acclist[152] =
++static yyconst flex_int16_t yy_acclist[183] =
      {   0,
-        31,   29,   30,    1,   29,   30,    2,   30,   29,   30,
-        24,   29,   30,   25,   29,   30,   28,   29,   30,   29,
-        30,   23,   29,   30,    5,   29,   30,    5,   29,   30,
-        29,   30,   29,   30,   29,   30,16390,   29,   30,16390,
-        26,   29,   30,   27,   29,   30,   29,   30,16390,   29,
-        30,16390,   29,   30,16390,   29,   30,16390,   29,   30,
-     16390,   29,   30,16390,   29,   30,16390,   29,   30,16390,
-        29,   30,16390,   29,   30,16390,   29,   30,16390,    1,
-         2,    3,    5,    5,    7,    8,16390,16390, 8198,16390,
-     16390,16390,16390,16390,16390,16390,16390,   22,16390,16390,
 -       30,   28,   29,    1,   28,   29,    2,   29,   28,   29,
 -       20,   28,   29,   21,   28,   29,   24,   28,   29,   28,
 -       29,   19,   28,   29,    5,   28,   29,    5,   28,   29,
 -       28,   29,   28,   29,16390,   22,   28,   29,   23,   28,
 -       29,   28,   29,16390,   28,   29,16390,   28,   29,16390,
 -       28,   29,16390,   28,   29,16390,   28,   29,16390,   28,
 -       29,16390,   28,   29,16390,   28,   29,16390,   28,   29,
 -    16390,   28,   29,16390,    1,    2,    3,    5,    7,16390,
 -     8198,16390,16390,16390,16390,16390,16390,16390,16390,   18,
 -    16390,16390,16390,16390,16390,16390,    4,   14,16390,   17,
--
-     16390,16390,16390,    4,    7,   18,16390,   21,16390,16390,
-     16390,   15,16390,16390,   20,16390,16390,16390,16390,16390,
-     16390,16390,16390,16390,16390,16390,16390,16390,   14,16390,
-     16390,16390,16390,16390,16390,16390,16390,   19,16390,   16,
-     16390,16390,    9,16390,16390,   10,16390,   11,16390,16390,
-         7,16390,16390,16390,   13,16390,   12,16390,16390,   17,
 -    16390,16390,16390,   11,16390,16390,   16,16390,16390,16390,
 -    16390,16390,16390,16390,16390,16390,16390,16390,   25,16390,
 -    16390,16390,   10,16390,16390,16390,16390,16390,16390,16390,
 -    16390,16390,   15,16390,   12,16390,16390,    8,16390,    9,
 -    16390,16390,16390,   26,16390,16390,   27,16390,16390,   13,
--    16390
++       34,   32,   33,    1,   32,   33,    2,   33,   32,   33,
++       24,   32,   33,   25,   32,   33,   28,   32,   33,   32,
++       33,   23,   32,   33,    5,   32,   33,    5,   32,   33,
++       32,   33,   32,   33,   32,   33,16390,   32,   33,16390,
++       26,   32,   33,   27,   32,   33,   32,   33,16390,   32,
++       33,16390,   32,   33,16390,   32,   33,16390,   32,   33,
++    16390,   32,   33,16390,   32,   33,16390,   32,   33,16390,
++       32,   33,16390,   32,   33,16390,   32,   33,16390,   32,
++       33,16390,    1,    2,    3,    5,    5,    7,    8,16390,
++    16390, 8198,16390,16390,16390,16390,16390,16390,16390,16390,
++
++    16390,   22,16390,16390,16390,16390,16390,16390,16390,    4,
++        7,   18,16390,   21,16390,16390,16390,   15,16390,16390,
++    16390,   20,16390,16390,16390,16390,16390,16390,16390,16390,
++    16390,16390,16390,16390,16390,16390,   29,16390,16390,16390,
++       14,16390,16390,16390,16390,16390,16390,16390,16390,16390,
++    16390,16390,   19,16390,   16,16390,16390,16390,    9,16390,
++    16390,   10,16390,   11,16390,16390,16390,    7,16390,   30,
++    16390,16390,16390,   31,16390,   13,16390,   12,16390,16390,
++       17,16390
      } ;
  
- static yyconst flex_int16_t yy_accept[114] =
 -static yyconst flex_int16_t yy_accept[99] =
++static yyconst flex_int16_t yy_accept[130] =
      {   0,
          1,    1,    1,    2,    4,    7,    9,   11,   14,   17,
 -       20,   22,   25,   28,   31,   33,   36,   39,   42,   45,
 -       48,   51,   54,   57,   60,   63,   66,   69,   72,   75,
 -       76,   77,   77,   78,   79,   79,   80,   80,   80,   81,
 -       82,   83,   84,   85,   86,   87,   88,   89,   90,   92,
 -       93,   94,   95,   96,   97,   98,  100,  102,  103,  104,
 -      106,  107,  109,  110,  111,  112,  113,  114,  115,  116,
 -      117,  118,  119,  121,  122,  123,  125,  126,  127,  128,
 -      129,  130,  131,  132,  133,  135,  137,  138,  140,  142,
 -      143,  144,  146,  147,  149,  150,  152,  152
 -
 +       20,   22,   25,   28,   31,   33,   35,   38,   41,   44,
 +       47,   50,   53,   56,   59,   62,   65,   68,   71,   74,
-        77,   80,   81,   82,   82,   83,   84,   84,   85,   85,
-        85,   85,   85,   86,   87,   87,   87,   88,   89,   90,
-        91,   92,   93,   94,   95,   96,   97,   98,  100,  101,
-       102,  103,  104,  104,  105,  106,  108,  110,  111,  112,
-       114,  115,  117,  118,  119,  120,  121,  122,  122,  123,
-       124,  125,  126,  127,  128,  129,  131,  131,  132,  133,
-       134,  135,  136,  137,  138,  138,  140,  142,  143,  145,
-       146,  148,  150,  151,  152,  153,  154,  155,  157,  159,
-       160,  162,  162
++       77,   80,   83,   84,   85,   85,   86,   87,   87,   88,
++       88,   88,   88,   88,   89,   90,   90,   90,   91,   92,
++       93,   94,   95,   96,   97,   98,   99,  100,  101,  102,
++      104,  105,  106,  107,  108,  109,  110,  110,  111,  112,
++      114,  116,  117,  118,  120,  121,  122,  124,  125,  126,
++      127,  128,  129,  130,  131,  131,  132,  133,  134,  135,
++      136,  137,  139,  140,  141,  143,  144,  144,  145,  146,
++
++      147,  148,  149,  150,  151,  152,  153,  153,  155,  157,
++      158,  159,  161,  162,  164,  166,  167,  168,  169,  170,
++      172,  173,  174,  176,  178,  180,  181,  183,  183
      } ;
  
  static yyconst YY_CHAR yy_ec[256] =
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
          1,    2,    1,    1,    1,    1,    1,    1,    4,    5,
          6,    1,    1,    7,    8,    9,    1,   10,   11,   11,
 -       11,   12,   11,   13,   11,   11,   11,    1,    1,    1,
 -       14,    1,    1,    1,   15,   15,   15,   15,   15,   15,
 -       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
 -       16,   16,   16,   16,   16,   16,   16,   17,   16,   16,
 -       18,    1,   19,    1,   20,    1,   21,   22,   23,   24,
 -
 -       25,   15,   26,   27,   28,   16,   29,   30,   31,   32,
 -       33,   34,   16,   35,   36,   37,   38,   16,   16,   39,
 -       40,   16,    1,    1,    1,    1,    1,    1,    1,    1,
 +       11,   12,   11,   13,   11,   11,   11,   14,    1,    1,
 +       15,    1,    1,    1,   16,   16,   16,   16,   16,   16,
 +       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
 +       17,   17,   17,   17,   17,   17,   17,   18,   17,   17,
 +       19,    1,   20,    1,   21,    1,   22,   23,   24,   25,
 +
-        26,   16,   27,   28,   29,   17,   30,   31,   17,   32,
-        33,   34,   17,   35,   36,   37,   38,   17,   17,   39,
-        40,   17,    1,    1,    1,    1,    1,    1,    1,    1,
++       26,   16,   27,   28,   29,   17,   30,   31,   32,   33,
++       34,   35,   17,   36,   37,   38,   39,   17,   17,   40,
++       41,   17,    1,    1,    1,    1,    1,    1,    1,    1,
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
          1,    1,    1,    1,    1
      } ;
  
--static yyconst YY_CHAR yy_meta[41] =
++static yyconst YY_CHAR yy_meta[42] =
      {   0,
 -        1,    2,    3,    1,    1,    1,    1,    2,    1,    4,
 -        4,    4,    4,    1,    5,    2,    6,    1,    2,    2,
 -        5,    5,    5,    5,    5,    2,    2,    2,    2,    2,
 -        2,    2,    2,    2,    2,    2,    2,    2,    6,    2
 +        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,    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 flex_uint16_t yy_base[118] =
 -static yyconst flex_uint16_t yy_base[102] =
++static yyconst flex_uint16_t yy_base[134] =
      {   0,
-         0,    0,  220,  221,  217,  215,  213,  221,  221,  221,
-        31,  221,   36,   33,  202,  200,   74,  105,  221,  221,
-        24,  181,  174,  186,  182,  177,   29,  183,  182,  169,
-       180,  203,  201,  199,  221,   55,   68,   35,  188,  187,
-         0,  186,    0,  221,  120,  122,    0,    0,  221,  168,
-       173,  165,  167,  156,  162,  156,  155,    0,  165,  159,
-       166,  149,  123,    0,    0,    0,    0,  163,  150,    0,
-       155,    0,  155,  148,  160,  145,  143,  133,  157,  141,
-       155,  143,  153,  134,  136,    0,  138,  135,  125,  116,
-       107,  113,   57,  102,  142,    0,    0,  101,    0,   95,
 -        0,    0,  122,  289,  103,   82,   70,  289,  289,  289,
 -       31,  289,   28,   36,   59,   49,  289,  289,   68,   23,
 -       33,   29,   28,   45,   49,   60,   61,   64,   74,   64,
 -       59,   46,  289,  100,    0,  289,  105,  112,   50,  289,
 -       65,   93,   71,   88,   89,  100,   97,  103,  106,  109,
 -      113,  125,  119,  129,    0,  122,  130,  133,  134,  137,
 -      141,  142,  147,  155,  159,  152,  160,  151,  172,  164,
 -      168,  173,  177,  180,  181,  184,  185,  192,  195,  196,
 -      202,  207,  203,  212,  211,  215,  221,  218,  222,  227,
 -      232,  228,  231,  235,  240,  239,  289,  272,  275,  280,
--
-         0,    0,   64,  146,   54,   48,   41,    0,    0,   44,
-         0,  221,  159,  161,  163,   53,  166
 -      283
++        0,    0,  237,  238,  234,  232,  230,  238,  238,  238,
++       32,  238,   37,   34,  219,  217,   76,  108,  238,  238,
++       23,  197,  190,  203,  199,  190,  192,   22,   38,  199,
++      185,   39,  221,  219,  217,  238,   59,   70,   55,  206,
++      205,    0,  204,    0,  238,  123,  125,    0,    0,  238,
++      186,  191,  182,  185,  173,  179,  184,  172,  171,    0,
++      182,  169,  175,  182,  164,  181,  126,    0,    0,    0,
++        0,  178,  164,    0,  170,  161,    0,  169,  161,  183,
++      173,  157,  155,  159,  136,  169,  152,  167,  147,  153,
++      164,    0,  144,  146,    0,  146,  141,  144,  144,  155,
++
++      144,  145,  152,   54,  140,  146,  145,    0,    0,  139,
++      118,    0,  117,    0,    0,  112,  115,  149,   93,    0,
++       87,   58,    0,    0,    0,   58,    0,  238,  162,  164,
++      166,   72,  169
      } ;
  
- static yyconst flex_int16_t yy_def[118] =
 -static yyconst flex_int16_t yy_def[102] =
++static yyconst flex_int16_t yy_def[134] =
      {   0,
-       112,    1,  112,  112,  112,  112,  113,  112,  112,  112,
-       112,  112,  112,   13,  114,  112,  112,   17,  112,  112,
 -       97,    1,   97,   97,   97,   97,   98,   97,   97,   97,
 -       97,   97,   99,   97,   97,  100,   97,   97,  100,   19,
 -       19,   19,   19,   19,   19,   19,   19,   19,   19,   97,
 -       97,   98,   97,   97,  101,   97,   97,   19,   19,   97,
 -       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,  101,   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,   19,   19,   19,   19,   19,
 -       19,   19,   19,   19,   19,   19,    0,   97,   97,   97,
 -
 -       97
++      128,    1,  128,  128,  128,  128,  129,  128,  128,  128,
++      128,  128,  128,   13,  130,  128,  128,   17,  128,  128,
 +       17,   17,   17,   18,   18,   18,   18,   18,   18,   18,
-        18,  112,  112,  113,  112,  112,  112,   13,  114,  115,
-       116,  114,  117,  112,  112,   18,   17,   18,  112,   18,
++       18,   18,  128,  128,  129,  128,  128,  128,   13,  130,
++      131,  132,  130,  133,  128,  128,   18,   17,   18,  128,
++       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,   18,   18,  128,  132,  133,   18,
 +       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,  112,  116,  117,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,   18,  112,   18,   18,
-        18,   18,   18,   18,   18,   18,  112,   18,   18,   18,
-        18,   18,   18,   18,  112,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,  128,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,   18,   18,  128,   18,   18,   18,
 +
-        18,   18,   18,  112,   18,   18,   18,   18,   18,   18,
-        18,    0,  112,  112,  112,  112,  112
++       18,   18,   18,   18,   18,   18,  128,   18,   18,   18,
++       18,   18,   18,   18,   18,   18,   18,  128,   18,   18,
++       18,   18,   18,   18,   18,   18,   18,    0,  128,  128,
++      128,  128,  128
      } ;
  
- static yyconst flex_uint16_t yy_nxt[262] =
 -static yyconst flex_uint16_t yy_nxt[330] =
++static yyconst flex_uint16_t yy_nxt[280] =
      {   0,
          4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
 -       14,   14,   14,   15,   16,   16,   16,   17,   18,    4,
 -       19,   16,   20,   16,   21,   16,   22,   16,   16,   16,
 -       23,   24,   25,   26,   27,   28,   29,   16,   16,   16,
 -       34,   34,   34,   34,   35,   34,   34,   34,   34,   33,
 -       37,   37,   39,   45,   39,   43,   38,   39,   39,   39,
 -       39,   31,   39,   46,   39,   30,   35,   40,   38,   37,
 -       37,   44,   36,   33,   39,   38,   39,   47,   39,   39,
 -       39,   39,   48,   49,   31,   51,   40,   38,   50,   39,
 -       39,   39,   39,   39,   56,   39,   39,   41,   53,   42,
 -
 -       39,   52,   58,   39,   30,   39,   37,   37,   54,   34,
 -       34,   34,   34,   97,   97,   59,   57,   39,   39,   39,
 -       39,   97,   39,   40,   39,   61,   39,   60,   39,   39,
 -       97,   39,   39,   62,   39,   39,   97,   39,   39,   63,
 -       39,   39,   65,   39,   39,   64,   66,   97,   39,   68,
 -       39,   39,   97,   39,   39,   69,   39,   67,   39,   39,
 -       39,   39,   39,   39,   39,   39,   39,   73,   39,   70,
 -       39,   39,   39,   39,   72,   97,   39,   71,   39,   74,
 -       39,   39,   77,   39,   39,   97,   39,   75,   39,   39,
 -       39,   39,   78,   39,   97,   39,   76,   39,   97,   39,
 -
 -       79,   39,   39,   39,   39,   81,   39,   80,   39,   39,
 -       39,   39,   39,   39,   39,   39,   39,   83,   89,   82,
 -       84,   39,   97,   39,   39,   39,   39,   39,   85,   87,
 -       86,   39,   39,   88,   39,   97,   39,   90,   39,   91,
 -       39,   39,   39,   39,   39,   92,   39,   39,   97,   39,
 -       39,   39,   39,   39,   93,   94,   39,   39,   39,   39,
 -       39,   39,   95,   39,   39,   96,   39,   97,   39,   39,
 -       39,   39,   32,   32,   97,   32,   32,   32,   34,   97,
 -       34,   39,   39,   39,   39,   39,   55,   55,    3,   97,
 -       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
 -
 -       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
 -       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
 -       97,   97,   97,   97,   97,   97,   97,   97,   97
 +       14,   14,   14,   15,   16,   17,   18,   18,   19,   20,
 +        4,   21,   17,   22,   17,   23,   18,   24,   18,   18,
-        25,   26,   27,   28,   29,   30,   31,   18,   18,   18,
-        36,   36,   36,   36,   37,   38,   38,   38,   38,   39,
-       112,   40,  112,   41,   50,   51,   64,   40,   40,   40,
-        40,   40,   57,   58,   36,   36,   36,   36,  101,  102,
-       111,  112,  110,  112,   41,   45,   45,   63,   63,   63,
-        63,   46,  109,   47,   47,   47,   47,   39,  108,   47,
-        48,   48,  107,   49,   46,   47,   47,   47,   47,   47,
-        48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-        48,   48,   48,   48,   48,   48,   48,   48,  112,  106,
-        48,   45,   45,  112,  112,  105,   48,   48,   48,   48,
-        48,   78,   63,   63,   63,   63,  103,  100,   99,   49,
-        98,  112,   87,   87,   87,   87,   95,   87,   87,   87,
-        87,  104,  104,  104,  104,  104,  104,  104,  104,   34,
-        97,   34,   34,   34,   42,   42,   40,   40,   65,   65,
-        65,   96,   94,   93,   92,   91,   90,   89,   88,   86,
-        85,   84,   83,   82,   81,   80,   79,   77,   76,   75,
-        74,   73,   72,   71,   70,   69,   68,   67,   66,   43,
-        39,   43,   35,   33,   32,   62,   61,   60,   59,   56,
-        55,   54,   53,   52,   44,   43,   35,   33,   32,  112,
-         3,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112
++       25,   26,   27,   28,   29,   30,   31,   32,   18,   18,
++       18,   37,   37,   37,   37,   38,   39,   39,   39,   39,
++       40,  128,   41,   51,   42,   52,   59,   60,   41,   41,
++       41,   41,   41,   61,   65,  114,  115,   62,   37,   37,
++       37,   37,  128,  128,   66,   68,   42,   46,   46,   67,
++       67,   67,   67,   47,  127,   48,   48,   48,   48,   40,
++      126,   48,   49,   49,  128,   50,   47,   48,   48,   48,
++
++       48,   48,   49,   49,   49,   49,   49,   49,   49,   49,
++       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
++       49,  128,  125,   49,   46,   46,  128,  128,  124,   49,
++       49,   49,   49,   49,   85,   67,   67,   67,   67,  123,
++      122,  121,   50,  120,  128,   97,   97,   97,   97,  107,
++       97,   97,   97,   97,  118,  118,  118,  118,  118,  118,
++      118,  118,   35,  119,   35,   35,   35,   43,   43,   41,
++       41,   69,   69,   69,  117,  116,  113,  112,  111,  110,
++      109,  108,  106,  105,  104,  103,  102,  101,  100,   99,
++       98,   96,   95,   94,   93,   92,   91,   90,   89,   88,
++
++       87,   86,   84,   83,   82,   81,   80,   79,   78,   77,
++       76,   75,   74,   73,   72,   71,   70,   44,   40,   44,
++       36,   34,   33,   64,   63,   58,   57,   56,   55,   54,
++       53,   45,   44,   36,   34,   33,  128,    3,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128
      } ;
  
- static yyconst flex_int16_t yy_chk[262] =
 -static yyconst flex_int16_t yy_chk[330] =
++static yyconst flex_int16_t yy_chk[280] =
      {   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,
-        11,   11,   11,   11,   13,   13,   13,   13,   13,   13,
-        14,   13,   38,   13,   21,   21,  116,   13,   13,   13,
-        13,   13,   27,   27,   36,   36,   36,   36,   93,   93,
-       110,   14,  107,   38,   13,   17,   17,   37,   37,   37,
-        37,   17,  106,   17,   17,   17,   17,   17,  105,   17,
-        17,   17,  103,   17,   17,   17,   17,   17,   17,   17,
 -       11,   11,   11,   11,   13,   14,   14,   14,   14,   32,
 -       16,   16,   20,   22,   20,   20,   16,   23,   22,   23,
 -       22,   31,   21,   23,   21,   30,   13,   16,   16,   19,
 -       19,   21,   15,    7,   24,   19,   24,   24,   25,   39,
 -       25,   39,   25,   25,    6,   27,   19,   19,   26,   26,
 -       27,   26,   27,   28,   41,   28,   41,   19,   29,   19,
 -
 -       43,   28,   43,   29,    5,   29,   37,   37,   29,   34,
 -       34,   34,   34,   38,   38,   44,   42,   44,   45,   44,
 -       45,    3,   42,   37,   42,   46,   47,   45,   47,   46,
 -       38,   46,   48,   47,   48,   49,    0,   49,   50,   48,
 -       50,   38,   51,   38,   51,   50,   52,    0,   53,   54,
 -       53,   56,    0,   56,   52,   58,   52,   53,   54,   57,
 -       54,   57,   58,   59,   58,   59,   60,   64,   60,   59,
 -       61,   62,   61,   62,   63,    0,   63,   61,   63,   65,
 -       68,   66,   68,   66,   64,    0,   64,   66,   65,   67,
 -       65,   67,   69,   70,    0,   70,   67,   71,    0,   71,
 -
 -       70,   69,   72,   69,   72,   72,   73,   71,   73,   74,
 -       75,   74,   75,   76,   77,   76,   77,   75,   82,   74,
 -       77,   78,    0,   78,   79,   80,   79,   80,   78,   80,
 -       79,   81,   83,   81,   83,    0,   82,   83,   82,   84,
 -       85,   84,   85,   84,   86,   87,   86,   88,    0,   88,
 -       87,   89,   87,   89,   90,   91,   90,   92,   90,   92,
 -       93,   91,   93,   91,   94,   95,   94,    0,   96,   95,
 -       96,   95,   98,   98,    0,   98,   98,   98,   99,    0,
 -       99,  100,  100,  100,  100,  100,  101,  101,   97,   97,
 -       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
 -
 -       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
 -       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
 -       97,   97,   97,   97,   97,   97,   97,   97,   97
++        1,   11,   11,   11,   11,   13,   13,   13,   13,   13,
++       13,   14,   13,   21,   13,   21,   28,   28,   13,   13,
++       13,   13,   13,   29,   32,  104,  104,   29,   37,   37,
++       37,   37,   39,   14,   32,  132,   13,   17,   17,   38,
++       38,   38,   38,   17,  126,   17,   17,   17,   17,   17,
++      122,   17,   17,   17,   39,   17,   17,   17,   17,   17,
 +
 +       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-        17,   17,   17,   17,   18,   18,   18,   18,   18,  100,
-        18,   45,   45,   46,   46,   98,   18,   18,   18,   18,
-        18,   63,   63,   63,   63,   63,   94,   92,   91,   45,
-        90,   46,   78,   78,   78,   78,   87,   87,   87,   87,
-        87,   95,   95,   95,   95,  104,  104,  104,  104,  113,
-        89,  113,  113,  113,  114,  114,  115,  115,  117,  117,
-       117,   88,   85,   84,   83,   82,   81,   80,   79,   77,
-        76,   75,   74,   73,   71,   69,   68,   62,   61,   60,
-        59,   57,   56,   55,   54,   53,   52,   51,   50,   42,
-        40,   39,   34,   33,   32,   31,   30,   29,   28,   26,
-        25,   24,   23,   22,   16,   15,    7,    6,    5,    3,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-       112
++       17,   17,   17,   17,   17,   17,   17,   18,   18,   18,
++       18,   18,  121,   18,   46,   46,   47,   47,  119,   18,
++       18,   18,   18,   18,   67,   67,   67,   67,   67,  117,
++      116,  113,   46,  111,   47,   85,   85,   85,   85,   97,
++       97,   97,   97,   97,  107,  107,  107,  107,  118,  118,
++      118,  118,  129,  110,  129,  129,  129,  130,  130,  131,
++      131,  133,  133,  133,  106,  105,  103,  102,  101,  100,
++       99,   98,   96,   94,   93,   91,   90,   89,   88,   87,
++       86,   84,   83,   82,   81,   80,   79,   78,   76,   75,
++
++       73,   72,   66,   65,   64,   63,   62,   61,   59,   58,
++       57,   56,   55,   54,   53,   52,   51,   43,   41,   40,
++       35,   34,   33,   31,   30,   27,   26,   25,   24,   23,
++       22,   16,   15,    7,    6,    5,    3,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
++      128,  128,  128,  128,  128,  128,  128,  128,  128
      } ;
  
  /* Table of booleans, true if rule could match eol. */
- static yyconst flex_int32_t yy_rule_can_match_eol[31] =
 -static yyconst flex_int32_t yy_rule_can_match_eol[30] =
++static yyconst flex_int32_t yy_rule_can_match_eol[34] =
      {   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,     };
  
  extern int yy_flex_debug;
  int yy_flex_debug = 1;
  
- static yyconst flex_int16_t yy_rule_linenum[30] =
 -static yyconst flex_int16_t yy_rule_linenum[29] =
++static yyconst flex_int16_t yy_rule_linenum[33] =
      {   0,
 -       78,   82,   88,   98,  104,  118,  125,  126,  127,  128,
 -      129,  130,  131,  132,  133,  134,  135,  136,  137,  138,
 -      139,  140,  141,  142,  144,  145,  146,  148
 +       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,  165
++      156,  157,  158,  159,  160,  161,  162,  163,  165,  166,
++      167,  169
      } ;
  
  static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@@ -763,7 -770,7 +774,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 767 "lexer.cc"
 -#line 774 "lexer.cc"
++#line 778 "lexer.cc"
  
  #define INITIAL 0
  
@@@ -1060,7 -1067,7 +1071,7 @@@ YY_DEC
      loc.step();
  
  
- #line 1064 "lexer.cc"
 -#line 1071 "lexer.cc"
++#line 1075 "lexer.cc"
  
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@@ -1088,14 -1095,14 +1099,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 >= 113 )
 -                              if ( yy_current_state >= 98 )
++                              if ( yy_current_state >= 129 )
                                        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 != 112 );
 -              while ( yy_current_state != 97 );
++              while ( yy_current_state != 128 );
  
  yy_find_action:
  /* %% [10.0] code to find the action number goes here */
@@@ -1158,13 -1165,13 +1169,13 @@@ do_action:   /* This label is used only t
                        {
                        if ( yy_act == 0 )
                                fprintf( stderr, "--scanner backing up\n" );
-                       else if ( yy_act < 30 )
 -                      else if ( yy_act < 29 )
++                      else if ( yy_act < 33 )
                                fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
                                         (long)yy_rule_linenum[yy_act], yytext );
-                       else if ( yy_act == 30 )
 -                      else if ( yy_act == 29 )
++                      else if ( yy_act == 33 )
                                fprintf( stderr, "--accepting default rule (\"%s\")\n",
                                         yytext );
-                       else if ( yy_act == 31 )
 -                      else if ( yy_act == 30 )
++                      else if ( yy_act == 34 )
                                fprintf( stderr, "--(end of buffer or a NUL)\n" );
                        else
                                fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@@ -1360,24 -1355,19 +1371,39 @@@ return isc::eval::EvalParser::make_RBRA
        YY_BREAK
  case 28:
  YY_RULE_SETUP
 -#line 148 "lexer.ll"
 +#line 163 "lexer.ll"
 +return isc::eval::EvalParser::make_COMA(loc);
 +      YY_BREAK
 +case 29:
 +YY_RULE_SETUP
 +#line 165 "lexer.ll"
++return isc::eval::EvalParser::make_PKT6(loc);
++      YY_BREAK
++case 30:
++YY_RULE_SETUP
++#line 166 "lexer.ll"
++return isc::eval::EvalParser::make_MSGTYPE(loc);
++      YY_BREAK
++case 31:
++YY_RULE_SETUP
++#line 167 "lexer.ll"
++return isc::eval::EvalParser::make_TRANSID(loc);
++      YY_BREAK
++case 32:
++YY_RULE_SETUP
++#line 169 "lexer.ll"
  driver.error (loc, "Invalid character: " + std::string(yytext));
        YY_BREAK
  case YY_STATE_EOF(INITIAL):
- #line 166 "lexer.ll"
 -#line 149 "lexer.ll"
++#line 170 "lexer.ll"
  return isc::eval::EvalParser::make_END(loc);
        YY_BREAK
- case 30:
 -case 29:
++case 33:
  YY_RULE_SETUP
- #line 167 "lexer.ll"
 -#line 150 "lexer.ll"
++#line 171 "lexer.ll"
  ECHO;
        YY_BREAK
- #line 1381 "lexer.cc"
 -#line 1371 "lexer.cc"
++#line 1407 "lexer.cc"
  
        case YY_END_OF_BUFFER:
                {
@@@ -1662,7 -1652,7 +1688,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 >= 113 )
 -                      if ( yy_current_state >= 98 )
++                      if ( yy_current_state >= 129 )
                                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 >= 113 )
 -              if ( yy_current_state >= 98 )
++              if ( yy_current_state >= 129 )
                        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 == 112);
 -      yy_is_jam = (yy_current_state == 97);
++      yy_is_jam = (yy_current_state == 128);
        if ( ! yy_is_jam )
                *(yy_state_ptr)++ = yy_current_state;
  
@@@ -2460,7 -2450,7 +2486,7 @@@ void yyfree (void * ptr 
  
  /* %ok-for-header */
  
- #line 167 "lexer.ll"
 -#line 150 "lexer.ll"
++#line 171 "lexer.ll"
  
  
  
Simple merge
index 3231b15b78d463794f47857e71d722d9a951407a,009fe693481e3535c253fc0b6cd81d7d9031c58c..fa8038cfc69da0ccd198ad71aeb0a4c3f140931b
@@@ -251,30 -251,25 +251,34 @@@ namespace isc { namespace eval 
    {
        switch (that.type_get ())
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          value.move< TokenOption::RepresentationType > (that.value);
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         value.move< TokenPkt6::FieldType > (that.value);
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        value.move< TokenRelay6Field::FieldType > (that.value);
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          value.move< std::string > (that.value);
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          value.move< uint16_t > (that.value);
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        value.move< uint8_t > (that.value);
 +        break;
 +
        default:
          break;
      }
      state = that.state;
        switch (that.type_get ())
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          value.copy< TokenOption::RepresentationType > (that.value);
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         value.copy< TokenPkt6::FieldType > (that.value);
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        value.copy< TokenRelay6Field::FieldType > (that.value);
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          value.copy< std::string > (that.value);
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          value.copy< uint16_t > (that.value);
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        value.copy< uint8_t > (that.value);
 +        break;
 +
        default:
          break;
      }
          << yysym.location << ": ";
      switch (yytype)
      {
--            case 24: // "constant string"
++            case 27: // "constant string"
 +
- #line 78 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< std::string > (); }
- #line 358 "parser.cc" // lalr1.cc:636
++#line 366 "parser.cc" // lalr1.cc:636
 +        break;
 +
-       case 25: // "integer"
++      case 28: // "integer"
  
- #line 78 "parser.yy" // lalr1.cc:636
 -#line 76 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 365 "parser.cc" // lalr1.cc:636
 -#line 348 "parser.cc" // lalr1.cc:636
++#line 373 "parser.cc" // lalr1.cc:636
          break;
  
-       case 26: // "constant hexstring"
 -      case 25: // "integer"
++      case 29: // "constant hexstring"
  
- #line 78 "parser.yy" // lalr1.cc:636
 -#line 76 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 372 "parser.cc" // lalr1.cc:636
 -#line 355 "parser.cc" // lalr1.cc:636
++#line 380 "parser.cc" // lalr1.cc:636
          break;
  
-       case 27: // "option name"
 -      case 26: // "constant hexstring"
++      case 30: // "option name"
  
- #line 78 "parser.yy" // lalr1.cc:636
 -#line 76 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 379 "parser.cc" // lalr1.cc:636
 -#line 362 "parser.cc" // lalr1.cc:636
++#line 387 "parser.cc" // lalr1.cc:636
          break;
  
-       case 28: // "ip address"
 -      case 27: // "option name"
++      case 31: // "ip address"
  
- #line 78 "parser.yy" // lalr1.cc:636
 -#line 76 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 386 "parser.cc" // lalr1.cc:636
 -#line 369 "parser.cc" // lalr1.cc:636
++#line 394 "parser.cc" // lalr1.cc:636
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
  
- #line 78 "parser.yy" // lalr1.cc:636
 -#line 76 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< uint16_t > (); }
- #line 393 "parser.cc" // lalr1.cc:636
 -#line 376 "parser.cc" // lalr1.cc:636
++#line 401 "parser.cc" // lalr1.cc:636
          break;
  
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
  
- #line 78 "parser.yy" // lalr1.cc:636
 -#line 76 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
- #line 400 "parser.cc" // lalr1.cc:636
 -#line 383 "parser.cc" // lalr1.cc:636
++#line 408 "parser.cc" // lalr1.cc:636
 +        break;
 +
-       case 37: // relay6_field
++      case 40: // relay6_field
 +
- #line 78 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< TokenRelay6Field::FieldType > (); }
- #line 407 "parser.cc" // lalr1.cc:636
++#line 415 "parser.cc" // lalr1.cc:636
          break;
  
-       case 38: // nest_level
 -      case 36: // pkt6_field
++      case 41: // nest_level
 +
- #line 78 "parser.yy" // lalr1.cc:636
++#line 82 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< uint8_t > (); }
- #line 414 "parser.cc" // lalr1.cc:636
++#line 422 "parser.cc" // lalr1.cc:636
++        break;
 -#line 76 "parser.yy" // lalr1.cc:636
++      case 42: // pkt6_field
++
++#line 82 "parser.yy" // lalr1.cc:636
+         { yyoutput << yysym.value.template as< TokenPkt6::FieldType > (); }
 -#line 390 "parser.cc" // lalr1.cc:636
++#line 429 "parser.cc" // lalr1.cc:636
          break;
  
  
           when using variants.  */
          switch (yyr1_[yyn])
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          yylhs.value.build< TokenOption::RepresentationType > ();
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         yylhs.value.build< TokenPkt6::FieldType > ();
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        yylhs.value.build< TokenRelay6Field::FieldType > ();
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          yylhs.value.build< std::string > ();
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          yylhs.value.build< uint16_t > ();
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        yylhs.value.build< uint8_t > ();
 +        break;
 +
        default:
          break;
      }
            switch (yyn)
              {
    case 4:
- #line 92 "parser.yy" // lalr1.cc:859
 -#line 90 "parser.yy" // lalr1.cc:859
++#line 96 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenNot());
                      ctx.expression.push_back(neg);
                  }
- #line 661 "parser.cc" // lalr1.cc:859
 -#line 632 "parser.cc" // lalr1.cc:859
++#line 680 "parser.cc" // lalr1.cc:859
      break;
  
    case 5:
- #line 97 "parser.yy" // lalr1.cc:859
 -#line 95 "parser.yy" // lalr1.cc:859
++#line 101 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenAnd());
                      ctx.expression.push_back(neg);
                  }
- #line 670 "parser.cc" // lalr1.cc:859
 -#line 641 "parser.cc" // lalr1.cc:859
++#line 689 "parser.cc" // lalr1.cc:859
      break;
  
    case 6:
- #line 102 "parser.yy" // lalr1.cc:859
 -#line 100 "parser.yy" // lalr1.cc:859
++#line 106 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenOr());
                      ctx.expression.push_back(neg);
                  }
- #line 679 "parser.cc" // lalr1.cc:859
 -#line 650 "parser.cc" // lalr1.cc:859
++#line 698 "parser.cc" // lalr1.cc:859
      break;
  
    case 7:
- #line 107 "parser.yy" // lalr1.cc:859
 -#line 105 "parser.yy" // lalr1.cc:859
++#line 111 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr eq(new TokenEqual());
                      ctx.expression.push_back(eq);
                  }
- #line 688 "parser.cc" // lalr1.cc:859
 -#line 659 "parser.cc" // lalr1.cc:859
++#line 707 "parser.cc" // lalr1.cc:859
      break;
  
    case 8:
- #line 112 "parser.yy" // lalr1.cc:859
 -#line 110 "parser.yy" // lalr1.cc:859
++#line 116 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
                      ctx.expression.push_back(opt);
                  }
- #line 697 "parser.cc" // lalr1.cc:859
 -#line 668 "parser.cc" // lalr1.cc:859
++#line 716 "parser.cc" // lalr1.cc:859
      break;
  
    case 9:
- #line 117 "parser.yy" // lalr1.cc:859
 -#line 115 "parser.yy" // lalr1.cc:859
++#line 121 "parser.yy" // lalr1.cc:859
      {
                     switch (ctx.getUniverse()) {
                     case Option::V4:
                         error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                     }
                  }
- #line 721 "parser.cc" // lalr1.cc:859
 -#line 692 "parser.cc" // lalr1.cc:859
++#line 740 "parser.cc" // lalr1.cc:859
      break;
  
    case 10:
--#line 137 "parser.yy" // lalr1.cc:859
++#line 141 "parser.yy" // lalr1.cc:859
 +    {
 +                    switch (ctx.getUniverse()) {
 +                    case Option::V6:
 +                    {
 +                        TokenPtr opt(new TokenRelay6Option(yystack_[8].value.as< uint8_t > (), yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
 +                        ctx.expression.push_back(opt);
 +                        break;
 +                    }
 +                    case Option::V4:
 +                        // For now we only use relay6 in DHCPv6.
 +                        error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
 +                    }
 +                }
- #line 739 "parser.cc" // lalr1.cc:859
++#line 758 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 11:
- #line 153 "parser.yy" // lalr1.cc:859
++#line 157 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(str);
                    }
- #line 748 "parser.cc" // lalr1.cc:859
 -#line 701 "parser.cc" // lalr1.cc:859
++#line 767 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 11:
 -#line 142 "parser.yy" // lalr1.cc:859
 +  case 12:
- #line 158 "parser.yy" // lalr1.cc:859
++#line 162 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(hex);
                    }
- #line 757 "parser.cc" // lalr1.cc:859
 -#line 710 "parser.cc" // lalr1.cc:859
++#line 776 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 12:
 -#line 147 "parser.yy" // lalr1.cc:859
 +  case 13:
- #line 163 "parser.yy" // lalr1.cc:859
++#line 167 "parser.yy" // lalr1.cc:859
 +    {
 +                      TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ()));
 +                      ctx.expression.push_back(ip);
 +                  }
- #line 766 "parser.cc" // lalr1.cc:859
++#line 785 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 14:
- #line 168 "parser.yy" // lalr1.cc:859
++#line 172 "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 775 "parser.cc" // lalr1.cc:859
 -#line 719 "parser.cc" // lalr1.cc:859
++#line 794 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 13:
 -#line 152 "parser.yy" // lalr1.cc:859
 +  case 15:
- #line 173 "parser.yy" // lalr1.cc:859
++#line 177 "parser.yy" // lalr1.cc:859
      {
                       switch (ctx.getUniverse()) {
                       case Option::V4:
                           error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                       }
                    }
- #line 799 "parser.cc" // lalr1.cc:859
 -#line 743 "parser.cc" // lalr1.cc:859
++#line 818 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 14:
 -#line 172 "parser.yy" // lalr1.cc:859
 +  case 16:
- #line 194 "parser.yy" // lalr1.cc:859
++#line 198 "parser.yy" // lalr1.cc:859
 +    {
 +                     switch (ctx.getUniverse()) {
 +                     case Option::V6:
 +                     {
 +                         TokenPtr opt(new TokenRelay6Option(yystack_[8].value.as< uint8_t > (), yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ()));
 +                         ctx.expression.push_back(opt);
 +                         break;
 +                     }
 +                     case Option::V4:
 +                         // For now we only use relay6 in DHCPv6.
 +                         error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
 +                     }
 +                  }
- #line 817 "parser.cc" // lalr1.cc:859
++#line 836 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 17:
- #line 209 "parser.yy" // lalr1.cc:859
++#line 213 "parser.yy" // lalr1.cc:859
 +    {
 +                     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 835 "parser.cc" // lalr1.cc:859
++#line 854 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 18:
- #line 225 "parser.yy" // lalr1.cc:859
++#line 229 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr sub(new TokenSubstring());
                        ctx.expression.push_back(sub);
                    }
- #line 844 "parser.cc" // lalr1.cc:859
 -#line 752 "parser.cc" // lalr1.cc:859
++#line 863 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 15:
 -#line 177 "parser.yy" // lalr1.cc:859
 +  case 19:
- #line 230 "parser.yy" // lalr1.cc:859
++#line 234 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr conc(new TokenConcat());
                        ctx.expression.push_back(conc);
                    }
- #line 853 "parser.cc" // lalr1.cc:859
 -#line 761 "parser.cc" // lalr1.cc:859
++#line 872 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 16:
 -#line 182 "parser.yy" // lalr1.cc:859
 +  case 20:
- #line 237 "parser.yy" // lalr1.cc:859
++#line 239 "parser.yy" // lalr1.cc:859
+     {
+                       TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
+                       ctx.expression.push_back(pkt6_field);
+                   }
 -#line 770 "parser.cc" // lalr1.cc:859
++#line 881 "parser.cc" // lalr1.cc:859
+     break;
 -  case 17:
 -#line 189 "parser.yy" // lalr1.cc:859
++  case 21:
++#line 246 "parser.yy" // lalr1.cc:859
      {
                       yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
                   }
- #line 861 "parser.cc" // lalr1.cc:859
 -#line 778 "parser.cc" // lalr1.cc:859
++#line 889 "parser.cc" // lalr1.cc:859
      break;
  
-   case 21:
- #line 241 "parser.yy" // lalr1.cc:859
 -  case 18:
 -#line 193 "parser.yy" // lalr1.cc:859
++  case 22:
++#line 250 "parser.yy" // lalr1.cc:859
      {
                       yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
                   }
- #line 869 "parser.cc" // lalr1.cc:859
 -#line 786 "parser.cc" // lalr1.cc:859
++#line 897 "parser.cc" // lalr1.cc:859
      break;
  
-   case 22:
- #line 247 "parser.yy" // lalr1.cc:859
 -  case 19:
 -#line 199 "parser.yy" // lalr1.cc:859
++  case 23:
++#line 256 "parser.yy" // lalr1.cc:859
      {
                            yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                        }
- #line 877 "parser.cc" // lalr1.cc:859
 -#line 794 "parser.cc" // lalr1.cc:859
++#line 905 "parser.cc" // lalr1.cc:859
      break;
  
-   case 23:
- #line 251 "parser.yy" // lalr1.cc:859
 -  case 20:
 -#line 203 "parser.yy" // lalr1.cc:859
++  case 24:
++#line 260 "parser.yy" // lalr1.cc:859
      {
                            yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
                        }
- #line 885 "parser.cc" // lalr1.cc:859
 -#line 802 "parser.cc" // lalr1.cc:859
++#line 913 "parser.cc" // lalr1.cc:859
      break;
  
-   case 24:
- #line 257 "parser.yy" // lalr1.cc:859
 -  case 21:
 -#line 209 "parser.yy" // lalr1.cc:859
++  case 25:
++#line 266 "parser.yy" // lalr1.cc:859
      {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
- #line 894 "parser.cc" // lalr1.cc:859
 -#line 811 "parser.cc" // lalr1.cc:859
++#line 922 "parser.cc" // lalr1.cc:859
      break;
  
-   case 25:
- #line 264 "parser.yy" // lalr1.cc:859
 -  case 22:
 -#line 216 "parser.yy" // lalr1.cc:859
++  case 26:
++#line 273 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(str);
                    }
- #line 903 "parser.cc" // lalr1.cc:859
 -#line 820 "parser.cc" // lalr1.cc:859
++#line 931 "parser.cc" // lalr1.cc:859
      break;
  
-   case 26:
- #line 269 "parser.yy" // lalr1.cc:859
 -  case 23:
 -#line 221 "parser.yy" // lalr1.cc:859
++  case 27:
++#line 278 "parser.yy" // lalr1.cc:859
      {
                       TokenPtr str(new TokenString("all"));
                       ctx.expression.push_back(str);
                   }
- #line 912 "parser.cc" // lalr1.cc:859
 -#line 829 "parser.cc" // lalr1.cc:859
++#line 940 "parser.cc" // lalr1.cc:859
      break;
  
-   case 27:
- #line 275 "parser.yy" // lalr1.cc:859
 -  case 24:
 -#line 227 "parser.yy" // lalr1.cc:859
++  case 28:
++#line 284 "parser.yy" // lalr1.cc:859
 +    { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR; }
- #line 918 "parser.cc" // lalr1.cc:859
++#line 946 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 28:
- #line 276 "parser.yy" // lalr1.cc:859
++  case 29:
++#line 285 "parser.yy" // lalr1.cc:859
 +    { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR; }
- #line 924 "parser.cc" // lalr1.cc:859
++#line 952 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 29:
- #line 280 "parser.yy" // lalr1.cc:859
++  case 30:
++#line 289 "parser.yy" // lalr1.cc:859
 +    {
 +               yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location);
 +                 }
- #line 932 "parser.cc" // lalr1.cc:859
++#line 960 "parser.cc" // lalr1.cc:859
 +    break;
 +
++  case 31:
++#line 297 "parser.yy" // lalr1.cc:859
+     { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE; }
 -#line 835 "parser.cc" // lalr1.cc:859
++#line 966 "parser.cc" // lalr1.cc:859
+     break;
  
- #line 936 "parser.cc" // lalr1.cc:859
 -  case 25:
 -#line 228 "parser.yy" // lalr1.cc:859
++  case 32:
++#line 298 "parser.yy" // lalr1.cc:859
+     { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID; }
 -#line 841 "parser.cc" // lalr1.cc:859
++#line 972 "parser.cc" // lalr1.cc:859
+     break;
 -#line 845 "parser.cc" // lalr1.cc:859
++#line 976 "parser.cc" // lalr1.cc:859
              default:
                break;
              }
    }
  
  
-   const signed char EvalParser::yypact_ninf_ = -47;
 -  const signed char EvalParser::yypact_ninf_ = -42;
++  const signed char EvalParser::yypact_ninf_ = -54;
  
    const signed char EvalParser::yytable_ninf_ = -1;
  
    const signed char
    EvalParser::yypact_[] =
    {
-       11,    11,    11,    -4,    -1,     3,    21,    27,   -47,   -47,
-      -47,    49,    51,    28,    44,   -47,    -2,    -2,    19,    36,
-       36,   -47,    11,    11,    36,   -47,   -47,   -47,    46,    48,
-      -47,    57,    59,    60,    61,    43,    54,   -47,    71,   -47,
-       62,    63,    64,    -2,    -2,    19,    56,    36,    23,    35,
-       -5,    67,    68,    69,   -47,    65,    81,   -47,   -47,   -47,
-      -47,   -47,   -47,    72,   -47,   -47,   -47,    73,    74,    75,
-      -16,   -47,    -2,    53,    53,     6,   -47,   -47,    84,    77,
-       79,   -47,    78,    -2,    50,    80,   -47,   -47,    82,    53
 -      -1,    -1,    -1,    10,    13,    35,    45,    40,   -42,   -42,
 -      26,     6,    46,    11,   -42,    12,    12,    23,    23,    19,
 -     -42,    -1,    -1,    23,   -42,   -42,   -42,    43,    44,    47,
 -      48,    38,    41,   -42,   -42,   -42,   -42,    55,   -42,    49,
 -      50,    12,    12,    39,    23,    20,    36,    53,    54,   -42,
 -      51,    63,   -42,   -42,   -42,   -42,   -42,   -42,    56,    58,
 -     -11,   -42,    31,    31,   -42,   -42,    64,   -42
++      29,    29,    29,   -12,    -4,     7,    21,    30,    32,   -54,
++     -54,   -54,    13,    10,    46,    16,   -54,    -3,    -3,     9,
++      52,    52,    42,   -54,    29,    29,    52,   -54,   -54,   -54,
++      40,    54,   -54,    56,    43,    59,    60,    55,    58,   -54,
++     -54,   -54,   -54,    72,   -54,    66,    68,    69,    -3,    -3,
++       9,    61,    52,    25,    28,    -1,    71,    73,    75,   -54,
++      65,    87,   -54,   -54,   -54,   -54,   -54,   -54,    78,   -54,
++     -54,   -54,    77,    79,    80,   -14,   -54,    -3,    33,    33,
++       6,   -54,   -54,    90,    82,    84,   -54,    83,    -3,    47,
++      85,   -54,   -54,    86,    33
    };
  
    const unsigned char
    EvalParser::yydefact_[] =
    {
-        0,     0,     0,     0,     0,     0,     0,     0,    11,    12,
-       13,     0,     2,     0,     0,     4,     0,     0,     0,     0,
-        0,     1,     0,     0,     0,     3,    20,    21,     0,     0,
-       29,     0,     0,     0,     0,     0,     0,     5,     6,     7,
-        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-        0,     0,     0,     0,    24,     0,     0,    22,    23,     8,
-       14,     9,    15,     0,    27,    28,    17,     0,     0,     0,
-        0,    19,     0,     0,     0,     0,    26,    25,     0,     0,
-        0,    18,     0,     0,     0,     0,    10,    16,     0,     0
 -       0,     0,     0,     0,     0,     0,     0,     0,    10,    11,
 -       0,     2,     0,     0,     4,     0,     0,     0,     0,     0,
 -       1,     0,     0,     0,     3,    17,    18,     0,     0,     0,
 -       0,     0,     0,    24,    25,    16,     5,     6,     7,     0,
 -       0,     0,     0,     0,     0,     0,     0,     0,     0,    21,
 -       0,     0,    19,    20,     8,    12,     9,    13,     0,     0,
 -       0,    15,     0,     0,    23,    22,     0,    14
++       0,     0,     0,     0,     0,     0,     0,     0,     0,    11,
++      12,    13,     0,     2,     0,     0,     4,     0,     0,     0,
++       0,     0,     0,     1,     0,     0,     0,     3,    21,    22,
++       0,     0,    30,     0,     0,     0,     0,     0,     0,    31,
++      32,    20,     5,     6,     7,     0,     0,     0,     0,     0,
++       0,     0,     0,     0,     0,     0,     0,     0,     0,    25,
++       0,     0,    23,    24,     8,    14,     9,    15,     0,    28,
++      29,    17,     0,     0,     0,     0,    19,     0,     0,     0,
++       0,    27,    26,     0,     0,     0,    18,     0,     0,     0,
++       0,    10,    16,     0,     0
    };
  
    const signed char
    EvalParser::yypgoto_[] =
    {
-      -47,   -47,    10,   -18,   -17,   -46,   -47,   -47,   -47,    52
 -     -42,   -42,     9,   -17,   -13,   -41,   -42,   -42,   -42
++     -54,   -54,     4,   -17,   -18,   -53,   -54,   -54,   -54,    51,
++     -54
    };
  
    const signed char
    EvalParser::yydefgoto_[] =
    {
-       -1,    11,    12,    13,    28,    60,    55,    78,    66,    31
 -      -1,    10,    11,    12,    27,    55,    50,    66,    35
++      -1,    12,    13,    14,    30,    65,    60,    83,    71,    33,
++      41
    };
  
    const unsigned char
    EvalParser::yytable_[] =
    {
-       29,    35,    36,    62,    63,    76,    39,    64,    65,    77,
-       16,    14,    15,    17,     1,    80,     2,    18,    64,    65,
-        3,     4,     5,    26,    19,    27,    51,    52,    62,    56,
-       20,     6,    37,    38,     7,     8,    24,     9,    87,    10,
-       57,    58,    59,    87,    30,    32,    33,    34,    25,    21,
-       22,    23,    57,    58,    61,    79,     6,    22,    23,     7,
-        8,    40,     9,    41,    10,    46,    85,    57,    58,    86,
-       57,    58,    42,    43,    44,    45,    47,    22,    48,    49,
-       50,    54,    67,    68,    69,    71,    72,    70,    81,    73,
-       74,    75,    82,    83,    84,    88,     0,    53,    89
 -      31,    32,     1,    28,     2,    57,    38,    64,     3,     4,
 -      13,    14,    21,    22,    65,    24,     5,    21,    22,     6,
 -       7,    15,    57,     8,    16,     9,    20,    51,    47,    48,
 -      36,    37,    29,    30,    52,    53,    54,    25,    17,    26,
 -       5,    33,    34,     6,     7,    52,    53,     8,    18,     9,
 -      52,    53,    56,    19,    23,    39,    40,    43,    41,    42,
 -      44,    21,    45,    46,    49,    58,    59,    61,    67,    62,
 -      60,    63
++      31,    67,    17,    37,    38,    15,    16,    81,    68,    44,
++      18,    69,    70,    23,    82,    85,    24,    25,    69,    70,
++      27,    19,    24,    25,    20,    28,    67,    29,    42,    43,
++      56,    57,     1,    21,     2,    61,    92,    32,     3,     4,
++       5,    92,    62,    63,    64,    62,    63,    66,    22,     6,
++      62,    63,     7,     8,    26,    45,     9,    48,    10,    84,
++      11,    34,    35,    36,    62,    63,    91,    39,    40,    46,
++      90,    47,     6,    49,    50,     7,     8,    51,    24,     9,
++      52,    10,    53,    11,    54,    55,    72,    75,    73,    59,
++      74,    76,    77,    78,    86,    79,    80,    87,    88,    89,
++      93,    58,    94
    };
  
-   const signed char
+   const unsigned char
    EvalParser::yycheck_[] =
    {
-       17,    19,    20,    49,     9,    21,    24,    12,    13,    25,
-       14,     1,     2,    14,     3,     9,     5,    14,    12,    13,
-        9,    10,    11,    25,     3,    27,    43,    44,    74,    47,
-        3,    20,    22,    23,    23,    24,     8,    26,    84,    28,
-       17,    18,    19,    89,    25,     9,    10,    11,     4,     0,
-        6,     7,    17,    18,    19,    72,    20,     6,     7,    23,
-       24,    15,    26,    15,    28,    22,    83,    17,    18,    19,
-       17,    18,    15,    14,    14,    14,    22,     6,    16,    16,
-       16,    25,    15,    15,    15,     4,    14,    22,     4,    16,
-       16,    16,    15,    14,    16,    15,    -1,    45,    16
 -      17,    18,     3,    16,     5,    46,    23,    18,     9,    10,
 -       1,     2,     6,     7,    25,     4,    17,     6,     7,    20,
 -      21,    11,    63,    24,    11,    26,     0,    44,    41,    42,
 -      21,    22,     9,    10,    14,    15,    16,    25,     3,    27,
 -      17,    22,    23,    20,    21,    14,    15,    24,     3,    26,
 -      14,    15,    16,    13,     8,    12,    12,    19,    11,    11,
 -      19,     6,    13,    13,    25,    12,    12,     4,     4,    13,
 -      19,    13
++      18,    54,    14,    20,    21,     1,     2,    21,     9,    26,
++      14,    12,    13,     0,    28,     9,     6,     7,    12,    13,
++       4,    14,     6,     7,     3,    28,    79,    30,    24,    25,
++      48,    49,     3,     3,     5,    52,    89,    28,     9,    10,
++      11,    94,    17,    18,    19,    17,    18,    19,    16,    20,
++      17,    18,    23,    24,     8,    15,    27,    14,    29,    77,
++      31,     9,    10,    11,    17,    18,    19,    25,    26,    15,
++      88,    15,    20,    14,    14,    23,    24,    22,     6,    27,
++      22,    29,    16,    31,    16,    16,    15,    22,    15,    28,
++      15,     4,    14,    16,     4,    16,    16,    15,    14,    16,
++      15,    50,    16
    };
  
    const unsigned char
    EvalParser::yystos_[] =
    {
-        0,     3,     5,     9,    10,    11,    20,    23,    24,    26,
-       28,    30,    31,    32,    31,    31,    14,    14,    14,     3,
-        3,     0,     6,     7,     8,     4,    25,    27,    33,    33,
-       25,    38,     9,    10,    11,    32,    32,    31,    31,    32,
-       15,    15,    15,    14,    14,    14,    22,    22,    16,    16,
-       16,    33,    33,    38,    25,    35,    32,    17,    18,    19,
-       34,    19,    34,     9,    12,    13,    37,    15,    15,    15,
-       22,     4,    14,    16,    16,    16,    21,    25,    36,    33,
-        9,     4,    15,    14,    16,    33,    19,    34,    15,    16
 -       0,     3,     5,     9,    10,    17,    20,    21,    24,    26,
 -      29,    30,    31,    30,    30,    11,    11,     3,     3,    13,
 -       0,     6,     7,     8,     4,    25,    27,    32,    32,     9,
 -      10,    31,    31,    22,    23,    36,    30,    30,    31,    12,
 -      12,    11,    11,    19,    19,    13,    13,    32,    32,    25,
 -      34,    31,    14,    15,    16,    33,    16,    33,    12,    12,
 -      19,     4,    13,    13,    18,    25,    35,     4
++       0,     3,     5,     9,    10,    11,    20,    23,    24,    27,
++      29,    31,    33,    34,    35,    34,    34,    14,    14,    14,
++       3,     3,    16,     0,     6,     7,     8,     4,    28,    30,
++      36,    36,    28,    41,     9,    10,    11,    35,    35,    25,
++      26,    42,    34,    34,    35,    15,    15,    15,    14,    14,
++      14,    22,    22,    16,    16,    16,    36,    36,    41,    28,
++      38,    35,    17,    18,    19,    37,    19,    37,     9,    12,
++      13,    40,    15,    15,    15,    22,     4,    14,    16,    16,
++      16,    21,    28,    39,    36,     9,     4,    15,    14,    16,
++      36,    19,    37,    15,    16
    };
  
    const unsigned char
    EvalParser::yyr1_[] =
    {
-        0,    29,    30,    31,    31,    31,    31,    31,    31,    31,
-       31,    32,    32,    32,    32,    32,    32,    32,    32,    32,
-       33,    33,    34,    34,    35,    36,    36,    37,    37,    38
 -       0,    28,    29,    30,    30,    30,    30,    30,    30,    30,
 -      31,    31,    31,    31,    31,    31,    31,    32,    32,    33,
 -      33,    34,    35,    35,    36,    36
++       0,    32,    33,    34,    34,    34,    34,    34,    34,    34,
++      34,    35,    35,    35,    35,    35,    35,    35,    35,    35,
++      35,    36,    36,    37,    37,    38,    39,    39,    40,    40,
++      41,    42,    42
    };
  
    const unsigned char
    EvalParser::yyr2_[] =
    {
         0,     2,     1,     3,     2,     3,     3,     3,     6,     6,
 -       1,     1,     6,     6,     8,     6,     3,     1,     1,     1,
 -       1,     1,     1,     1,     1,     1
 +      11,     1,     1,     1,     6,     6,    11,     6,     8,     6,
-        1,     1,     1,     1,     1,     1,     1,     1,     1,     1
++       3,     1,     1,     1,     1,     1,     1,     1,     1,     1,
++       1,     1,     1
    };
  
  
    const EvalParser::yytname_[] =
    {
    "\"end of file\"", "error", "$undefined", "\"(\"", "\")\"", "\"not\"",
 -  "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"[\"",
 -  "\"]\"", "\".\"", "\"text\"", "\"hex\"", "\"exists\"", "\"substring\"",
 -  "\"all\"", "\",\"", "\"concat\"", "\"pkt6\"", "\"msgtype\"",
 -  "\"transid\"", "\"constant string\"", "\"integer\"",
 -  "\"constant hexstring\"", "\"option name\"", "$accept", "expression",
 +  "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"relay6\"",
 +  "\"peeraddr\"", "\"linkaddr\"", "\"[\"", "\"]\"", "\".\"", "\"text\"",
 +  "\"hex\"", "\"exists\"", "\"substring\"", "\"all\"", "\",\"",
-   "\"concat\"", "\"constant string\"", "\"integer\"",
-   "\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept",
-   "expression", "bool_expr", "string_expr", "option_code",
-   "option_repr_type", "start_expr", "length_expr", "relay6_field",
-   "nest_level", YY_NULLPTR
++  "\"concat\"", "\"pkt6\"", "\"msgtype\"", "\"transid\"",
++  "\"constant string\"", "\"integer\"", "\"constant hexstring\"",
++  "\"option name\"", "\"ip address\"", "$accept", "expression",
+   "bool_expr", "string_expr", "option_code", "option_repr_type",
 -  "start_expr", "length_expr", "pkt6_field", YY_NULLPTR
++  "start_expr", "length_expr", "relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
    };
  
  #if YYDEBUG
 -  const unsigned char
 +  const unsigned short int
    EvalParser::yyrline_[] =
    {
-        0,    87,    87,    90,    91,    96,   101,   106,   111,   116,
-      136,   152,   157,   162,   167,   172,   193,   208,   224,   229,
-      236,   240,   246,   250,   256,   263,   268,   275,   276,   279
 -       0,    85,    85,    88,    89,    94,    99,   104,   109,   114,
 -     136,   141,   146,   151,   171,   176,   181,   188,   192,   198,
 -     202,   208,   215,   220,   227,   228
++       0,    91,    91,    94,    95,   100,   105,   110,   115,   120,
++     140,   156,   161,   166,   171,   176,   197,   212,   228,   233,
++     238,   245,   249,   255,   259,   265,   272,   277,   284,   285,
++     288,   297,   298
    };
  
    // Print the state stack on the debug stream.
  
  #line 13 "parser.yy" // lalr1.cc:1167
  } } // isc::eval
- #line 1354 "parser.cc" // lalr1.cc:1167
- #line 288 "parser.yy" // lalr1.cc:1168
 -#line 1252 "parser.cc" // lalr1.cc:1167
 -#line 231 "parser.yy" // lalr1.cc:1168
++#line 1404 "parser.cc" // lalr1.cc:1167
++#line 301 "parser.yy" // lalr1.cc:1168
  
  void
  isc::eval::EvalParser::error(const location_type& loc,
index c22092b9850eef2c92d56f29678911581a508b04,ce3adb04bbf2c316266344d5951956a78b6c1c75..7727cffa8bcb1d30a80866196e89dd7e5174c8dd
@@@ -298,21 -298,17 +298,24 @@@ namespace isc { namespace eval 
        // option_repr_type
        char dummy1[sizeof(TokenOption::RepresentationType)];
  
-       char dummy2[sizeof(TokenRelay6Field::FieldType)];
+       // pkt6_field
+       char dummy2[sizeof(TokenPkt6::FieldType)];
 +      // relay6_field
++      char dummy3[sizeof(TokenRelay6Field::FieldType)];
 +
        // "constant string"
        // "integer"
        // "constant hexstring"
        // "option name"
 -      char dummy3[sizeof(std::string)];
 +      // "ip address"
-       char dummy3[sizeof(std::string)];
++      char dummy4[sizeof(std::string)];
  
        // option_code
--      char dummy4[sizeof(uint16_t)];
++      char dummy5[sizeof(uint16_t)];
 +
 +      // nest_level
-       char dummy5[sizeof(uint8_t)];
++      char dummy6[sizeof(uint8_t)];
  };
  
      /// Symbol semantic values.
          TOKEN_EQUAL = 263,
          TOKEN_OPTION = 264,
          TOKEN_RELAY4 = 265,
 -        TOKEN_LBRACKET = 266,
 -        TOKEN_RBRACKET = 267,
 -        TOKEN_DOT = 268,
 -        TOKEN_TEXT = 269,
 -        TOKEN_HEX = 270,
 -        TOKEN_EXISTS = 271,
 -        TOKEN_SUBSTRING = 272,
 -        TOKEN_ALL = 273,
 -        TOKEN_COMA = 274,
 -        TOKEN_CONCAT = 275,
 -        TOKEN_PKT6 = 276,
 -        TOKEN_MSGTYPE = 277,
 -        TOKEN_TRANSID = 278,
 -        TOKEN_STRING = 279,
 -        TOKEN_INTEGER = 280,
 -        TOKEN_HEXSTRING = 281,
 -        TOKEN_OPTION_NAME = 282
 +        TOKEN_RELAY6 = 266,
 +        TOKEN_PEERADDR = 267,
 +        TOKEN_LINKADDR = 268,
 +        TOKEN_LBRACKET = 269,
 +        TOKEN_RBRACKET = 270,
 +        TOKEN_DOT = 271,
 +        TOKEN_TEXT = 272,
 +        TOKEN_HEX = 273,
 +        TOKEN_EXISTS = 274,
 +        TOKEN_SUBSTRING = 275,
 +        TOKEN_ALL = 276,
 +        TOKEN_COMA = 277,
 +        TOKEN_CONCAT = 278,
-         TOKEN_STRING = 279,
-         TOKEN_INTEGER = 280,
-         TOKEN_HEXSTRING = 281,
-         TOKEN_OPTION_NAME = 282,
-         TOKEN_IP_ADDRESS = 283
++        TOKEN_PKT6 = 279,
++        TOKEN_MSGTYPE = 280,
++        TOKEN_TRANSID = 281,
++        TOKEN_STRING = 282,
++        TOKEN_INTEGER = 283,
++        TOKEN_HEXSTRING = 284,
++        TOKEN_OPTION_NAME = 285,
++        TOKEN_IP_ADDRESS = 286
        };
      };
  
  
    basic_symbol (typename Base::kind_type t, const TokenOption::RepresentationType v, const location_type& l);
  
+   basic_symbol (typename Base::kind_type t, const TokenPkt6::FieldType v, const location_type& l);
 +  basic_symbol (typename Base::kind_type t, const TokenRelay6Field::FieldType v, const location_type& l);
 +
    basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l);
  
    basic_symbol (typename Base::kind_type t, const uint16_t v, const location_type& l);
      enum
      {
        yyeof_ = 0,
-       yylast_ = 98,     ///< Last index in yytable_.
-       yynnts_ = 10,  ///< Number of nonterminal symbols.
-       yyfinal_ = 21, ///< Termination state number.
 -      yylast_ = 71,     ///< Last index in yytable_.
 -      yynnts_ = 9,  ///< Number of nonterminal symbols.
 -      yyfinal_ = 20, ///< Termination state number.
++      yylast_ = 102,     ///< Last index in yytable_.
++      yynnts_ = 11,  ///< Number of nonterminal symbols.
++      yyfinal_ = 23, ///< Termination state number.
        yyterror_ = 1,
        yyerrcode_ = 256,
-       yyntokens_ = 29  ///< Number of tokens.
 -      yyntokens_ = 28  ///< Number of tokens.
++      yyntokens_ = 32  ///< Number of tokens.
      };
  
  
         2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
         5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
        15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-       25,    26,    27,    28
 -      25,    26,    27
++      25,    26,    27,    28,    29,    30,    31
      };
-     const unsigned int user_token_number_max_ = 283;
 -    const unsigned int user_token_number_max_ = 282;
++    const unsigned int user_token_number_max_ = 286;
      const token_number_type undef_token_ = 2;
  
      if (static_cast<int>(t) <= yyeof_)
    {
        switch (other.type_get ())
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          value.copy< TokenOption::RepresentationType > (other.value);
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         value.copy< TokenPkt6::FieldType > (other.value);
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        value.copy< TokenRelay6Field::FieldType > (other.value);
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          value.copy< std::string > (other.value);
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          value.copy< uint16_t > (other.value);
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        value.copy< uint8_t > (other.value);
 +        break;
 +
        default:
          break;
      }
      (void) v;
        switch (this->type_get ())
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          value.copy< TokenOption::RepresentationType > (v);
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         value.copy< TokenPkt6::FieldType > (v);
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        value.copy< TokenRelay6Field::FieldType > (v);
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          value.copy< std::string > (v);
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          value.copy< uint16_t > (v);
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        value.copy< uint8_t > (v);
 +        break;
 +
        default:
          break;
      }
      , location (l)
    {}
  
+   template <typename Base>
+   EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const TokenPkt6::FieldType v, const location_type& l)
+     : Base (t)
+     , value (v)
+     , location (l)
+   {}
 +  template <typename Base>
 +  EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const TokenRelay6Field::FieldType v, const location_type& l)
 +    : Base (t)
 +    , value (v)
 +    , location (l)
 +  {}
 +
    template <typename Base>
    EvalParser::basic_symbol<Base>::basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l)
      : Base (t)
      // Type destructor.
      switch (yytype)
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          value.template destroy< TokenOption::RepresentationType > ();
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         value.template destroy< TokenPkt6::FieldType > ();
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        value.template destroy< TokenRelay6Field::FieldType > ();
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          value.template destroy< std::string > ();
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          value.template destroy< uint16_t > ();
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        value.template destroy< uint8_t > ();
 +        break;
 +
        default:
          break;
      }
      super_type::move(s);
        switch (this->type_get ())
      {
-       case 34: // option_repr_type
 -      case 33: // option_repr_type
++      case 37: // option_repr_type
          value.move< TokenOption::RepresentationType > (s.value);
          break;
  
-       case 37: // relay6_field
 -      case 36: // pkt6_field
++      case 42: // pkt6_field
+         value.move< TokenPkt6::FieldType > (s.value);
+         break;
 -      case 24: // "constant string"
 -      case 25: // "integer"
 -      case 26: // "constant hexstring"
 -      case 27: // "option name"
++      case 40: // relay6_field
 +        value.move< TokenRelay6Field::FieldType > (s.value);
 +        break;
 +
-       case 24: // "constant string"
-       case 25: // "integer"
-       case 26: // "constant hexstring"
-       case 27: // "option name"
-       case 28: // "ip address"
++      case 27: // "constant string"
++      case 28: // "integer"
++      case 29: // "constant hexstring"
++      case 30: // "option name"
++      case 31: // "ip address"
          value.move< std::string > (s.value);
          break;
  
-       case 33: // option_code
 -      case 32: // option_code
++      case 36: // option_code
          value.move< uint16_t > (s.value);
          break;
  
-       case 38: // nest_level
++      case 41: // nest_level
 +        value.move< uint8_t > (s.value);
 +        break;
 +
        default:
          break;
      }
      {
         0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
       265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-      275,   276,   277,   278,   279,   280,   281,   282,   283
 -     275,   276,   277,   278,   279,   280,   281,   282
++     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
++     285,   286
      };
      return static_cast<token_type> (yytoken_number_[type]);
    }
  
  #line 13 "parser.yy" // lalr1.cc:377
  } } // isc::eval
- #line 1317 "parser.h" // lalr1.cc:377
 -#line 1273 "parser.h" // lalr1.cc:377
++#line 1379 "parser.h" // lalr1.cc:377
  
  
  
index cc7ed8fd50449359c5bf6fb88e22b4393f8238a3,67d190b6c0c806cb53c903d0aa8475ab576ed184..1fd28a66f3d267b58bbc7ef6550a673e7c2a690a
@@@ -68,8 -67,7 +71,9 @@@ using namespace isc::eval
  
  %type <uint16_t> option_code
  %type <TokenOption::RepresentationType> option_repr_type
 +%type <TokenRelay6Field::FieldType> relay6_field
 +%type <uint8_t> nest_level
+ %type <TokenPkt6::FieldType> pkt6_field
  
  %left OR
  %left AND
@@@ -272,19 -224,10 +281,23 @@@ length_expr : INTEGE
                   }
              ;
  
 +relay6_field : PEERADDR { $$ = TokenRelay6Field::PEERADDR; }
 +             | LINKADDR { $$ = TokenRelay6Field::LINKADDR; }
 +             ;
 +
 +nest_level : INTEGER
 +                 {
 +               $$ = ctx.convertNestLevelNumber($1, @1);
 +                 }
 +                 // Eventually we may add strings to handle different
 +                 // ways of choosing from which relay we want to extract
 +                 // an option or field.
 +           ;
 +
+ pkt6_field:MSGTYPE { $$ = TokenPkt6::MSGTYPE; }
+           | TRANSID { $$ = TokenPkt6::TRANSID; }
+           ;
  %%
  void
  isc::eval::EvalParser::error(const location_type& loc,
index d086b3da46a59f2c9b28fa87a72e4c3b748ec878,e4ae0c3dcd28cbd3d2354b574dc6cf5af6637ff3..eab31f9ac0f430a0deb5813bfcbe4d24c6bacb44
@@@ -148,114 -123,21 +148,129 @@@ public
          EXPECT_TRUE(conc);
      }
  
 +    /// @brief checks if the given token is a TokenRelay6Option with
 +    /// the correct nesting level, option code and representation.
 +    /// @param token token to be checked
 +    /// @param expected_level expected nesting level
 +    /// @param expected_code expected option code
 +    /// @param expected_repr expected representation (text, hex, exists)
 +    void checkTokenRelay6Option(const TokenPtr& token,
 +                                uint8_t expected_level,
 +                                uint16_t expected_code,
 +                                TokenOption::RepresentationType expected_repr) {
 +        ASSERT_TRUE(token);
 +        boost::shared_ptr<TokenRelay6Option> opt =
 +            boost::dynamic_pointer_cast<TokenRelay6Option>(token);
 +        ASSERT_TRUE(opt);
 +
 +        EXPECT_EQ(expected_level, opt->getNest());
 +        EXPECT_EQ(expected_code, opt->getCode());
 +        EXPECT_EQ(expected_repr, opt->getRepresentation());
 +    }
 +
 +    /// @brief This tests attempts to parse the expression then checks
 +    /// if the number of tokens is correct and the TokenRelay6Option
 +    /// is as expected.
 +    ///
 +    /// @param expr expression to be parsed
 +    /// @param exp_level expected level to be parsed
 +    /// @param exp_code expected option code to be parsed
 +    /// @param exp_repr expected representation to be parsed
 +    /// @param exp_tokens expected number of tokens
 +    void testRelay6Option(std::string expr,
 +                         uint8_t exp_level,
 +                         uint16_t exp_code,
 +                         TokenOption::RepresentationType exp_repr,
 +                         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 succed and return a token.
 +        EXPECT_TRUE(parsed_);
 +
 +        // There should be the expected number of tokens.
 +        ASSERT_EQ(exp_tokens, eval.expression.size());
 +
 +        // checkt that the first token is TokenRelay6Option and that
 +        // is has the correct attributes
 +        checkTokenRelay6Option(eval.expression.at(0), exp_level, exp_code, exp_repr);
 +    }
 +
 +    /// @brief checks if the given token is a TokenRelay with the
 +    /// correct nesting level and field type.
 +    /// @param token token to be checked
 +    /// @param expected_level expected nesting level
 +    /// @param expected_code expected option code
 +    /// @param expected_repr expected representation (text, hex, exists)
 +    void checkTokenRelay6Field(const TokenPtr& token,
 +                               uint8_t expected_level,
 +                               TokenRelay6Field::FieldType expected_type) {
 +        ASSERT_TRUE(token);
 +        boost::shared_ptr<TokenRelay6Field> opt =
 +            boost::dynamic_pointer_cast<TokenRelay6Field>(token);
 +        ASSERT_TRUE(opt);
 +
 +        EXPECT_EQ(expected_level, opt->getNest());
 +        EXPECT_EQ(expected_type, opt->getType());
 +    }
 +
 +    /// @brief This tests attempts to parse the expression then checks
 +    /// if the number of tokens is correct and the TokenRelay6Field is as
 +    /// expected.
 +    ///
 +    /// @param expr expression to be parsed
 +    /// @param exp_level expected level to be parsed
 +    /// @param exp_type expected field type to be parsed
 +    /// @param exp_tokens expected number of tokens
 +    void testRelay6Field(std::string expr,
 +                         uint8_t exp_level,
 +                         TokenRelay6Field::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 succed and return a token.
 +        EXPECT_TRUE(parsed_);
 +
 +        // There should be the expected number of tokens.
 +        ASSERT_EQ(exp_tokens, eval.expression.size());
 +
 +        // checkt that the first token is TokenRelay6Field and that
 +        // is has the correct attributes
 +        checkTokenRelay6Field(eval.expression.at(0), exp_level, exp_type);
 +    }
 +
+     /// @brief checks if the given token is Pkt6 of specified type
+     /// @param token token to be checked
+     /// @param exp_type expected type of the Pkt6 field
+     void checkTokenPkt6(const TokenPtr& token,
+                         TokenPkt6::FieldType exp_type) {
+         ASSERT_TRUE(token);
+         boost::shared_ptr<TokenPkt6> pkt =
+             boost::dynamic_pointer_cast<TokenPkt6>(token);
+         ASSERT_TRUE(pkt);
+         EXPECT_EQ(exp_type, pkt->getType());
+     }
      /// @brief checks if the given expression raises the expected message
      /// when it is parsed.
      void checkError(const string& expr, const string& msg) {
index c9276bed4f54ada941fc9d906228499631513eaf,c47d9e8096f6a54e59635c80479a8f48065d56e7..d81f078bb2768387c8bf652c747be6e106ee3a06
@@@ -1118,88 -968,28 +1118,114 @@@ TEST_F(TokenTest, concat) 
      EXPECT_EQ("foobar", values_.top());
  }
  
 +// This test checks if we can properly extract the link and peer
 +// address fields from relay encapsulations.  Our packet has
 +// two relay encapsulations.  We attempt to extract the two
 +// fields from both of the encapsulations and compare them.
 +// We also try to extract one of the fields from an encapsulation
 +// that doesn't exist (level 2), this should result in an empty
 +// string.
 +TEST_F(TokenTest, relay6Field) {
 +    // Values for the address results
 +    uint8_t zeroaddr[] = { 0, 0, 0, 0, 0, 0, 0, 0,
 +                           0, 0, 0, 0, 0, 0, 0, 0 };
 +    uint8_t linkaddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
 +                           0, 0, 0, 0, 0, 0, 0, 1 };
 +    uint8_t peeraddr[] = { 0, 1, 0, 0, 0, 0, 0, 0,
 +                           0, 0, 0, 0, 0, 0, 0, 2 };
 +
 +    // We start by adding a set of relay encapsulations to the
 +    // basic v6 packet.
 +    addRelay6Encapsulations();
 +
 +    // Then we work our way through the set of choices
 +    // Level 0 both link and peer address should be 0::0
 +    verifyRelay6Eval(0, TokenRelay6Field::LINKADDR, 16, zeroaddr);
 +    verifyRelay6Eval(0, TokenRelay6Field::PEERADDR, 16, zeroaddr);
 +
 +    // Level 1 link and peer should have different non-zero addresses
 +    verifyRelay6Eval(1, TokenRelay6Field::LINKADDR, 16, linkaddr);
 +    verifyRelay6Eval(1, TokenRelay6Field::PEERADDR, 16, peeraddr);
 +
 +    // Level 2 has no encapsulation so the address should be zero length
 +    verifyRelay6Eval(2, TokenRelay6Field::LINKADDR, 0, zeroaddr);
 +
 +    // Lets check that the layout of the address returned by the
 +    // token matches that of the TokenIpAddress
 +    TokenPtr trelay;
 +    TokenPtr taddr;
 +    TokenPtr tequal;
 +    ASSERT_NO_THROW(trelay.reset(new TokenRelay6Field(1, TokenRelay6Field::LINKADDR)));
 +    ASSERT_NO_THROW(taddr.reset(new TokenIpAddress("1::1")));
 +    ASSERT_NO_THROW(tequal.reset(new TokenEqual()));
 +
 +    EXPECT_NO_THROW(trelay->evaluate(*pkt6_, values_));
 +    EXPECT_NO_THROW(taddr->evaluate(*pkt6_, values_));
 +    EXPECT_NO_THROW(tequal->evaluate(*pkt6_, values_));
 +
 +    // We should have a single value on the stack and it should be "true"
 +    ASSERT_EQ(1, values_.size());
 +    EXPECT_EQ("true", values_.top());
 +
 +    // be tidy
 +    clearStack();
 +}
 +
 +// This test checks if we can properly extract an option
 +// from relay encapsulations.  Our packet has two relay
 +// encapsulations.  Both include a common option with the
 +// original message (option 100) and both include their
 +// own option (101 and 102).  We attempt to extract the
 +// options and compare them to expected values.  We also
 +// try to extract an option from an encapsulation
 +// that doesn't exist (level 2), this should result in an empty
 +// string.
 +TEST_F(TokenTest, relay6Option) {
 +    // We start by adding a set of relay encapsulations to the
 +    // basic v6 packet.
 +    addRelay6Encapsulations();
 +
 +    // Then we work our way through the set of choices
 +    // Level 0 both options it has and the check that
 +    // the checking for an option it doesn't have results
 +    // in an empty string.
 +    verifyRelay6Option(0, 100, TokenOption::TEXTUAL, "hundred.zero");
 +    verifyRelay6Option(0, 100, TokenOption::EXISTS, "true");
 +    verifyRelay6Option(0, 101, TokenOption::TEXTUAL, "hundredone.zero");
 +    verifyRelay6Option(0, 102, TokenOption::TEXTUAL, "");
 +    verifyRelay6Option(0, 102, TokenOption::EXISTS, "false");
 +
 +    // Level 1, again both options it has and the one for level 0
 +    verifyRelay6Option(1, 100, TokenOption::TEXTUAL, "hundred.one");
 +    verifyRelay6Option(1, 101, TokenOption::TEXTUAL, "");
 +    verifyRelay6Option(1, 102, TokenOption::TEXTUAL, "hundredtwo.one");
 +
 +    // Level 2, no encapsulation so no options
 +    verifyRelay6Option(2, 100, TokenOption::TEXTUAL, "");
 +}
++
+ // Verifies if the DHCPv6 packet fields can be extracted.
+ TEST_F(TokenTest, pkt6Fields) {
+     // The default test creates a v6 DHCPV6_SOLICIT packet with a
+     // transaction id of 12345.
+     // Check the message type
+     ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE)));
+     EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+     ASSERT_EQ(1, values_.size());
+     uint32_t expected = htonl(1);
+     EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+     // Check the transaction id field
+     clearStack();
+     ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
+     EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+     ASSERT_EQ(1, values_.size());
+     expected = htonl(12345);
+     EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+     // Check that working with a v4 packet generates an error
+     clearStack();
+     ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
+     EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+ }
index b3e52ba9249f355f808ca999d217910b78d2acb0,9610f4af667ec80540701a5a7abd94142d395b20..30b4dbc7a8af270b59d091ac22be6d8cae75fdc4
@@@ -297,66 -275,44 +297,109 @@@ TokenOr::evaluate(const Pkt& /*pkt*/, V
      }
  }
  
 -};
 +OptionPtr TokenRelay6Option::getOption(const Pkt& pkt) {
 +
 +    try {
 +        // Check if it's a Pkt6.  If it's not the dynamic_cast will
 +        // throw std::bad_cast.
 +        const Pkt6& pkt6 = dynamic_cast<const 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(const Pkt& pkt, ValueStack& values) {
 +
 +    vector<uint8_t> binary;
 +    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:
 +                binary = pkt6.getRelay6LinkAddress(nest_level_).toBytes();
 +                break;
 +            case 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("");
 +            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);
 +}
++
+ void
+ TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) {
+     vector<uint8_t> binary;
+     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());
+           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);
+           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);
++}
index e603192490a271f507dd1e0c0fc4a210933f68a3,e3a1854e560e6944e190e78ece0176a1c710ccae..92591c7f200d71b51c9ce9b218a673d3591b233d
@@@ -467,119 -444,52 +467,165 @@@ public
      void evaluate(const Pkt& pkt, ValueStack& values);
  };
  
 -    /// @brief enum value that determins the field.
 +/// @brief Token that represents a value of an option within a DHCPv6 relay
 +/// encapsulation
 +///
 +/// This represents a reference to a given option similar to TokenOption
 +/// but from within the information from a relay.  In the expresssion
 +/// relay6[nest-level].option[option-code], nest-level indicates which
 +/// of the relays to examine and option-code which option to extract.
 +///
 +/// During the evaluation it tries to extract the value of the specified
 +/// option from the requested relay block.  If the relay block doesn't
 +/// exist or the option is not found an empty string ("") is returned
 +/// (or "false" when the representation is EXISTS).
 +///
 +/// The nesting level can go from 0 (closest to the server) to 31
 +class TokenRelay6Option : public TokenOption {
 +public:
 +    /// @brief Constructor that takes a nesting level and an option
 +    /// code as paramaters.
 +    ///
 +    /// @param nest_level the nesting for which relay to examine.
 +    /// @param option_code code of the option.
 +    /// @param rep_type Token representation type.
 +    TokenRelay6Option(const uint8_t nest_level, const uint16_t option_code,
 +                      const RepresentationType& rep_type)
 +        :TokenOption(option_code, rep_type), nest_level_(nest_level) {}
 +
 +    /// @brief Returns nest-level
 +    ///
 +    /// This method is used in testing to determine if the parser has
 +    /// instantiated TokenRelay6Option with correct parameters.
 +    ///
 +    /// @return nest-level of the relay block this token expects to use
 +    /// for extraction.
 +    uint8_t getNest() const {
 +        return (nest_level_);
 +    }
 +
 +protected:
 +    /// @brief Attempts to obtain specified option from the specified relay block
 +    /// @param pkt DHCPv6 packet that hopefully contains the proper relay block
 +    /// @return option instance if available
 +    virtual OptionPtr getOption(const Pkt& pkt);
 +
 +    uint8_t nest_level_; ///< nesting level of the relay block to use
 +};
 +
 +/// @breif Token that represents a value of a field within a DHCPv6 relay
 +/// encapsulation
 +///
 +/// This represents a reference to a field with a given DHCPv6 relay encapsulation.
 +/// In the expression relay6[nest-level].field-name, nest-level indicates which of
 +/// the relays to examine and field-name which of the fields to extract.
 +///
 +/// During the evaluation it tries to extract the value of the specified
 +/// field from the requested relay block.  If the relay block doesn't exist
 +/// an empty string ("") is returned.  If the relay block does exist the field
 +/// is always returned as a 16 byte IPv6 address.  As the relay may not have
 +/// set the field it may be 0s.
 +///
 +/// The nesting level can go from 0 (closest to the server) to 31.
 +class 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(const 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:
 -    /// @breif Returns field type
++    /// @brief enum value that determines the field.
+     enum FieldType {
+         MSGTYPE, ///< msg type
+         TRANSID  ///< transaction id (integer but manipulated as as 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(const 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_;
+ };
  }; // end of isc::dhcp namespace
  }; // end of isc namespace