]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[master] Finish merge of trac4268a (DHCPv4 fields)
authorFrancis Dupont <fdupont@isc.org>
Wed, 27 Apr 2016 11:32:59 +0000 (13:32 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 27 Apr 2016 11:32:59 +0000 (13:32 +0200)
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 7c2341d9c8aaf99652c67c46093fe851858cfd95,9245c0655b241d7890e2f03701adf24639f30e63..5f926a817d9bcd7efc7bba9037b3e8d3100b87f2
+++ b/ChangeLog
@@@ -1,68 -1,3 +1,73 @@@
++1107. [func]          fdupont
++      Added support for extracting constant length fields from a DHCPv4
++      packet.
++      (Trac #4268, git xxx)
++
 +1106. [func]          sar
 +      Added support for accessing DHCPv6 packet fields message type
 +      and transaction id in a classification expression.
 +      (Trac #4269, git 48be5f5ceaba6b0d0a2b31465e8a5904524e894c)
 +
 +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
 +      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 #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)
index 76c310641b633292aab4121f43d117648b4faeb7,acd208fb36cd7aaccfcdbe89dc9b04c873205fd0..ba746272f5fede38cd38b68ef678bde93716b3da
                <entry>Description</entry>
              </row>
            </thead>
            <tbody>
- <row><entry>String</entry><entry>'example'</entry><entry>A string</entry></row>
- <row><entry>Hex String</entry><entry>0XABCD</entry><entry>A hexadecimal string</entry></row>
- <row><entry>IP Address</entry><entry>10.0.0.1</entry><entry>An IP address</entry></row>
- <row><entry>Integer</entry><entry>123</entry><entry>An integer value</entry></row>
+             <row>
+               <entry>String literal</entry>
+               <entry>'example'</entry>
+               <entry>'example'</entry>
+               <entry>A string</entry>
+             </row>
+             <row>
+               <entry>Hexadecimal string literal</entry>
+               <entry>0x5a7d</entry>
+               <entry>'Z}'</entry>
+               <entry>A hexadecimal string</entry>
+             </row>
+             <row>
+               <entry>IP address literal</entry>
+               <entry>10.0.0.1</entry>
+               <entry>0x0a000001</entry>
+               <entry>An IP address</entry>
+             </row>
+             <row>
+               <entry>Integer literal</entry>
+               <entry>123</entry>
+               <entry>'123'</entry>
+               <entry>An integer value</entry>
+             </row>
+             <row></row>
+             <row>
+               <entry>Binary content of the option</entry>
+               <entry>option[123].hex</entry>
+               <entry>'(content of the option)'</entry>
+               <entry>The value of the option with given code from the
+               packet as hex</entry>
+             </row>
  <!-- Text option not fully defined yet, leave it out
- <row><entry>Option Text</entry><entry>option[code].text</entry><entry>The value of the option with code "code" from the packet as text</entry></row>
- -->
- <row><entry>Option Hex</entry><entry>option[code].hex</entry><entry>The value of the option with code "code" from the packet as hex</entry></row>
- <row><entry>Option Exist</entry><entry>option[code].exist</entry><entry>If the option with code "code" is present in the packet "true" else "false"</entry></row>
- <row><entry>DHCPv4 Relay Agent
- 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>
+             <row>
+               <entry>Option Text</entry>
+               <entry>option[123].text</entry>
+               <entry>'foobar'</entry>
+               <entry>The value of the option with given code from the
+               packet as text</entry>
+             </row>
  -->
-   <entry>The value of the transaction id in the DHCPv6 packet.</entry>
- </row>
+             <row>
+               <entry>Option existence</entry>
+               <entry>option[123].exist</entry>
+               <entry>'true'</entry>
+               <entry>If the option with given code is present in the
+               packet "true" else "false"</entry>
+             </row>
+             <row>
+               <entry>DHCPv4 relay agent sub-option</entry>
+               <entry>relay4[123].hex</entry>
+               <entry>'(content of the RAI sub-option)'</entry>
+               <entry>The value of sub-option with given 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>Hardware address in DHCPv4 packet</entry>
+               <entry>pkt4.mac</entry>
+               <entry>0x010203040506</entry>
+               <entry>The value of the chaddr field of the DHCPv4 packet, hlen (0 to 16) bytes</entry>
+             </row>
+             <row>
+               <entry>Hardware length in DHCPv4 packet</entry>
+               <entry>pkt4.hlen</entry>
+               <entry>0x00000006</entry>
+               <entry>The value of the hlen field of the DHCPv4 packet padded to 4 bytes</entry>
+             </row>
+             <row>
+               <entry>Hardware type in DHCPv4 packet</entry>
+               <entry>pkt4.htype</entry>
+               <entry>0x0000007b</entry>
+               <entry>The value of the htype field of the DHCPv4 packet padded to 4 bytes</entry>
+             </row>
+             <row>
+               <entry>ciaddr field in DHCPv4 packet</entry>
+               <entry>pkt4.ciaddr</entry>
+               <entry>192.0.2.1</entry>
+               <entry>The value of the ciaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
+             </row>
+             <row>
+               <entry>giaddr field in DHCPv4 packet</entry>
+               <entry>pkt4.giaddr</entry>
+               <entry>192.0.2.1</entry>
+               <entry>The value of the giaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
+             </row>
+             <row>
+               <entry>yiaddr field in DHCPv4 packet</entry>
+               <entry>pkt4.yiaddr</entry>
+               <entry>192.0.2.1</entry>
+               <entry>The value of the yiaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
+             </row>
+             <row>
+               <entry>siaddr field in DHCPv4 packet</entry>
+               <entry>pkt4.siaddr</entry>
+               <entry>192.0.2.1</entry>
+               <entry>The value of the siaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</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>
          </table>
         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>
+         Expressions starting with pkt4 can be used only in DHCPv4.
+       </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 02ea9fa38801dcda66015dca36c07bf1a4c2031a,85516345a4c463cd40a89bc141c641a85abbe875..20bdad15b9c7867077c5b052e11402817e74d8be
@@@ -483,8 -460,8 +460,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 33
- #define YY_END_OF_BUFFER 34
 -#define YY_NUM_RULES 35
 -#define YY_END_OF_BUFFER 36
++#define YY_NUM_RULES 41
++#define YY_END_OF_BUFFER 42
  /* 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[183] =
 -static yyconst flex_int16_t yy_acclist[190] =
++static yyconst flex_int16_t yy_acclist[227] =
      {   0,
-        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,
 -       36,   34,   35,    1,   34,   35,    2,   35,   34,   35,
 -       29,   34,   35,   30,   34,   35,   33,   34,   35,   34,
 -       35,   28,   34,   35,    5,   34,   35,    5,   34,   35,
 -       34,   35,   34,   35,   34,   35,16390,   34,   35,16390,
 -       31,   34,   35,   32,   34,   35,   34,   35,16390,   34,
 -       35,16390,   34,   35,16390,   34,   35,16390,   34,   35,
 -    16390,   34,   35,16390,   34,   35,16390,   34,   35,16390,
 -       34,   35,16390,   34,   35,16390,   34,   35,16390,   34,
 -       35,16390,   34,   35,16390,    1,    2,    3,    5,    5,
 -        7,    8,16390,16390, 8198,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
 -    16390,16390,16390,16390,16390,16390,16390,   27,16390,16390,
 -    16390,16390,16390,16390,16390,    4,    7,   23,16390,   26,
 -    16390,16390,16390,16390,16390,   12,16390,16390,16390,   15,
 -    16390,   25,16390,16390,16390,16390,16390,16390,16390,16390,
 -    16390,16390,16390,16390,   16,16390,16390,16390,   14,16390,
 -    16390,16390,16390,   11,16390,16390,16390,16390,16390,16390,
 -       17,16390,16390,16390,16390,16390,16390,   18,16390,   24,
 -    16390,   13,16390,   19,16390,    9,16390,   10,16390,   21,
 -    16390,16390,   20,16390,    7,16390,16390,   22,16390
++       42,   40,   41,    1,   40,   41,    2,   41,   40,   41,
++       32,   40,   41,   33,   40,   41,   36,   40,   41,   40,
++       41,   31,   40,   41,    5,   40,   41,    5,   40,   41,
++       40,   41,   40,   41,   40,   41,16390,   40,   41,16390,
++       34,   40,   41,   35,   40,   41,   40,   41,16390,   40,
++       41,16390,   40,   41,16390,   40,   41,16390,   40,   41,
++    16390,   40,   41,16390,   40,   41,16390,   40,   41,16390,
++       40,   41,16390,   40,   41,16390,   40,   41,16390,   40,
++       41,16390,   40,   41,16390,   40,   41,16390,    1,    2,
++        3,    5,    5,    7,    8,16390,16390, 8198,16390,16390,
++
++    16390,16390,16390,16390,16390,16390,16390,16390,16390,16390,
++    16390,16390,   30,16390,16390,16390,16390,16390,16390,16390,
++    16390,16390,    4,    7,   26,16390,   29,16390,16390,16390,
++    16390,16390,   15,16390,16390,16390,16390,   18,16390,16390,
++       28,16390,16390,16390,16390,16390,16390,16390,16390,16390,
++    16390,16390,16390,16390,16390,   19,16390,16390,16390,16390,
++    16390,16390,   17,16390,   37,16390,16390,16390,16390,   14,
++    16390,16390,16390,16390,16390,16390,16390,   20,16390,16390,
++    16390,16390,16390,16390,16390,16390,16390,16390,   21,16390,
++       27,16390,   16,16390,   22,16390,16390,16390,    9,16390,
++
++    16390,   10,16390,   11,16390,   24,16390,16390,16390,   23,
++    16390,    7,16390,   38,16390,16390,16390,   39,16390,   13,
++    16390,   12,16390,16390,   25,16390
      } ;
  
- static yyconst flex_int16_t yy_accept[130] =
 -static yyconst flex_int16_t yy_accept[133] =
++static yyconst flex_int16_t yy_accept[162] =
      {   0,
          1,    1,    1,    2,    4,    7,    9,   11,   14,   17,
         20,   22,   25,   28,   31,   33,   35,   38,   41,   44,
         47,   50,   53,   56,   59,   62,   65,   68,   71,   74,
-        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,
 -       77,   80,   83,   86,   87,   88,   88,   89,   90,   90,
 -       91,   91,   91,   91,   91,   92,   93,   93,   93,   94,
 -       95,   96,   97,   98,   99,  100,  101,  102,  103,  104,
 -      105,  106,  107,  108,  110,  111,  112,  113,  114,  115,
 -      116,  116,  117,  118,  120,  122,  123,  124,  125,  126,
 -      128,  129,  130,  132,  134,  135,  136,  137,  138,  139,
 -      140,  141,  141,  142,  143,  144,  145,  147,  148,  149,
--
-       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
 -      151,  152,  153,  154,  156,  157,  157,  158,  159,  160,
 -      161,  163,  164,  165,  166,  167,  168,  168,  170,  172,
 -      174,  176,  178,  180,  182,  183,  185,  186,  187,  188,
 -      190,  190
++       77,   80,   83,   86,   89,   90,   91,   91,   92,   93,
++       93,   94,   94,   94,   94,   94,   95,   96,   96,   96,
++       97,   98,   99,  100,  101,  102,  103,  104,  105,  106,
++      107,  108,  109,  110,  111,  112,  113,  115,  116,  117,
++      118,  119,  120,  121,  122,  123,  123,  124,  125,  127,
++      129,  130,  131,  132,  133,  135,  136,  137,  138,  140,
++      141,  143,  144,  145,  146,  147,  148,  149,  150,  151,
++
++      152,  152,  153,  154,  155,  156,  158,  159,  160,  161,
++      162,  163,  165,  167,  168,  169,  170,  172,  173,  174,
++      174,  175,  176,  177,  178,  180,  181,  182,  183,  184,
++      185,  186,  187,  188,  189,  189,  191,  193,  195,  197,
++      198,  199,  201,  202,  204,  206,  208,  209,  210,  212,
++      213,  214,  216,  217,  218,  220,  222,  224,  225,  227,
++      227
      } ;
  
- static yyconst YY_CHAR yy_ec[256] =
+ static yyconst flex_int32_t yy_ec[256] =
      {   0,
          1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
          1,    1,    1,    1,    1
      } ;
  
- static yyconst YY_CHAR yy_meta[42] =
 -static yyconst flex_int32_t yy_meta[41] =
++static yyconst flex_int32_t yy_meta[42] =
      {   0,
          1,    1,    2,    1,    1,    1,    1,    1,    3,    4,
 -        4,    4,    5,    1,    4,    1,    1,    1,    1,    1,
 -        4,    4,    4,    4,    4,    1,    1,    1,    1,    1,
 -        1,    1,    1,    1,    1,    1,    1,    1,    1,    1
 +        4,    4,    4,    5,    1,    4,    1,    1,    1,    1,
 +        1,    4,    4,    4,    4,    4,    1,    1,    1,    1,
 +        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 +        1
      } ;
  
- static yyconst flex_uint16_t yy_base[134] =
 -static yyconst flex_int16_t yy_base[137] =
++static yyconst flex_int16_t yy_base[166] =
      {   0,
-         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,
 -        0,    0,  227,  228,  224,  222,  220,  228,  228,  228,
 -       31,  228,   35,   32,  210,  208,   73,  104,  228,  228,
 -       21,   33,  182,  192,   40,  198,  185,   20,  188,  191,
 -       34,  190,  186,  211,  209,  207,  228,   57,   68,  101,
 -      197,  196,    0,  195,    0,  228,  118,  120,    0,    0,
 -      228,  177,  182,  184,  172,  175,  181,  162,  175,  159,
 -      175,  160,  159,    0,  158,  164,  172,  170,  152,  169,
 -      121,    0,    0,    0,    0,  165,  165,  151,  162,    0,
 -      153,  150,    0,    0,  155,  170,  160,  156,  143,  141,
 -      153,  124,  152,  154,  137,  149,    0,  147,  138,    0,
--
-       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
 -      130,  145,  131,    0,  143,  132,  131,  128,  128,  128,
 -        0,  120,  126,   89,   56,   52,  135,    0,    0,    0,
 -        0,    0,    0,    0,   54,    0,  138,   41,   38,    0,
 -      228,  150,  152,  154,   59,  157
++        0,    0,  267,  268,  264,  262,  260,  268,  268,  268,
++       32,  268,   37,   34,  249,  247,   76,  108,  268,  268,
++       23,   35,  221,  231,   42,  230,   35,  224,   30,   41,
++      231,   46,   55,  227,  253,  251,  249,  268,  115,  125,
++      105,  238,  237,    0,  236,    0,  268,  137,  139,    0,
++        0,  268,  218,  223,  225,  213,  216,  222,  203,  216,
++      200,  207,  215,  211,  199,  198,    0,  209,  196,  202,
++      210,  208,  190,  207,  206,  137,    0,    0,    0,    0,
++      202,  202,  188,  199,    0,  190,  187,  191,    0,  182,
++        0,  190,  182,   70,  195,  191,  178,  176,  180,  187,
++
++      141,  186,  188,  171,  183,    0,  181,  184,  164,  170,
++      181,    0,    0,  161,  176,  162,    0,  162,  173,  151,
++      161,  158,  158,  158,    0,  168,  157,  158,  165,  131,
++      153,  152,  158,  150,  155,    0,    0,    0,    0,  160,
++      148,    0,  133,    0,    0,    0,  127,  130,    0,  159,
++       93,    0,   59,   43,    0,    0,    0,   43,    0,  268,
++      172,  174,  176,   54,  179
      } ;
  
- static yyconst flex_int16_t yy_def[134] =
 -static yyconst flex_int16_t yy_def[137] =
++static yyconst flex_int16_t yy_def[166] =
      {   0,
-       128,    1,  128,  128,  128,  128,  129,  128,  128,  128,
-       128,  128,  128,   13,  130,  128,  128,   17,  128,  128,
 -      131,    1,  131,  131,  131,  131,  132,  131,  131,  131,
 -      131,  131,  131,   13,  133,  131,  131,   17,  131,  131,
++      160,    1,  160,  160,  160,  160,  161,  160,  160,  160,
++      160,  160,  160,   13,  162,  160,  160,   17,  160,  160,
         17,   17,   17,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,  128,  128,  129,  128,  128,  128,   13,  130,
-       131,  132,  130,  133,  128,  128,   18,   17,   18,  128,
 -       18,   18,   18,  131,  131,  132,  131,  131,  131,   13,
 -      133,  134,  135,  133,  136,  131,  131,   18,   17,   18,
 -      131,   18,   18,   18,   18,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,  160,  160,  161,  160,  160,  160,
++       13,  162,  163,  164,  162,  165,  160,  160,   18,   17,
++       18,  160,   18,   18,   18,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,   18,  160,  164,  165,   18,   18,
         18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-        18,   18,   18,   18,   18,   18,  128,  132,  133,   18,
 -      131,  135,  136,   18,   18,   18,   18,   18,   18,   18,
         18,   18,   18,   18,   18,   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,  131,   18,   18,   18,   18,   18,   18,   18,   18,
  
-        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
 -       18,   18,   18,   18,   18,  131,   18,   18,   18,   18,
 -       18,   18,   18,   18,   18,   18,  131,   18,   18,   18,
 -       18,   18,   18,   18,   18,   18,  131,   18,   18,   18,
 -        0,  131,  131,  131,  131,  131
++      160,   18,   18,   18,   18,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,   18,   18,   18,   18,   18,  160,
++       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,  160,   18,   18,   18,   18,   18,
++       18,   18,   18,   18,   18,   18,   18,   18,   18,  160,
++       18,   18,   18,   18,   18,   18,   18,   18,   18,    0,
++      160,  160,  160,  160,  160
      } ;
  
- static yyconst flex_uint16_t yy_nxt[280] =
 -static yyconst flex_int16_t yy_nxt[269] =
++static yyconst flex_int16_t yy_nxt[310] =
      {   0,
          4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
 -       14,   14,   15,   16,   17,   18,   18,   19,   20,    4,
 -       21,   17,   22,   17,   23,   24,   25,   18,   18,   18,
 -       26,   27,   28,   29,   30,   31,   32,   18,   18,   33,
 -       38,   38,   38,   39,   40,   40,   40,   41,  131,   42,
 -       52,   43,   53,   63,   64,   42,   42,   42,   42,   42,
 -       54,   67,   72,  130,   58,   55,   38,   38,   38,   59,
 -      131,   68,  129,   43,   47,   47,   60,   71,   71,   71,
 -       48,  128,   49,   49,   49,   41,  126,   49,   50,   50,
 -      125,   51,   48,   49,   49,   49,   49,   49,   50,   50,
 -
 -       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
 -       50,   50,   50,   50,   50,   50,  131,  131,   50,   47,
 -       47,  131,  131,  124,   50,   50,   50,   50,   50,   92,
 -       71,   71,   71,  106,  106,  106,   51,  123,  131,  131,
 -      117,  106,  106,  106,  127,  127,  127,  127,  127,  127,
 -       36,  122,   36,   36,   36,   44,   44,   42,   42,   73,
 -       73,   73,  121,  120,  119,  118,  116,  115,  114,  113,
 -      112,  111,  110,  109,  108,  107,  105,  104,  103,  102,
 -      101,  100,   99,   98,   97,   96,   95,   94,   93,   91,
 -       90,   89,   88,   87,   86,   85,   84,   83,   82,   81,
 -
 -       80,   79,   78,   77,   76,   75,   74,   45,   41,   45,
 -       37,   35,   34,   70,   69,   66,   65,   62,   61,   57,
 -       56,   46,   45,   37,   35,   34,  131,    3,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131
 +       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,   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
++        4,   21,   17,   22,   17,   23,   24,   25,   18,   18,
++       26,   27,   28,   29,   30,   31,   32,   33,   18,   18,
++       34,   39,   39,   39,   39,   40,   41,   41,   41,   41,
++       42,  160,   43,   53,   44,   54,   63,   77,   43,   43,
++       43,   43,   43,   55,   66,   67,   68,   59,   56,  159,
++       69,   64,   60,  160,   71,  158,   44,   48,   48,   61,
++       73,  112,  113,   49,   72,   50,   50,   50,   50,   42,
++       74,   50,   51,   51,  157,   52,   49,   50,   50,   50,
++
++       50,   50,   51,   51,   51,   51,   51,   51,   51,   51,
++       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
++       51,  160,  160,   51,   39,   39,   39,   39,  156,   51,
++       51,   51,   51,   51,   76,   76,   76,   76,   48,   48,
++      160,  160,  144,  145,  160,  101,   76,   76,   76,   76,
++      120,  120,  120,  120,  155,  154,   52,  153,  160,  135,
++      120,  120,  120,  120,  150,  150,  150,  150,  150,  150,
++      150,  150,   37,  152,   37,   37,   37,   45,   45,   43,
++       43,   78,   78,   78,  151,  149,  148,  147,  146,  143,
++      142,  141,  140,  139,  138,  137,  136,  134,  133,  132,
++
++      131,  130,  129,  128,  127,  126,  125,  124,  123,  122,
++      121,  119,  118,  117,  116,  115,  114,  111,  110,  109,
++      108,  107,  106,  105,  104,  103,  102,  100,   99,   98,
++       97,   96,   95,   94,   93,   92,   91,   90,   89,   88,
++       87,   86,   85,   84,   83,   82,   81,   80,   79,   46,
++       42,   46,   38,   36,   35,   75,   70,   65,   62,   58,
++       57,   47,   46,   38,   36,   35,  160,    3,  160,  160,
++      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
++      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
++      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
++
++      160,  160,  160,  160,  160,  160,  160,  160,  160
      } ;
  
- static yyconst flex_int16_t yy_chk[280] =
 -static yyconst flex_int16_t yy_chk[269] =
++static yyconst flex_int16_t yy_chk[310] =
      {   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,   13,   13,   13,   13,   13,   14,   13,
 -       21,   13,   21,   28,   28,   13,   13,   13,   13,   13,
 -       22,   31,  135,  129,   25,   22,   38,   38,   38,   25,
 -       14,   31,  128,   13,   17,   17,   25,   39,   39,   39,
 -       17,  125,   17,   17,   17,   17,  116,   17,   17,   17,
 -      115,   17,   17,   17,   17,   17,   17,   17,   17,   17,
 +        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,
++       13,   14,   13,   21,   13,   21,   27,  164,   13,   13,
++       13,   13,   13,   22,   29,   29,   30,   25,   22,  158,
++       30,   27,   25,   14,   32,  154,   13,   17,   17,   25,
++       33,   94,   94,   17,   32,   17,   17,   17,   17,   17,
++       33,   17,   17,   17,  153,   17,   17,   17,   17,   17,
  
         17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
 -       17,   17,   17,   18,   18,   18,   18,   40,   18,   47,
 -       47,   48,   48,  114,   18,   18,   18,   18,   18,   71,
 -       71,   71,   71,   92,   92,   92,   47,  113,   48,   40,
 -      106,  106,  106,  106,  117,  117,  117,  127,  127,  127,
 -      132,  112,  132,  132,  132,  133,  133,  134,  134,  136,
 -      136,  136,  110,  109,  108,  107,  105,  103,  102,  101,
 -       99,   98,   96,   95,   94,   93,   91,   90,   89,   88,
 -       87,   86,   85,   82,   81,   79,   78,   77,   76,   70,
 -       69,   68,   67,   66,   65,   63,   62,   61,   60,   59,
 -
 -       58,   57,   56,   55,   54,   53,   52,   44,   42,   41,
 -       36,   35,   34,   33,   32,   30,   29,   27,   26,   24,
 -       23,   16,   15,    7,    6,    5,    3,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131,  131,  131,
 -      131,  131,  131,  131,  131,  131,  131,  131
 +       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
++       18,   18,   41,   18,   39,   39,   39,   39,  151,   18,
++       18,   18,   18,   18,   40,   40,   40,   40,   48,   48,
++       49,   49,  130,  130,   41,   76,   76,   76,   76,   76,
++      101,  101,  101,  101,  148,  147,   48,  143,   49,  120,
++      120,  120,  120,  120,  135,  135,  135,  135,  150,  150,
++      150,  150,  161,  141,  161,  161,  161,  162,  162,  163,
++      163,  165,  165,  165,  140,  134,  133,  132,  131,  129,
++      128,  127,  126,  124,  123,  122,  121,  119,  118,  116,
++
++      115,  114,  111,  110,  109,  108,  107,  105,  104,  103,
++      102,  100,   99,   98,   97,   96,   95,   93,   92,   90,
++       88,   87,   86,   84,   83,   82,   81,   75,   74,   73,
++       72,   71,   70,   69,   68,   66,   65,   64,   63,   62,
++       61,   60,   59,   58,   57,   56,   55,   54,   53,   45,
++       43,   42,   37,   36,   35,   34,   31,   28,   26,   24,
++       23,   16,   15,    7,    6,    5,    3,  160,  160,  160,
++      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
++      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
++      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
++
++      160,  160,  160,  160,  160,  160,  160,  160,  160
      } ;
  
  /* Table of booleans, true if rule could match eol. */
- static yyconst flex_int32_t yy_rule_can_match_eol[34] =
 -static yyconst flex_int32_t yy_rule_can_match_eol[36] =
++static yyconst flex_int32_t yy_rule_can_match_eol[42] =
      {   0,
  0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     };
 -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     };
++    0, 0, 0, 0, 0, 0, 0, 0, 0, 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[33] =
 -static yyconst flex_int16_t yy_rule_linenum[35] =
++static yyconst flex_int16_t yy_rule_linenum[41] =
      {   0,
         82,   86,   92,  102,  108,  122,  129,  143,  144,  145,
        146,  147,  148,  149,  150,  151,  152,  153,  154,  155,
-       156,  157,  158,  159,  160,  161,  162,  163,  165,  166,
-       167,  169
+       156,  157,  158,  159,  160,  161,  162,  163,  164,  165,
 -      166,  167,  168,  170
++      166,  167,  168,  169,  170,  171,  173,  174,  175,  177
      } ;
  
  static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@@ -774,7 -749,7 +775,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 778 "lexer.cc"
 -#line 753 "lexer.cc"
++#line 779 "lexer.cc"
  
  #define INITIAL 0
  
@@@ -1017,10 -984,21 +1010,21 @@@ extern int yylex (void)
   */
  YY_DECL
  {
-       yy_state_type yy_current_state;
-       char *yy_cp, *yy_bp;
-       int yy_act;
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
      
 -#line 1001 "lexer.cc"
+ /* %% [7.0] user's declarations go here */
+ #line 75 "lexer.ll"
+     // Code run each time yylex is called.
+     loc.step();
++#line 1027 "lexer.cc"
        if ( !(yy_init) )
                {
                (yy_init) = 1;
@@@ -1099,14 -1065,14 +1091,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 >= 129 )
 -                              if ( yy_current_state >= 132 )
++                              if ( yy_current_state >= 161 )
                                        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 != 128 );
 -              while ( yy_current_state != 131 );
++              while ( yy_current_state != 160 );
  
  yy_find_action:
  /* %% [10.0] code to find the action number goes here */
@@@ -1169,13 -1136,13 +1162,13 @@@ do_action:   /* This label is used only t
                        {
                        if ( yy_act == 0 )
                                fprintf( stderr, "--scanner backing up\n" );
-                       else if ( yy_act < 33 )
 -                      else if ( yy_act < 35 )
++                      else if ( yy_act < 41 )
                                fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
                                         (long)yy_rule_linenum[yy_act], yytext );
-                       else if ( yy_act == 33 )
 -                      else if ( yy_act == 35 )
++                      else if ( yy_act == 41 )
                                fprintf( stderr, "--accepting default rule (\"%s\")\n",
                                         yytext );
-                       else if ( yy_act == 34 )
 -                      else if ( yy_act == 36 )
++                      else if ( yy_act == 42 )
                                fprintf( stderr, "--(end of buffer or a NUL)\n" );
                        else
                                fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@@ -1317,93 -1284,103 +1310,133 @@@ return isc::eval::EvalParser::make_EXIS
  case 17:
  YY_RULE_SETUP
  #line 152 "lexer.ll"
- return isc::eval::EvalParser::make_SUBSTRING(loc);
 -return isc::eval::EvalParser::make_HTYPE(loc);
++return isc::eval::EvalParser::make_PKT4(loc);
        YY_BREAK
  case 18:
  YY_RULE_SETUP
  #line 153 "lexer.ll"
- return isc::eval::EvalParser::make_ALL(loc);
 -return isc::eval::EvalParser::make_CIADDR(loc);
++return isc::eval::EvalParser::make_CHADDR(loc);
        YY_BREAK
  case 19:
  YY_RULE_SETUP
  #line 154 "lexer.ll"
- return isc::eval::EvalParser::make_CONCAT(loc);
 -return isc::eval::EvalParser::make_GIADDR(loc);
++return isc::eval::EvalParser::make_HLEN(loc);
        YY_BREAK
  case 20:
  YY_RULE_SETUP
  #line 155 "lexer.ll"
- return isc::eval::EvalParser::make_NOT(loc);
 -return isc::eval::EvalParser::make_YIADDR(loc);
++return isc::eval::EvalParser::make_HTYPE(loc);
        YY_BREAK
  case 21:
  YY_RULE_SETUP
  #line 156 "lexer.ll"
- return isc::eval::EvalParser::make_AND(loc);
 -return isc::eval::EvalParser::make_SIADDR(loc);
++return isc::eval::EvalParser::make_CIADDR(loc);
        YY_BREAK
  case 22:
  YY_RULE_SETUP
  #line 157 "lexer.ll"
- return isc::eval::EvalParser::make_OR(loc);
 -return isc::eval::EvalParser::make_SUBSTRING(loc);
++return isc::eval::EvalParser::make_GIADDR(loc);
        YY_BREAK
  case 23:
  YY_RULE_SETUP
  #line 158 "lexer.ll"
- return isc::eval::EvalParser::make_DOT(loc);
 -return isc::eval::EvalParser::make_ALL(loc);
++return isc::eval::EvalParser::make_YIADDR(loc);
        YY_BREAK
  case 24:
  YY_RULE_SETUP
  #line 159 "lexer.ll"
- return isc::eval::EvalParser::make_LPAREN(loc);
 -return isc::eval::EvalParser::make_CONCAT(loc);
++return isc::eval::EvalParser::make_SIADDR(loc);
        YY_BREAK
  case 25:
  YY_RULE_SETUP
  #line 160 "lexer.ll"
- return isc::eval::EvalParser::make_RPAREN(loc);
 -return isc::eval::EvalParser::make_NOT(loc);
++return isc::eval::EvalParser::make_SUBSTRING(loc);
        YY_BREAK
  case 26:
  YY_RULE_SETUP
  #line 161 "lexer.ll"
- return isc::eval::EvalParser::make_LBRACKET(loc);
 -return isc::eval::EvalParser::make_AND(loc);
++return isc::eval::EvalParser::make_ALL(loc);
        YY_BREAK
  case 27:
  YY_RULE_SETUP
  #line 162 "lexer.ll"
- return isc::eval::EvalParser::make_RBRACKET(loc);
 -return isc::eval::EvalParser::make_OR(loc);
++return isc::eval::EvalParser::make_CONCAT(loc);
        YY_BREAK
  case 28:
  YY_RULE_SETUP
  #line 163 "lexer.ll"
- return isc::eval::EvalParser::make_COMA(loc);
 -return isc::eval::EvalParser::make_DOT(loc);
++return isc::eval::EvalParser::make_NOT(loc);
        YY_BREAK
  case 29:
  YY_RULE_SETUP
- #line 165 "lexer.ll"
- return isc::eval::EvalParser::make_PKT6(loc);
+ #line 164 "lexer.ll"
 -return isc::eval::EvalParser::make_LPAREN(loc);
++return isc::eval::EvalParser::make_AND(loc);
        YY_BREAK
  case 30:
  YY_RULE_SETUP
- #line 166 "lexer.ll"
- return isc::eval::EvalParser::make_MSGTYPE(loc);
+ #line 165 "lexer.ll"
 -return isc::eval::EvalParser::make_RPAREN(loc);
++return isc::eval::EvalParser::make_OR(loc);
        YY_BREAK
  case 31:
  YY_RULE_SETUP
- #line 167 "lexer.ll"
- return isc::eval::EvalParser::make_TRANSID(loc);
+ #line 166 "lexer.ll"
 -return isc::eval::EvalParser::make_LBRACKET(loc);
++return isc::eval::EvalParser::make_DOT(loc);
        YY_BREAK
  case 32:
  YY_RULE_SETUP
 -return isc::eval::EvalParser::make_RBRACKET(loc);
+ #line 167 "lexer.ll"
 -return isc::eval::EvalParser::make_COMA(loc);
++return isc::eval::EvalParser::make_LPAREN(loc);
+       YY_BREAK
+ case 33:
+ YY_RULE_SETUP
+ #line 168 "lexer.ll"
++return isc::eval::EvalParser::make_RPAREN(loc);
+       YY_BREAK
+ case 34:
+ YY_RULE_SETUP
 +#line 169 "lexer.ll"
++return isc::eval::EvalParser::make_LBRACKET(loc);
++      YY_BREAK
++case 35:
++YY_RULE_SETUP
+ #line 170 "lexer.ll"
++return isc::eval::EvalParser::make_RBRACKET(loc);
++      YY_BREAK
++case 36:
++YY_RULE_SETUP
++#line 171 "lexer.ll"
++return isc::eval::EvalParser::make_COMA(loc);
++      YY_BREAK
++case 37:
++YY_RULE_SETUP
++#line 173 "lexer.ll"
++return isc::eval::EvalParser::make_PKT6(loc);
++      YY_BREAK
++case 38:
++YY_RULE_SETUP
++#line 174 "lexer.ll"
++return isc::eval::EvalParser::make_MSGTYPE(loc);
++      YY_BREAK
++case 39:
++YY_RULE_SETUP
++#line 175 "lexer.ll"
++return isc::eval::EvalParser::make_TRANSID(loc);
++      YY_BREAK
++case 40:
++YY_RULE_SETUP
++#line 177 "lexer.ll"
  driver.error (loc, "Invalid character: " + std::string(yytext));
        YY_BREAK
  case YY_STATE_EOF(INITIAL):
- #line 170 "lexer.ll"
 -#line 171 "lexer.ll"
++#line 178 "lexer.ll"
  return isc::eval::EvalParser::make_END(loc);
        YY_BREAK
- case 33:
 -case 35:
++case 41:
  YY_RULE_SETUP
- #line 171 "lexer.ll"
 -#line 172 "lexer.ll"
++#line 179 "lexer.ll"
  ECHO;
        YY_BREAK
- #line 1407 "lexer.cc"
 -#line 1384 "lexer.cc"
++#line 1440 "lexer.cc"
  
        case YY_END_OF_BUFFER:
                {
@@@ -1688,7 -1660,7 +1716,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 >= 129 )
 -                      if ( yy_current_state >= 132 )
++                      if ( yy_current_state >= 161 )
                                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 >= 129 )
 -              if ( yy_current_state >= 132 )
++              if ( yy_current_state >= 161 )
                        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 == 128);
 -      yy_is_jam = (yy_current_state == 131);
++      yy_is_jam = (yy_current_state == 160);
        if ( ! yy_is_jam )
                *(yy_state_ptr)++ = yy_current_state;
  
@@@ -2486,7 -2450,7 +2506,7 @@@ void yyfree (void * ptr 
  
  /* %ok-for-header */
  
- #line 171 "lexer.ll"
 -#line 172 "lexer.ll"
++#line 179 "lexer.ll"
  
  
  
Simple merge
index fa8038cfc69da0ccd198ad71aeb0a4c3f140931b,520ea3711b90164e962ab8ee83095eb0394edbcd..c14a54942fc3bbc512a989760bd82061b33f758d
@@@ -251,34 -251,26 +251,38 @@@ namespace isc { namespace eval 
    {
        switch (that.type_get ())
      {
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          value.move< TokenOption::RepresentationType > (that.value);
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         value.move< TokenPkt4::FieldType > (that.value);
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        value.move< TokenPkt6::FieldType > (that.value);
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        value.move< TokenRelay6Field::FieldType > (that.value);
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          value.move< std::string > (that.value);
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          value.move< uint16_t > (that.value);
          break;
  
-       case 41: // nest_level
++      case 50: // nest_level
 +        value.move< uint8_t > (that.value);
 +        break;
 +
        default:
          break;
      }
      state = that.state;
        switch (that.type_get ())
      {
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          value.copy< TokenOption::RepresentationType > (that.value);
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         value.copy< TokenPkt4::FieldType > (that.value);
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        value.copy< TokenPkt6::FieldType > (that.value);
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        value.copy< TokenRelay6Field::FieldType > (that.value);
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          value.copy< std::string > (that.value);
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          value.copy< uint16_t > (that.value);
          break;
  
-       case 41: // nest_level
++      case 50: // nest_level
 +        value.copy< uint8_t > (that.value);
 +        break;
 +
        default:
          break;
      }
          << yysym.location << ": ";
      switch (yytype)
      {
-             case 27: // "constant string"
 -            case 29: // "constant string"
++            case 35: // "constant string"
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 366 "parser.cc" // lalr1.cc:636
 -#line 350 "parser.cc" // lalr1.cc:636
++#line 374 "parser.cc" // lalr1.cc:636
          break;
  
-       case 28: // "integer"
 -      case 30: // "integer"
++      case 36: // "integer"
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 373 "parser.cc" // lalr1.cc:636
 -#line 357 "parser.cc" // lalr1.cc:636
++#line 381 "parser.cc" // lalr1.cc:636
          break;
  
-       case 29: // "constant hexstring"
 -      case 31: // "constant hexstring"
++      case 37: // "constant hexstring"
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 380 "parser.cc" // lalr1.cc:636
 -#line 364 "parser.cc" // lalr1.cc:636
++#line 388 "parser.cc" // lalr1.cc:636
          break;
  
-       case 30: // "option name"
 -      case 32: // "option name"
++      case 38: // "option name"
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 387 "parser.cc" // lalr1.cc:636
 -#line 371 "parser.cc" // lalr1.cc:636
++#line 395 "parser.cc" // lalr1.cc:636
          break;
  
-       case 31: // "ip address"
 -      case 33: // "ip address"
++      case 39: // "ip address"
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< std::string > (); }
- #line 394 "parser.cc" // lalr1.cc:636
 -#line 378 "parser.cc" // lalr1.cc:636
++#line 402 "parser.cc" // lalr1.cc:636
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< uint16_t > (); }
- #line 401 "parser.cc" // lalr1.cc:636
 -#line 385 "parser.cc" // lalr1.cc:636
++#line 409 "parser.cc" // lalr1.cc:636
          break;
  
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
  
--#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
          { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
- #line 408 "parser.cc" // lalr1.cc:636
 -#line 392 "parser.cc" // lalr1.cc:636
++#line 416 "parser.cc" // lalr1.cc:636
+         break;
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
 -#line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
+         { yyoutput << yysym.value.template as< TokenPkt4::FieldType > (); }
 -#line 399 "parser.cc" // lalr1.cc:636
++#line 423 "parser.cc" // lalr1.cc:636
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +
- #line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< TokenRelay6Field::FieldType > (); }
- #line 415 "parser.cc" // lalr1.cc:636
++#line 430 "parser.cc" // lalr1.cc:636
 +        break;
 +
-       case 41: // nest_level
++      case 50: // nest_level
 +
- #line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< uint8_t > (); }
- #line 422 "parser.cc" // lalr1.cc:636
++#line 437 "parser.cc" // lalr1.cc:636
 +        break;
 +
-       case 42: // pkt6_field
++      case 51: // pkt6_field
 +
- #line 82 "parser.yy" // lalr1.cc:636
++#line 91 "parser.yy" // lalr1.cc:636
 +        { yyoutput << yysym.value.template as< TokenPkt6::FieldType > (); }
- #line 429 "parser.cc" // lalr1.cc:636
++#line 444 "parser.cc" // lalr1.cc:636
          break;
  
  
           when using variants.  */
          switch (yyr1_[yyn])
      {
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          yylhs.value.build< TokenOption::RepresentationType > ();
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         yylhs.value.build< TokenPkt4::FieldType > ();
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        yylhs.value.build< TokenPkt6::FieldType > ();
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        yylhs.value.build< TokenRelay6Field::FieldType > ();
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          yylhs.value.build< std::string > ();
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          yylhs.value.build< uint16_t > ();
          break;
  
-       case 41: // nest_level
++      case 50: // nest_level
 +        yylhs.value.build< uint8_t > ();
 +        break;
 +
        default:
          break;
      }
            switch (yyn)
              {
    case 4:
--#line 96 "parser.yy" // lalr1.cc:859
++#line 105 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenNot());
                      ctx.expression.push_back(neg);
                  }
- #line 680 "parser.cc" // lalr1.cc:859
 -#line 642 "parser.cc" // lalr1.cc:859
++#line 699 "parser.cc" // lalr1.cc:859
      break;
  
    case 5:
--#line 101 "parser.yy" // lalr1.cc:859
++#line 110 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenAnd());
                      ctx.expression.push_back(neg);
                  }
- #line 689 "parser.cc" // lalr1.cc:859
 -#line 651 "parser.cc" // lalr1.cc:859
++#line 708 "parser.cc" // lalr1.cc:859
      break;
  
    case 6:
--#line 106 "parser.yy" // lalr1.cc:859
++#line 115 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr neg(new TokenOr());
                      ctx.expression.push_back(neg);
                  }
- #line 698 "parser.cc" // lalr1.cc:859
 -#line 660 "parser.cc" // lalr1.cc:859
++#line 717 "parser.cc" // lalr1.cc:859
      break;
  
    case 7:
--#line 111 "parser.yy" // lalr1.cc:859
++#line 120 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr eq(new TokenEqual());
                      ctx.expression.push_back(eq);
                  }
- #line 707 "parser.cc" // lalr1.cc:859
 -#line 669 "parser.cc" // lalr1.cc:859
++#line 726 "parser.cc" // lalr1.cc:859
      break;
  
    case 8:
--#line 116 "parser.yy" // lalr1.cc:859
++#line 125 "parser.yy" // lalr1.cc:859
      {
                      TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
                      ctx.expression.push_back(opt);
                  }
- #line 716 "parser.cc" // lalr1.cc:859
 -#line 678 "parser.cc" // lalr1.cc:859
++#line 735 "parser.cc" // lalr1.cc:859
      break;
  
    case 9:
--#line 121 "parser.yy" // lalr1.cc:859
++#line 130 "parser.yy" // lalr1.cc:859
      {
                     switch (ctx.getUniverse()) {
                     case Option::V4:
                         error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                     }
                  }
- #line 740 "parser.cc" // lalr1.cc:859
 -#line 702 "parser.cc" // lalr1.cc:859
++#line 759 "parser.cc" // lalr1.cc:859
      break;
  
    case 10:
- #line 141 "parser.yy" // lalr1.cc:859
 -#line 143 "parser.yy" // lalr1.cc:859
++#line 150 "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 758 "parser.cc" // lalr1.cc:859
++#line 777 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 11:
- #line 157 "parser.yy" // lalr1.cc:859
++#line 166 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(str);
                    }
- #line 767 "parser.cc" // lalr1.cc:859
 -#line 711 "parser.cc" // lalr1.cc:859
++#line 786 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 11:
 -#line 148 "parser.yy" // lalr1.cc:859
 +  case 12:
- #line 162 "parser.yy" // lalr1.cc:859
++#line 171 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(hex);
                    }
- #line 776 "parser.cc" // lalr1.cc:859
 -#line 720 "parser.cc" // lalr1.cc:859
++#line 795 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 12:
 -#line 153 "parser.yy" // lalr1.cc:859
 +  case 13:
- #line 167 "parser.yy" // lalr1.cc:859
++#line 176 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(ip);
                    }
- #line 785 "parser.cc" // lalr1.cc:859
 -#line 729 "parser.cc" // lalr1.cc:859
++#line 804 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 13:
 -#line 158 "parser.yy" // lalr1.cc:859
 +  case 14:
- #line 172 "parser.yy" // lalr1.cc:859
++#line 181 "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 794 "parser.cc" // lalr1.cc:859
 -#line 738 "parser.cc" // lalr1.cc:859
++#line 813 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 14:
 -#line 163 "parser.yy" // lalr1.cc:859
 +  case 15:
- #line 177 "parser.yy" // lalr1.cc:859
++#line 186 "parser.yy" // lalr1.cc:859
      {
                       switch (ctx.getUniverse()) {
                       case Option::V4:
                           error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                       }
                    }
- #line 818 "parser.cc" // lalr1.cc:859
 -#line 762 "parser.cc" // lalr1.cc:859
++#line 837 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 15:
 -#line 183 "parser.yy" // lalr1.cc:859
 +  case 16:
- #line 198 "parser.yy" // lalr1.cc:859
++#line 207 "parser.yy" // lalr1.cc:859
      {
 -                      TokenPtr pkt4field(new TokenPkt4(yystack_[0].value.as< TokenPkt4::FieldType > ()));
 -                      ctx.expression.push_back(pkt4field);
 +                     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 836 "parser.cc" // lalr1.cc:859
 -#line 771 "parser.cc" // lalr1.cc:859
++#line 855 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 16:
 -#line 188 "parser.yy" // lalr1.cc:859
 +  case 17:
- #line 213 "parser.yy" // lalr1.cc:859
++#line 222 "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 854 "parser.cc" // lalr1.cc:859
++#line 873 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 18:
- #line 229 "parser.yy" // lalr1.cc:859
++#line 237 "parser.yy" // lalr1.cc:859
 +    {
-                       TokenPtr sub(new TokenSubstring());
-                       ctx.expression.push_back(sub);
++                      TokenPtr pkt4_field(new TokenPkt4(yystack_[0].value.as< TokenPkt4::FieldType > ()));
++                      ctx.expression.push_back(pkt4_field);
 +                  }
- #line 863 "parser.cc" // lalr1.cc:859
++#line 882 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 19:
- #line 234 "parser.yy" // lalr1.cc:859
++#line 242 "parser.yy" // lalr1.cc:859
 +    {
-                       TokenPtr conc(new TokenConcat());
-                       ctx.expression.push_back(conc);
++                      TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
++                      ctx.expression.push_back(pkt6_field);
 +                  }
- #line 872 "parser.cc" // lalr1.cc:859
++#line 891 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +  case 20:
- #line 239 "parser.yy" // lalr1.cc:859
++#line 247 "parser.yy" // lalr1.cc:859
      {
-                       TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
-                       ctx.expression.push_back(pkt6_field);
+                       TokenPtr sub(new TokenSubstring());
+                       ctx.expression.push_back(sub);
                    }
- #line 881 "parser.cc" // lalr1.cc:859
 -#line 780 "parser.cc" // lalr1.cc:859
++#line 900 "parser.cc" // lalr1.cc:859
      break;
  
 -  case 17:
 -#line 193 "parser.yy" // lalr1.cc:859
 +  case 21:
- #line 246 "parser.yy" // lalr1.cc:859
++#line 252 "parser.yy" // lalr1.cc:859
+     {
+                       TokenPtr conc(new TokenConcat());
+                       ctx.expression.push_back(conc);
+                   }
 -#line 789 "parser.cc" // lalr1.cc:859
++#line 909 "parser.cc" // lalr1.cc:859
+     break;
 -  case 18:
 -#line 200 "parser.yy" // lalr1.cc:859
++  case 22:
++#line 259 "parser.yy" // lalr1.cc:859
      {
                       yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
                   }
- #line 889 "parser.cc" // lalr1.cc:859
 -#line 797 "parser.cc" // lalr1.cc:859
++#line 917 "parser.cc" // lalr1.cc:859
      break;
  
-   case 22:
- #line 250 "parser.yy" // lalr1.cc:859
 -  case 19:
 -#line 204 "parser.yy" // lalr1.cc:859
++  case 23:
++#line 263 "parser.yy" // lalr1.cc:859
      {
                       yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
                   }
- #line 897 "parser.cc" // lalr1.cc:859
 -#line 805 "parser.cc" // lalr1.cc:859
++#line 925 "parser.cc" // lalr1.cc:859
      break;
  
-   case 23:
- #line 256 "parser.yy" // lalr1.cc:859
 -  case 20:
 -#line 210 "parser.yy" // lalr1.cc:859
++  case 24:
++#line 269 "parser.yy" // lalr1.cc:859
      {
                            yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                        }
- #line 905 "parser.cc" // lalr1.cc:859
 -#line 813 "parser.cc" // lalr1.cc:859
++#line 933 "parser.cc" // lalr1.cc:859
      break;
  
-   case 24:
- #line 260 "parser.yy" // lalr1.cc:859
 -  case 21:
 -#line 214 "parser.yy" // lalr1.cc:859
++  case 25:
++#line 273 "parser.yy" // lalr1.cc:859
      {
                            yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
                        }
- #line 913 "parser.cc" // lalr1.cc:859
 -#line 821 "parser.cc" // lalr1.cc:859
++#line 941 "parser.cc" // lalr1.cc:859
      break;
  
-   case 25:
- #line 266 "parser.yy" // lalr1.cc:859
 -  case 22:
 -#line 220 "parser.yy" // lalr1.cc:859
++  case 26:
++#line 279 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CHADDR;
+                 }
 -#line 829 "parser.cc" // lalr1.cc:859
++#line 949 "parser.cc" // lalr1.cc:859
+     break;
 -  case 23:
 -#line 224 "parser.yy" // lalr1.cc:859
++  case 27:
++#line 283 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HLEN;
+                 }
 -#line 837 "parser.cc" // lalr1.cc:859
++#line 957 "parser.cc" // lalr1.cc:859
+     break;
 -  case 24:
 -#line 228 "parser.yy" // lalr1.cc:859
++  case 28:
++#line 287 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::HTYPE;
+                 }
 -#line 845 "parser.cc" // lalr1.cc:859
++#line 965 "parser.cc" // lalr1.cc:859
+     break;
 -  case 25:
 -#line 232 "parser.yy" // lalr1.cc:859
++  case 29:
++#line 291 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::CIADDR;
+                 }
 -#line 853 "parser.cc" // lalr1.cc:859
++#line 973 "parser.cc" // lalr1.cc:859
+     break;
 -  case 26:
 -#line 236 "parser.yy" // lalr1.cc:859
++  case 30:
++#line 295 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::GIADDR;
+                 }
 -#line 861 "parser.cc" // lalr1.cc:859
++#line 981 "parser.cc" // lalr1.cc:859
+     break;
 -  case 27:
 -#line 240 "parser.yy" // lalr1.cc:859
++  case 31:
++#line 299 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::YIADDR;
+                 }
 -#line 869 "parser.cc" // lalr1.cc:859
++#line 989 "parser.cc" // lalr1.cc:859
+     break;
 -  case 28:
 -#line 244 "parser.yy" // lalr1.cc:859
++  case 32:
++#line 303 "parser.yy" // lalr1.cc:859
+     {
+                     yylhs.value.as< TokenPkt4::FieldType > () = TokenPkt4::SIADDR;
+                 }
 -#line 877 "parser.cc" // lalr1.cc:859
++#line 997 "parser.cc" // lalr1.cc:859
+     break;
 -  case 29:
 -#line 250 "parser.yy" // lalr1.cc:859
++  case 33:
++#line 309 "parser.yy" // lalr1.cc:859
      {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
- #line 922 "parser.cc" // lalr1.cc:859
 -#line 886 "parser.cc" // lalr1.cc:859
++#line 1006 "parser.cc" // lalr1.cc:859
      break;
  
-   case 26:
- #line 273 "parser.yy" // lalr1.cc:859
 -  case 30:
 -#line 257 "parser.yy" // lalr1.cc:859
++  case 34:
++#line 316 "parser.yy" // lalr1.cc:859
      {
                        TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                        ctx.expression.push_back(str);
                    }
- #line 931 "parser.cc" // lalr1.cc:859
 -#line 895 "parser.cc" // lalr1.cc:859
++#line 1015 "parser.cc" // lalr1.cc:859
      break;
  
-   case 27:
- #line 278 "parser.yy" // lalr1.cc:859
 -  case 31:
 -#line 262 "parser.yy" // lalr1.cc:859
++  case 35:
++#line 321 "parser.yy" // lalr1.cc:859
      {
                       TokenPtr str(new TokenString("all"));
                       ctx.expression.push_back(str);
                   }
- #line 940 "parser.cc" // lalr1.cc:859
 -#line 904 "parser.cc" // lalr1.cc:859
++#line 1024 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 28:
- #line 284 "parser.yy" // lalr1.cc:859
++  case 36:
++#line 327 "parser.yy" // lalr1.cc:859
 +    { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR; }
- #line 946 "parser.cc" // lalr1.cc:859
++#line 1030 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 29:
- #line 285 "parser.yy" // lalr1.cc:859
++  case 37:
++#line 328 "parser.yy" // lalr1.cc:859
 +    { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR; }
- #line 952 "parser.cc" // lalr1.cc:859
++#line 1036 "parser.cc" // lalr1.cc:859
      break;
  
-   case 30:
- #line 289 "parser.yy" // lalr1.cc:859
++  case 38:
++#line 332 "parser.yy" // lalr1.cc:859
 +    {
 +               yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location);
 +                 }
- #line 960 "parser.cc" // lalr1.cc:859
++#line 1044 "parser.cc" // lalr1.cc:859
 +    break;
  
-   case 31:
- #line 297 "parser.yy" // lalr1.cc:859
 -#line 908 "parser.cc" // lalr1.cc:859
++  case 39:
++#line 340 "parser.yy" // lalr1.cc:859
 +    { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE; }
- #line 966 "parser.cc" // lalr1.cc:859
++#line 1050 "parser.cc" // lalr1.cc:859
 +    break;
 +
-   case 32:
- #line 298 "parser.yy" // lalr1.cc:859
++  case 40:
++#line 341 "parser.yy" // lalr1.cc:859
 +    { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID; }
- #line 972 "parser.cc" // lalr1.cc:859
++#line 1056 "parser.cc" // lalr1.cc:859
 +    break;
 +
 +
- #line 976 "parser.cc" // lalr1.cc:859
++#line 1060 "parser.cc" // lalr1.cc:859
              default:
                break;
              }
    }
  
  
-   const signed char EvalParser::yypact_ninf_ = -54;
 -  const signed char EvalParser::yypact_ninf_ = -47;
++  const signed char EvalParser::yypact_ninf_ = -62;
  
    const signed char EvalParser::yytable_ninf_ = -1;
  
    const signed char
    EvalParser::yypact_[] =
    {
-       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
 -       9,     9,     9,    -4,    25,    26,    38,    45,   -47,   -47,
 -     -47,    50,    23,    52,     4,   -47,    29,    29,    34,    18,
 -      18,   -47,     9,     9,    18,   -47,   -47,   -47,    51,    53,
 -     -47,   -47,   -47,   -47,   -47,   -47,   -47,   -47,    55,    56,
 -      35,    37,   -47,    62,   -47,    57,    58,    29,    29,    39,
 -      18,     1,     6,    60,    61,   -47,    47,    71,   -47,   -47,
 -     -47,   -47,   -47,   -47,    63,    64,   -17,   -47,    30,    30,
 -     -47,   -47,    74,   -47
++      14,    14,    14,     6,    17,    18,    21,    41,    44,    48,
++     -62,   -62,   -62,    72,    20,    66,    29,   -62,    12,    12,
++      16,    36,    45,    45,   -24,   -62,    14,    14,    45,   -62,
++     -62,   -62,    60,    63,   -62,    73,   -62,   -62,   -62,   -62,
++     -62,   -62,   -62,   -62,    67,    69,    75,    61,    62,   -62,
++     -62,   -62,   -62,    84,   -62,    77,    78,    79,    12,    12,
++      16,    64,    45,    -3,    52,    -1,    81,    82,    83,   -62,
++      71,    95,   -62,   -62,   -62,   -62,   -62,   -62,    88,   -62,
++     -62,   -62,    87,    89,    90,   -23,   -62,    12,    49,    49,
++       9,   -62,   -62,   100,    92,    94,   -62,    93,    12,    68,
++      96,   -62,   -62,    97,    49
    };
  
    const unsigned char
    EvalParser::yydefact_[] =
    {
-        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,     0,     0,     0,     0,     0,     0,     0,    10,    11,
 -      12,     0,     2,     0,     0,     4,     0,     0,     0,     0,
 -       0,     1,     0,     0,     0,     3,    18,    19,     0,     0,
 -      22,    23,    24,    25,    26,    27,    28,    15,     0,     0,
 -       0,     0,     5,     6,     7,     0,     0,     0,     0,     0,
 -       0,     0,     0,     0,     0,    29,     0,     0,    20,    21,
 -       8,    13,     9,    14,     0,     0,     0,    17,     0,     0,
 -      31,    30,     0,    16
++       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
++      11,    12,    13,     0,     2,     0,     0,     4,     0,     0,
++       0,     0,     0,     0,     0,     1,     0,     0,     0,     3,
++      22,    23,     0,     0,    38,     0,    26,    27,    28,    29,
++      30,    31,    32,    18,     0,     0,     0,     0,     0,    39,
++      40,    19,     5,     6,     7,     0,     0,     0,     0,     0,
++       0,     0,     0,     0,     0,     0,     0,     0,     0,    33,
++       0,     0,    24,    25,     8,    14,     9,    15,     0,    36,
++      37,    17,     0,     0,     0,     0,    21,     0,     0,     0,
++       0,    35,    34,     0,     0,     0,    20,     0,     0,     0,
 +       0,    10,    16,     0,     0
    };
  
    const signed char
    EvalParser::yypgoto_[] =
    {
-      -54,   -54,     4,   -17,   -18,   -53,   -54,   -54,   -54,    51,
-      -54
 -     -47,   -47,     2,   -19,   -15,   -46,   -47,   -47,   -47
++     -62,   -62,     3,   -21,   -19,   -61,   -62,   -62,   -62,   -62,
++      50,   -62
    };
  
    const signed char
    EvalParser::yydefgoto_[] =
    {
-       -1,    12,    13,    14,    30,    65,    60,    83,    71,    33,
-       41
 -      -1,    11,    12,    13,    28,    61,    37,    56,    72
++      -1,    13,    14,    15,    32,    75,    43,    70,    93,    81,
++      35,    51
    };
  
    const unsigned char
    EvalParser::yytable_[] =
    {
-       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
 -      40,    41,    29,    14,    15,    44,    63,    16,    25,    70,
 -      22,    23,     1,    71,     2,    58,    59,    60,     3,     4,
 -      58,    59,    62,    63,    42,    43,     5,    38,    39,    22,
 -      23,    57,    53,    54,     6,     5,    17,     7,     8,    18,
 -       9,    19,    10,     6,    58,    59,     7,     8,    20,     9,
 -      21,    10,    30,    31,    32,    33,    34,    35,    36,    26,
 -      24,    27,    49,    45,    50,    46,    47,    48,    22,    55,
 -      51,    52,    64,    65,    66,    67,    68,    69,    73
++      33,    47,    48,    77,    16,    17,    91,    54,    78,    49,
++      50,    79,    80,    92,    72,    73,    74,     1,    95,     2,
++      18,    79,    80,     3,     4,     5,    26,    27,    77,    52,
++      53,    19,    20,    29,     6,    26,    27,    21,   102,    66,
++      67,    71,     7,   102,    22,     8,     9,    23,    30,    10,
++      31,    11,    34,    12,    44,    45,    46,    36,    37,    38,
++      39,    40,    41,    42,    24,     6,    72,    73,    94,    72,
++      73,    76,    25,     7,    28,    55,     8,     9,    56,   100,
++      10,    58,    11,    59,    12,    72,    73,   101,    57,    60,
++      26,    61,    62,    63,    64,    65,    82,    83,    84,    86,
++      69,    85,    87,    88,    96,    89,    90,    97,    98,    99,
++      68,   103,     0,   104
    };
  
--  const unsigned char
++  const signed char
    EvalParser::yycheck_[] =
    {
-       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
 -      19,    20,    17,     1,     2,    24,    52,    11,     4,    26,
 -       6,     7,     3,    30,     5,    14,    15,    16,     9,    10,
 -      14,    15,    16,    69,    22,    23,    17,     9,    10,     6,
 -       7,    50,    47,    48,    25,    17,    11,    28,    29,    13,
 -      31,     3,    33,    25,    14,    15,    28,    29,     3,    31,
 -       0,    33,    18,    19,    20,    21,    22,    23,    24,    30,
 -       8,    32,    27,    12,    27,    12,    11,    11,     6,    30,
 -      13,    13,    12,    12,    27,     4,    13,    13,     4
++      19,    22,    23,    64,     1,     2,    29,    28,     9,    33,
++      34,    12,    13,    36,    17,    18,    19,     3,     9,     5,
++      14,    12,    13,     9,    10,    11,     6,     7,    89,    26,
++      27,    14,    14,     4,    20,     6,     7,    16,    99,    58,
++      59,    62,    28,   104,     3,    31,    32,     3,    36,    35,
++      38,    37,    36,    39,     9,    10,    11,    21,    22,    23,
++      24,    25,    26,    27,    16,    20,    17,    18,    87,    17,
++      18,    19,     0,    28,     8,    15,    31,    32,    15,    98,
++      35,    14,    37,    14,    39,    17,    18,    19,    15,    14,
++       6,    30,    30,    16,    16,    16,    15,    15,    15,     4,
++      36,    30,    14,    16,     4,    16,    16,    15,    14,    16,
++      60,    15,    -1,    16
    };
  
    const unsigned char
    EvalParser::yystos_[] =
    {
-        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
 -       0,     3,     5,     9,    10,    17,    25,    28,    29,    31,
 -      33,    35,    36,    37,    36,    36,    11,    11,    13,     3,
 -       3,     0,     6,     7,     8,     4,    30,    32,    38,    38,
 -      18,    19,    20,    21,    22,    23,    24,    40,     9,    10,
 -      37,    37,    36,    36,    37,    12,    12,    11,    11,    27,
 -      27,    13,    13,    38,    38,    30,    41,    37,    14,    15,
 -      16,    39,    16,    39,    12,    12,    27,     4,    13,    13,
 -      26,    30,    42,     4
++       0,     3,     5,     9,    10,    11,    20,    28,    31,    32,
++      35,    37,    39,    41,    42,    43,    42,    42,    14,    14,
++      14,    16,     3,     3,    16,     0,     6,     7,     8,     4,
++      36,    38,    44,    44,    36,    50,    21,    22,    23,    24,
++      25,    26,    27,    46,     9,    10,    11,    43,    43,    33,
++      34,    51,    42,    42,    43,    15,    15,    15,    14,    14,
++      14,    30,    30,    16,    16,    16,    44,    44,    50,    36,
++      47,    43,    17,    18,    19,    45,    19,    45,     9,    12,
++      13,    49,    15,    15,    15,    30,     4,    14,    16,    16,
++      16,    29,    36,    48,    44,     9,     4,    15,    14,    16,
++      44,    19,    45,    15,    16
    };
  
    const unsigned char
    EvalParser::yyr1_[] =
    {
-        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
 -       0,    34,    35,    36,    36,    36,    36,    36,    36,    36,
 -      37,    37,    37,    37,    37,    37,    37,    37,    38,    38,
 -      39,    39,    40,    40,    40,    40,    40,    40,    40,    41,
 -      42,    42
++       0,    40,    41,    42,    42,    42,    42,    42,    42,    42,
++      42,    43,    43,    43,    43,    43,    43,    43,    43,    43,
++      43,    43,    44,    44,    45,    45,    46,    46,    46,    46,
++      46,    46,    46,    47,    48,    48,    49,    49,    50,    51,
++      51
    };
  
    const unsigned char
    EvalParser::yyr2_[] =
    {
         0,     2,     1,     3,     2,     3,     3,     3,     6,     6,
-       11,     1,     1,     1,     6,     6,    11,     6,     8,     6,
-        3,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-        1,     1,     1
 -       1,     1,     1,     6,     6,     3,     8,     6,     1,     1,
++      11,     1,     1,     1,     6,     6,    11,     6,     3,     3,
++       8,     6,     1,     1,     1,     1,     1,     1,     1,     1,
+        1,     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\"", "\"pkt4\"",
 -  "\"mac\"", "\"hlen\"", "\"htype\"", "\"ciaddr\"", "\"giaddr\"",
 -  "\"yiaddr\"", "\"siaddr\"", "\"substring\"", "\"all\"", "\",\"",
 -  "\"concat\"", "\"constant string\"", "\"integer\"",
 +  "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"relay6\"",
 +  "\"peeraddr\"", "\"linkaddr\"", "\"[\"", "\"]\"", "\".\"", "\"text\"",
-   "\"hex\"", "\"exists\"", "\"substring\"", "\"all\"", "\",\"",
-   "\"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", "relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
++  "\"hex\"", "\"exists\"", "\"pkt4\"", "\"mac\"", "\"hlen\"", "\"htype\"",
++  "\"ciaddr\"", "\"giaddr\"", "\"yiaddr\"", "\"siaddr\"", "\"substring\"",
++  "\"all\"", "\",\"", "\"concat\"", "\"pkt6\"", "\"msgtype\"",
++  "\"transid\"", "\"constant string\"", "\"integer\"",
+   "\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept",
+   "expression", "bool_expr", "string_expr", "option_code",
 -  "option_repr_type", "pkt4_field", "start_expr", "length_expr", YY_NULLPTR
++  "option_repr_type", "pkt4_field", "start_expr", "length_expr",
++  "relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
    };
  
  #if YYDEBUG
    const unsigned short int
    EvalParser::yyrline_[] =
    {
--       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
 -     142,   147,   152,   157,   162,   182,   187,   192,   199,   203,
 -     209,   213,   219,   223,   227,   231,   235,   239,   243,   249,
 -     256,   261
++       0,   100,   100,   103,   104,   109,   114,   119,   124,   129,
++     149,   165,   170,   175,   180,   185,   206,   221,   236,   241,
++     246,   251,   258,   262,   268,   272,   278,   282,   286,   290,
++     294,   298,   302,   308,   315,   320,   327,   328,   331,   340,
++     341
    };
  
    // Print the state stack on the debug stream.
  
  #line 13 "parser.yy" // lalr1.cc:1167
  } } // isc::eval
- #line 1404 "parser.cc" // lalr1.cc:1167
- #line 301 "parser.yy" // lalr1.cc:1168
 -#line 1322 "parser.cc" // lalr1.cc:1167
 -#line 268 "parser.yy" // lalr1.cc:1168
++#line 1498 "parser.cc" // lalr1.cc:1167
++#line 344 "parser.yy" // lalr1.cc:1168
  
  void
  isc::eval::EvalParser::error(const location_type& loc,
index 7727cffa8bcb1d30a80866196e89dd7e5174c8dd,9728780db3d72254401f51849b92036e8428b464..2cb61b5e4f5da7f50262f506b85fea9632c314be
@@@ -298,24 -298,18 +298,27 @@@ namespace isc { namespace eval 
        // option_repr_type
        char dummy1[sizeof(TokenOption::RepresentationType)];
  
-       char dummy2[sizeof(TokenPkt6::FieldType)];
+       // pkt4_field
+       char dummy2[sizeof(TokenPkt4::FieldType)];
 +      // pkt6_field
-       char dummy3[sizeof(TokenRelay6Field::FieldType)];
++      char dummy3[sizeof(TokenPkt6::FieldType)];
 +
 +      // relay6_field
++      char dummy4[sizeof(TokenRelay6Field::FieldType)];
 +
        // "constant string"
        // "integer"
        // "constant hexstring"
        // "option name"
        // "ip address"
-       char dummy4[sizeof(std::string)];
 -      char dummy3[sizeof(std::string)];
++      char dummy5[sizeof(std::string)];
  
        // option_code
-       char dummy5[sizeof(uint16_t)];
 -      char dummy4[sizeof(uint16_t)];
++      char dummy6[sizeof(uint16_t)];
 +
 +      // nest_level
-       char dummy6[sizeof(uint8_t)];
++      char dummy7[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_PKT4 = 272,
 -        TOKEN_CHADDR = 273,
 -        TOKEN_HLEN = 274,
 -        TOKEN_HTYPE = 275,
 -        TOKEN_CIADDR = 276,
 -        TOKEN_GIADDR = 277,
 -        TOKEN_YIADDR = 278,
 -        TOKEN_SIADDR = 279,
 -        TOKEN_SUBSTRING = 280,
 -        TOKEN_ALL = 281,
 -        TOKEN_COMA = 282,
 -        TOKEN_CONCAT = 283,
 -        TOKEN_STRING = 284,
 -        TOKEN_INTEGER = 285,
 -        TOKEN_HEXSTRING = 286,
 -        TOKEN_OPTION_NAME = 287,
 -        TOKEN_IP_ADDRESS = 288
 +        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_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
++        TOKEN_PKT4 = 275,
++        TOKEN_CHADDR = 276,
++        TOKEN_HLEN = 277,
++        TOKEN_HTYPE = 278,
++        TOKEN_CIADDR = 279,
++        TOKEN_GIADDR = 280,
++        TOKEN_YIADDR = 281,
++        TOKEN_SIADDR = 282,
++        TOKEN_SUBSTRING = 283,
++        TOKEN_ALL = 284,
++        TOKEN_COMA = 285,
++        TOKEN_CONCAT = 286,
++        TOKEN_PKT6 = 287,
++        TOKEN_MSGTYPE = 288,
++        TOKEN_TRANSID = 289,
++        TOKEN_STRING = 290,
++        TOKEN_INTEGER = 291,
++        TOKEN_HEXSTRING = 292,
++        TOKEN_OPTION_NAME = 293,
++        TOKEN_IP_ADDRESS = 294
        };
      };
  
  
    basic_symbol (typename Base::kind_type t, const TokenOption::RepresentationType v, const location_type& l);
  
+   basic_symbol (typename Base::kind_type t, const TokenPkt4::FieldType 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);
    // number is the opposite.  If YYTABLE_NINF, syntax error.
    static const unsigned char yytable_[];
  
--  static const unsigned char yycheck_[];
++  static const signed char yycheck_[];
  
    // YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    // symbol of state STATE-NUM.
      enum
      {
        yyeof_ = 0,
-       yylast_ = 102,     ///< Last index in yytable_.
-       yynnts_ = 11,  ///< Number of nonterminal symbols.
-       yyfinal_ = 23, ///< Termination state number.
 -      yylast_ = 78,     ///< Last index in yytable_.
 -      yynnts_ = 9,  ///< Number of nonterminal symbols.
 -      yyfinal_ = 21, ///< Termination state number.
++      yylast_ = 113,     ///< Last index in yytable_.
++      yynnts_ = 12,  ///< Number of nonterminal symbols.
++      yyfinal_ = 25, ///< Termination state number.
        yyterror_ = 1,
        yyerrcode_ = 256,
-       yyntokens_ = 32  ///< Number of tokens.
 -      yyntokens_ = 34  ///< Number of tokens.
++      yyntokens_ = 40  ///< 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,    29,    30,    31
 -      25,    26,    27,    28,    29,    30,    31,    32,    33
++      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
++      35,    36,    37,    38,    39
      };
-     const unsigned int user_token_number_max_ = 286;
 -    const unsigned int user_token_number_max_ = 288;
++    const unsigned int user_token_number_max_ = 294;
      const token_number_type undef_token_ = 2;
  
      if (static_cast<int>(t) <= yyeof_)
    {
        switch (other.type_get ())
      {
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          value.copy< TokenOption::RepresentationType > (other.value);
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         value.copy< TokenPkt4::FieldType > (other.value);
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        value.copy< TokenPkt6::FieldType > (other.value);
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        value.copy< TokenRelay6Field::FieldType > (other.value);
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          value.copy< std::string > (other.value);
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          value.copy< uint16_t > (other.value);
          break;
  
-       case 41: // nest_level
++      case 50: // nest_level
 +        value.copy< uint8_t > (other.value);
 +        break;
 +
        default:
          break;
      }
      (void) v;
        switch (this->type_get ())
      {
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          value.copy< TokenOption::RepresentationType > (v);
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         value.copy< TokenPkt4::FieldType > (v);
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        value.copy< TokenPkt6::FieldType > (v);
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        value.copy< TokenRelay6Field::FieldType > (v);
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          value.copy< std::string > (v);
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          value.copy< uint16_t > (v);
          break;
  
-       case 41: // nest_level
++      case 50: // 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 TokenPkt4::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 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 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          value.template destroy< TokenOption::RepresentationType > ();
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         value.template destroy< TokenPkt4::FieldType > ();
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        value.template destroy< TokenPkt6::FieldType > ();
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        value.template destroy< TokenRelay6Field::FieldType > ();
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          value.template destroy< std::string > ();
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          value.template destroy< uint16_t > ();
          break;
  
-       case 41: // nest_level
++      case 50: // nest_level
 +        value.template destroy< uint8_t > ();
 +        break;
 +
        default:
          break;
      }
      super_type::move(s);
        switch (this->type_get ())
      {
-       case 37: // option_repr_type
 -      case 39: // option_repr_type
++      case 45: // option_repr_type
          value.move< TokenOption::RepresentationType > (s.value);
          break;
  
-       case 42: // pkt6_field
 -      case 40: // pkt4_field
++      case 46: // pkt4_field
+         value.move< TokenPkt4::FieldType > (s.value);
+         break;
 -      case 29: // "constant string"
 -      case 30: // "integer"
 -      case 31: // "constant hexstring"
 -      case 32: // "option name"
 -      case 33: // "ip address"
++      case 51: // pkt6_field
 +        value.move< TokenPkt6::FieldType > (s.value);
 +        break;
 +
-       case 40: // relay6_field
++      case 49: // relay6_field
 +        value.move< TokenRelay6Field::FieldType > (s.value);
 +        break;
 +
-       case 27: // "constant string"
-       case 28: // "integer"
-       case 29: // "constant hexstring"
-       case 30: // "option name"
-       case 31: // "ip address"
++      case 35: // "constant string"
++      case 36: // "integer"
++      case 37: // "constant hexstring"
++      case 38: // "option name"
++      case 39: // "ip address"
          value.move< std::string > (s.value);
          break;
  
-       case 36: // option_code
 -      case 38: // option_code
++      case 44: // option_code
          value.move< uint16_t > (s.value);
          break;
  
-       case 41: // nest_level
++      case 50: // 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,   284,
-      285,   286
 -     285,   286,   287,   288
++     285,   286,   287,   288,   289,   290,   291,   292,   293,   294
      };
      return static_cast<token_type> (yytoken_number_[type]);
    }
    }
  
  
- #line 13 "parser.yy" // lalr1.cc:377
+ #line 13 "parser.yy" // lalr1.cc:392
  } } // isc::eval
- #line 1379 "parser.h" // lalr1.cc:377
 -#line 1345 "parser.h" // lalr1.cc:392
++#line 1496 "parser.h" // lalr1.cc:392
  
  
  
index 1fd28a66f3d267b58bbc7ef6550a673e7c2a690a,83ab9f148bfeb1b12f27358b11145ad00306ac1c..52e69c0668ea867256a9e15a72098e0442cadafa
@@@ -71,9 -73,7 +79,10 @@@ 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 <TokenPkt4::FieldType> pkt4_field
 +%type <TokenPkt6::FieldType> pkt6_field
  
  %left OR
  %left AND
@@@ -193,38 -179,11 +202,47 @@@ string_expr : STRIN
                           error(@1, "relay4 can only be used in DHCPv4.");
                       }
                    }
 +
 +            | RELAY6 "[" nest_level "]" "." OPTION "[" option_code "]" "." option_repr_type
 +                  {
 +                     switch (ctx.getUniverse()) {
 +                     case Option::V6:
 +                     {
 +                         TokenPtr opt(new TokenRelay6Option($3, $8, $11));
 +                         ctx.expression.push_back(opt);
 +                         break;
 +                     }
 +                     case Option::V4:
 +                         // For now we only use relay6 in DHCPv6.
 +                         error(@1, "relay6 can only be used in DHCPv6.");
 +                     }
 +                  }
 +
 +            | RELAY6 "[" nest_level "]" "." relay6_field
 +                  {
 +                     switch (ctx.getUniverse()) {
 +                     case Option::V6:
 +                     {
 +                         TokenPtr relay6field(new TokenRelay6Field($3, $6));
 +                         ctx.expression.push_back(relay6field);
 +                         break;
 +                     }
 +                     case Option::V4:
 +                         // For now we only use relay6 in DHCPv6.
 +                         error(@1, "relay6 can only be used in DHCPv6.");
 +                     }
 +                  }
 +
 -                      TokenPtr pkt4field(new TokenPkt4($3));
 -                      ctx.expression.push_back(pkt4field);
+             | PKT4 "." pkt4_field
+                   {
++                      TokenPtr pkt4_field(new TokenPkt4($3));
++                      ctx.expression.push_back(pkt4_field);
++                  }
++            | PKT6 "." pkt6_field
++                  {
++                      TokenPtr pkt6_field(new TokenPkt6($3));
++                      ctx.expression.push_back(pkt6_field);
+                   }
              | SUBSTRING "(" string_expr "," start_expr "," length_expr ")"
                    {
                        TokenPtr sub(new TokenSubstring());
index eab31f9ac0f430a0deb5813bfcbe4d24c6bacb44,7e4ef26f2cc3e46c5559f88de5d3570b375a4a47..9d757d6690d6dc2120fc00de2385ffa79cd71f62
@@@ -585,16 -475,41 +630,51 @@@ TEST_F(EvalContextTest, relay4Error) 
                 "<string>:1.1-6: relay4 can only be used in DHCPv4.");
  }
  
+ // Tests whether chaddr field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldChaddr) {
+     testPkt4Field("pkt4.mac == 0x000102030405", TokenPkt4::CHADDR, 3);
+ }
+ // Tests whether hlen field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldHlen) {
+     testPkt4Field("pkt4.hlen == 0x6", TokenPkt4::HLEN, 3);
+ }
+ // Tests whether htype field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldHtype) {
+     testPkt4Field("pkt4.htype == 0x1", TokenPkt4::HTYPE, 3);
+ }
+ // Tests whether ciaddr field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldCiaddr) {
+     testPkt4Field("pkt4.ciaddr == 192.0.2.1", TokenPkt4::CIADDR, 3);
+ }
+ // Tests whether giaddr field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldGiaddr) {
+     testPkt4Field("pkt4.giaddr == 192.0.2.1", TokenPkt4::GIADDR, 3);
+ }
+ // Tests whether yiaddr field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldYiaddr) {
+     testPkt4Field("pkt4.yiaddr == 192.0.2.1", TokenPkt4::YIADDR, 3);
+ }
+ // Tests whether siaddr field in DHCPv4 can be accessed.
+ TEST_F(EvalContextTest, pkt4FieldSiaddr) {
+     testPkt4Field("pkt4.siaddr == 192.0.2.1", TokenPkt4::SIADDR, 3);
+ }
 +// Tests whether message type field in DHCPv6 can be accessed.
 +TEST_F(EvalContextTest, pkt6FieldMsgtype) {
 +    testPkt6Field("pkt6.msgtype == '1'", TokenPkt6::MSGTYPE, 3);
 +}
 +
 +// Tests whether transaction id field in DHCPv6 can be accessed.
 +TEST_F(EvalContextTest, pkt6FieldTransid) {
 +    testPkt6Field("pkt6.transid == '1'", TokenPkt6::TRANSID, 3);
 +}
 +
  // Test parsing of logical operators
  TEST_F(EvalContextTest, logicalOps) {
      // option.exists
Simple merge
index 30b4dbc7a8af270b59d091ac22be6d8cae75fdc4,7745a3da06b6a5419f59a886c66957173c99e889..7fbe6f2d223652cc088fd573bba24e58394c7ce5
@@@ -8,8 -8,8 +8,9 @@@
  #include <eval/eval_log.h>
  #include <util/encode/hex.h>
  #include <asiolink/io_address.h>
+ #include <dhcp/pkt4.h>
  #include <boost/lexical_cast.hpp>
 +#include <dhcp/pkt6.h>
  #include <cstring>
  #include <string>
  
Simple merge