Browse Source

Merge branch 'trac4269' Merge 4269 after updates to fix conflicts

Shawn Routhier 9 years ago
parent
commit
48be5f5cea

+ 7 - 2
ChangeLog

@@ -1,3 +1,8 @@
+1106.	[func]		sar
+	Added support for accessing DHCPv6 packet fields message type
+	and transaction id in a classification expression.
+	(Trac #4269, git <tbd>)
+
 1105.	[bug]		pallotron
 	perfdhcp uses the same transaction id throughout the DORA
 	exchange to adhere with RFC 2131.
@@ -5,7 +10,7 @@
 
 1104.	[func]		tmark
 	The DDNS parameter, replace-client-name, has been changed from a boolean
-	to list of modes, which provides greater flexibility in when the Kea 
+	to list of modes, which provides greater flexibility in when the Kea
 	servers replace or supply DNS names for clients.  This is supported both
 	kea-dhcp4 and kea-dhcp6.
 	(Trac #4529, git 45e56d7aa0d4a6224a1a28941f6cb11575391222)
@@ -19,7 +24,7 @@
 1102.	[func]		sar
 	Added access to the peer address, link address and option
 	information added by relays in a DHCPv6 message.
-	(Trac $4269, git bb00d9d205ee047961ba70417d7ce02c37d80ce7)
+	(Trac $4265, git bb00d9d205ee047961ba70417d7ce02c37d80ce7)
 
 1101.	[bug]		stephen
 	Made DHCPSRV_MEMFILE_LFC_UNREGISTER_TIMER_FAILED a debug message as the

+ 22 - 0
doc/guide/classify.xml

@@ -188,6 +188,20 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
 <!-- <entry>2001:DB8::1</entry> -->n
   <entry>The value of the link address field from the relay encapsulation "nest"</entry>
 </row>
+<row>
+  <entry>Message Type in DHCPv6 packet</entry>
+  <entry>pkt6.msgtype</entry>
+<!--  <entry>1</entry>
+-->
+  <entry>The value of the message type field in the DHCPv6 packet.</entry>
+</row>
+<row>
+  <entry>Transaction ID in DHCPv6 packet</entry>
+  <entry>pkt6.transid</entry>
+<!--  <entry>12345</entry>
+-->
+  <entry>The value of the transaction id in the DHCPv6 packet.</entry>
+</row>
           </tbody>
           </tgroup>
         </table>
@@ -248,6 +262,14 @@ sub-option with code "code" from the DHCPv4 Relay Agent Information option
       </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>
           <tgroup cols='3'>

+ 158 - 132
src/lib/eval/lexer.cc

@@ -483,8 +483,8 @@ static void yy_fatal_error (yyconst char msg[]  );
 	(yy_c_buf_p) = yy_cp;
 
 /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 30
-#define YY_END_OF_BUFFER 31
+#define YY_NUM_RULES 33
+#define YY_END_OF_BUFFER 34
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -492,43 +492,46 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_acclist[162] =
+static yyconst flex_int16_t yy_acclist[183] =
     {   0,
-       31,   29,   30,    1,   29,   30,    2,   30,   29,   30,
-       24,   29,   30,   25,   29,   30,   28,   29,   30,   29,
-       30,   23,   29,   30,    5,   29,   30,    5,   29,   30,
-       29,   30,   29,   30,   29,   30,16390,   29,   30,16390,
-       26,   29,   30,   27,   29,   30,   29,   30,16390,   29,
-       30,16390,   29,   30,16390,   29,   30,16390,   29,   30,
-    16390,   29,   30,16390,   29,   30,16390,   29,   30,16390,
-       29,   30,16390,   29,   30,16390,   29,   30,16390,    1,
-        2,    3,    5,    5,    7,    8,16390,16390, 8198,16390,
-    16390,16390,16390,16390,16390,16390,16390,   22,16390,16390,
-
-    16390,16390,16390,    4,    7,   18,16390,   21,16390,16390,
-    16390,   15,16390,16390,   20,16390,16390,16390,16390,16390,
-    16390,16390,16390,16390,16390,16390,16390,16390,   14,16390,
-    16390,16390,16390,16390,16390,16390,16390,   19,16390,   16,
-    16390,16390,    9,16390,16390,   10,16390,   11,16390,16390,
-        7,16390,16390,16390,   13,16390,   12,16390,16390,   17,
-    16390
+       34,   32,   33,    1,   32,   33,    2,   33,   32,   33,
+       24,   32,   33,   25,   32,   33,   28,   32,   33,   32,
+       33,   23,   32,   33,    5,   32,   33,    5,   32,   33,
+       32,   33,   32,   33,   32,   33,16390,   32,   33,16390,
+       26,   32,   33,   27,   32,   33,   32,   33,16390,   32,
+       33,16390,   32,   33,16390,   32,   33,16390,   32,   33,
+    16390,   32,   33,16390,   32,   33,16390,   32,   33,16390,
+       32,   33,16390,   32,   33,16390,   32,   33,16390,   32,
+       33,16390,    1,    2,    3,    5,    5,    7,    8,16390,
+    16390, 8198,16390,16390,16390,16390,16390,16390,16390,16390,
+
+    16390,   22,16390,16390,16390,16390,16390,16390,16390,    4,
+        7,   18,16390,   21,16390,16390,16390,   15,16390,16390,
+    16390,   20,16390,16390,16390,16390,16390,16390,16390,16390,
+    16390,16390,16390,16390,16390,16390,   29,16390,16390,16390,
+       14,16390,16390,16390,16390,16390,16390,16390,16390,16390,
+    16390,16390,   19,16390,   16,16390,16390,16390,    9,16390,
+    16390,   10,16390,   11,16390,16390,16390,    7,16390,   30,
+    16390,16390,16390,   31,16390,   13,16390,   12,16390,16390,
+       17,16390
     } ;
 
-static yyconst flex_int16_t yy_accept[114] =
+static yyconst flex_int16_t yy_accept[130] =
     {   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,   81,   82,   82,   83,   84,   84,   85,   85,
-       85,   85,   85,   86,   87,   87,   87,   88,   89,   90,
-       91,   92,   93,   94,   95,   96,   97,   98,  100,  101,
-      102,  103,  104,  104,  105,  106,  108,  110,  111,  112,
-      114,  115,  117,  118,  119,  120,  121,  122,  122,  123,
-      124,  125,  126,  127,  128,  129,  131,  131,  132,  133,
-      134,  135,  136,  137,  138,  138,  140,  142,  143,  145,
-
-      146,  148,  150,  151,  152,  153,  154,  155,  157,  159,
-      160,  162,  162
+       77,   80,   83,   84,   85,   85,   86,   87,   87,   88,
+       88,   88,   88,   88,   89,   90,   90,   90,   91,   92,
+       93,   94,   95,   96,   97,   98,   99,  100,  101,  102,
+      104,  105,  106,  107,  108,  109,  110,  110,  111,  112,
+      114,  116,  117,  118,  120,  121,  122,  124,  125,  126,
+      127,  128,  129,  130,  131,  131,  132,  133,  134,  135,
+      136,  137,  139,  140,  141,  143,  144,  144,  145,  146,
+
+      147,  148,  149,  150,  151,  152,  153,  153,  155,  157,
+      158,  159,  161,  162,  164,  166,  167,  168,  169,  170,
+      172,  173,  174,  176,  178,  180,  181,  183,  183
     } ;
 
 static yyconst YY_CHAR yy_ec[256] =
@@ -544,9 +547,9 @@ static yyconst YY_CHAR yy_ec[256] =
        17,   17,   17,   17,   17,   17,   17,   18,   17,   17,
        19,    1,   20,    1,   21,    1,   22,   23,   24,   25,
 
-       26,   16,   27,   28,   29,   17,   30,   31,   17,   32,
-       33,   34,   17,   35,   36,   37,   38,   17,   17,   39,
-       40,   17,    1,    1,    1,    1,    1,    1,    1,    1,
+       26,   16,   27,   28,   29,   17,   30,   31,   32,   33,
+       34,   35,   17,   36,   37,   38,   39,   17,   17,   40,
+       41,   17,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -563,128 +566,136 @@ static yyconst YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst YY_CHAR yy_meta[41] =
+static yyconst YY_CHAR yy_meta[42] =
     {   0,
         1,    1,    2,    1,    1,    1,    1,    1,    3,    4,
         4,    4,    4,    5,    1,    4,    1,    1,    1,    1,
         1,    4,    4,    4,    4,    4,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1
     } ;
 
-static yyconst flex_uint16_t yy_base[118] =
+static yyconst flex_uint16_t yy_base[134] =
     {   0,
-        0,    0,  220,  221,  217,  215,  213,  221,  221,  221,
-       31,  221,   36,   33,  202,  200,   74,  105,  221,  221,
-       24,  181,  174,  186,  182,  177,   29,  183,  182,  169,
-      180,  203,  201,  199,  221,   55,   68,   35,  188,  187,
-        0,  186,    0,  221,  120,  122,    0,    0,  221,  168,
-      173,  165,  167,  156,  162,  156,  155,    0,  165,  159,
-      166,  149,  123,    0,    0,    0,    0,  163,  150,    0,
-      155,    0,  155,  148,  160,  145,  143,  133,  157,  141,
-      155,  143,  153,  134,  136,    0,  138,  135,  125,  116,
-      107,  113,   57,  102,  142,    0,    0,  101,    0,   95,
-
-        0,    0,   64,  146,   54,   48,   41,    0,    0,   44,
-        0,  221,  159,  161,  163,   53,  166
+        0,    0,  237,  238,  234,  232,  230,  238,  238,  238,
+       32,  238,   37,   34,  219,  217,   76,  108,  238,  238,
+       23,  197,  190,  203,  199,  190,  192,   22,   38,  199,
+      185,   39,  221,  219,  217,  238,   59,   70,   55,  206,
+      205,    0,  204,    0,  238,  123,  125,    0,    0,  238,
+      186,  191,  182,  185,  173,  179,  184,  172,  171,    0,
+      182,  169,  175,  182,  164,  181,  126,    0,    0,    0,
+        0,  178,  164,    0,  170,  161,    0,  169,  161,  183,
+      173,  157,  155,  159,  136,  169,  152,  167,  147,  153,
+      164,    0,  144,  146,    0,  146,  141,  144,  144,  155,
+
+      144,  145,  152,   54,  140,  146,  145,    0,    0,  139,
+      118,    0,  117,    0,    0,  112,  115,  149,   93,    0,
+       87,   58,    0,    0,    0,   58,    0,  238,  162,  164,
+      166,   72,  169
     } ;
 
-static yyconst flex_int16_t yy_def[118] =
+static yyconst flex_int16_t yy_def[134] =
     {   0,
-      112,    1,  112,  112,  112,  112,  113,  112,  112,  112,
-      112,  112,  112,   13,  114,  112,  112,   17,  112,  112,
+      128,    1,  128,  128,  128,  128,  129,  128,  128,  128,
+      128,  128,  128,   13,  130,  128,  128,   17,  128,  128,
        17,   17,   17,   18,   18,   18,   18,   18,   18,   18,
-       18,  112,  112,  113,  112,  112,  112,   13,  114,  115,
-      116,  114,  117,  112,  112,   18,   17,   18,  112,   18,
+       18,   18,  128,  128,  129,  128,  128,  128,   13,  130,
+      131,  132,  130,  133,  128,  128,   18,   17,   18,  128,
+       18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,  128,  132,  133,   18,
        18,   18,   18,   18,   18,   18,   18,   18,   18,   18,
-       18,   18,  112,  116,  117,   18,   18,   18,   18,   18,
-       18,   18,   18,   18,   18,   18,   18,  112,   18,   18,
-       18,   18,   18,   18,   18,   18,  112,   18,   18,   18,
-       18,   18,   18,   18,  112,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,  128,   18,   18,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,  128,   18,   18,   18,
 
-       18,   18,   18,  112,   18,   18,   18,   18,   18,   18,
-       18,    0,  112,  112,  112,  112,  112
+       18,   18,   18,   18,   18,   18,  128,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,  128,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,    0,  128,  128,
+      128,  128,  128
     } ;
 
-static yyconst flex_uint16_t yy_nxt[262] =
+static yyconst flex_uint16_t yy_nxt[280] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
        14,   14,   14,   15,   16,   17,   18,   18,   19,   20,
         4,   21,   17,   22,   17,   23,   18,   24,   18,   18,
-       25,   26,   27,   28,   29,   30,   31,   18,   18,   18,
-       36,   36,   36,   36,   37,   38,   38,   38,   38,   39,
-      112,   40,  112,   41,   50,   51,   64,   40,   40,   40,
-       40,   40,   57,   58,   36,   36,   36,   36,  101,  102,
-      111,  112,  110,  112,   41,   45,   45,   63,   63,   63,
-       63,   46,  109,   47,   47,   47,   47,   39,  108,   47,
-       48,   48,  107,   49,   46,   47,   47,   47,   47,   47,
-
-       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
-       48,   48,   48,   48,   48,   48,   48,   48,  112,  106,
-       48,   45,   45,  112,  112,  105,   48,   48,   48,   48,
-       48,   78,   63,   63,   63,   63,  103,  100,   99,   49,
-       98,  112,   87,   87,   87,   87,   95,   87,   87,   87,
-       87,  104,  104,  104,  104,  104,  104,  104,  104,   34,
-       97,   34,   34,   34,   42,   42,   40,   40,   65,   65,
-       65,   96,   94,   93,   92,   91,   90,   89,   88,   86,
-       85,   84,   83,   82,   81,   80,   79,   77,   76,   75,
-       74,   73,   72,   71,   70,   69,   68,   67,   66,   43,
-
-       39,   43,   35,   33,   32,   62,   61,   60,   59,   56,
-       55,   54,   53,   52,   44,   43,   35,   33,   32,  112,
-        3,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112
+       25,   26,   27,   28,   29,   30,   31,   32,   18,   18,
+       18,   37,   37,   37,   37,   38,   39,   39,   39,   39,
+       40,  128,   41,   51,   42,   52,   59,   60,   41,   41,
+       41,   41,   41,   61,   65,  114,  115,   62,   37,   37,
+       37,   37,  128,  128,   66,   68,   42,   46,   46,   67,
+       67,   67,   67,   47,  127,   48,   48,   48,   48,   40,
+      126,   48,   49,   49,  128,   50,   47,   48,   48,   48,
+
+       48,   48,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,  128,  125,   49,   46,   46,  128,  128,  124,   49,
+       49,   49,   49,   49,   85,   67,   67,   67,   67,  123,
+      122,  121,   50,  120,  128,   97,   97,   97,   97,  107,
+       97,   97,   97,   97,  118,  118,  118,  118,  118,  118,
+      118,  118,   35,  119,   35,   35,   35,   43,   43,   41,
+       41,   69,   69,   69,  117,  116,  113,  112,  111,  110,
+      109,  108,  106,  105,  104,  103,  102,  101,  100,   99,
+       98,   96,   95,   94,   93,   92,   91,   90,   89,   88,
+
+       87,   86,   84,   83,   82,   81,   80,   79,   78,   77,
+       76,   75,   74,   73,   72,   71,   70,   44,   40,   44,
+       36,   34,   33,   64,   63,   58,   57,   56,   55,   54,
+       53,   45,   44,   36,   34,   33,  128,    3,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128
     } ;
 
-static yyconst flex_int16_t yy_chk[262] =
+static yyconst flex_int16_t yy_chk[280] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-       11,   11,   11,   11,   13,   13,   13,   13,   13,   13,
-       14,   13,   38,   13,   21,   21,  116,   13,   13,   13,
-       13,   13,   27,   27,   36,   36,   36,   36,   93,   93,
-      110,   14,  107,   38,   13,   17,   17,   37,   37,   37,
-       37,   17,  106,   17,   17,   17,   17,   17,  105,   17,
-       17,   17,  103,   17,   17,   17,   17,   17,   17,   17,
+        1,   11,   11,   11,   11,   13,   13,   13,   13,   13,
+       13,   14,   13,   21,   13,   21,   28,   28,   13,   13,
+       13,   13,   13,   29,   32,  104,  104,   29,   37,   37,
+       37,   37,   39,   14,   32,  132,   13,   17,   17,   38,
+       38,   38,   38,   17,  126,   17,   17,   17,   17,   17,
+      122,   17,   17,   17,   39,   17,   17,   17,   17,   17,
 
        17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
-       17,   17,   17,   17,   18,   18,   18,   18,   18,  100,
-       18,   45,   45,   46,   46,   98,   18,   18,   18,   18,
-       18,   63,   63,   63,   63,   63,   94,   92,   91,   45,
-       90,   46,   78,   78,   78,   78,   87,   87,   87,   87,
-       87,   95,   95,   95,   95,  104,  104,  104,  104,  113,
-       89,  113,  113,  113,  114,  114,  115,  115,  117,  117,
-      117,   88,   85,   84,   83,   82,   81,   80,   79,   77,
-       76,   75,   74,   73,   71,   69,   68,   62,   61,   60,
-       59,   57,   56,   55,   54,   53,   52,   51,   50,   42,
-
-       40,   39,   34,   33,   32,   31,   30,   29,   28,   26,
-       25,   24,   23,   22,   16,   15,    7,    6,    5,    3,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112,  112,  112,  112,  112,  112,  112,  112,  112,  112,
-      112
+       17,   17,   17,   17,   17,   17,   17,   18,   18,   18,
+       18,   18,  121,   18,   46,   46,   47,   47,  119,   18,
+       18,   18,   18,   18,   67,   67,   67,   67,   67,  117,
+      116,  113,   46,  111,   47,   85,   85,   85,   85,   97,
+       97,   97,   97,   97,  107,  107,  107,  107,  118,  118,
+      118,  118,  129,  110,  129,  129,  129,  130,  130,  131,
+      131,  133,  133,  133,  106,  105,  103,  102,  101,  100,
+       99,   98,   96,   94,   93,   91,   90,   89,   88,   87,
+       86,   84,   83,   82,   81,   80,   79,   78,   76,   75,
+
+       73,   72,   66,   65,   64,   63,   62,   61,   59,   58,
+       57,   56,   55,   54,   53,   52,   51,   43,   41,   40,
+       35,   34,   33,   31,   30,   27,   26,   25,   24,   23,
+       22,   16,   15,    7,    6,    5,    3,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128,  128,
+      128,  128,  128,  128,  128,  128,  128,  128,  128
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[31] =
+static yyconst flex_int32_t yy_rule_can_match_eol[34] =
     {   0,
 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     };
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     };
 
 extern int yy_flex_debug;
 int yy_flex_debug = 1;
 
-static yyconst flex_int16_t yy_rule_linenum[30] =
+static yyconst flex_int16_t yy_rule_linenum[33] =
     {   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
+      156,  157,  158,  159,  160,  161,  162,  163,  165,  166,
+      167,  169
     } ;
 
 static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@ -763,7 +774,7 @@ static isc::eval::location loc;
 // by moving it ahead by yyleng bytes. yyleng specifies the length of the
 // currently matched token.
 #define YY_USER_ACTION  loc.columns(yyleng);
-#line 767 "lexer.cc"
+#line 778 "lexer.cc"
 
 #define INITIAL 0
 
@@ -1060,7 +1071,7 @@ YY_DECL
     loc.step();
 
 
-#line 1064 "lexer.cc"
+#line 1075 "lexer.cc"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1088,14 +1099,14 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 113 )
+				if ( yy_current_state >= 129 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			*(yy_state_ptr)++ = yy_current_state;
 			++yy_cp;
 			}
-		while ( yy_current_state != 112 );
+		while ( yy_current_state != 128 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1158,13 +1169,13 @@ do_action:	/* This label is used only to access EOF actions. */
 			{
 			if ( yy_act == 0 )
 				fprintf( stderr, "--scanner backing up\n" );
-			else if ( yy_act < 30 )
+			else if ( yy_act < 33 )
 				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
 				         (long)yy_rule_linenum[yy_act], yytext );
-			else if ( yy_act == 30 )
+			else if ( yy_act == 33 )
 				fprintf( stderr, "--accepting default rule (\"%s\")\n",
 				         yytext );
-			else if ( yy_act == 31 )
+			else if ( yy_act == 34 )
 				fprintf( stderr, "--(end of buffer or a NUL)\n" );
 			else
 				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1366,18 +1377,33 @@ return isc::eval::EvalParser::make_COMA(loc);
 case 29:
 YY_RULE_SETUP
 #line 165 "lexer.ll"
+return isc::eval::EvalParser::make_PKT6(loc);
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 166 "lexer.ll"
+return isc::eval::EvalParser::make_MSGTYPE(loc);
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 167 "lexer.ll"
+return isc::eval::EvalParser::make_TRANSID(loc);
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 169 "lexer.ll"
 driver.error (loc, "Invalid character: " + std::string(yytext));
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 166 "lexer.ll"
+#line 170 "lexer.ll"
 return isc::eval::EvalParser::make_END(loc);
 	YY_BREAK
-case 30:
+case 33:
 YY_RULE_SETUP
-#line 167 "lexer.ll"
+#line 171 "lexer.ll"
 ECHO;
 	YY_BREAK
-#line 1381 "lexer.cc"
+#line 1407 "lexer.cc"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1662,7 +1688,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 113 )
+			if ( yy_current_state >= 129 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1690,11 +1716,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 113 )
+		if ( yy_current_state >= 129 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 112);
+	yy_is_jam = (yy_current_state == 128);
 	if ( ! yy_is_jam )
 		*(yy_state_ptr)++ = yy_current_state;
 
@@ -2460,7 +2486,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 167 "lexer.ll"
+#line 171 "lexer.ll"
 
 
 

+ 4 - 0
src/lib/eval/lexer.ll

@@ -162,6 +162,10 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
 "]"         return isc::eval::EvalParser::make_RBRACKET(loc);
 ","         return isc::eval::EvalParser::make_COMA(loc);
 
+"pkt6"      return isc::eval::EvalParser::make_PKT6(loc);
+"msgtype"   return isc::eval::EvalParser::make_MSGTYPE(loc);
+"transid"   return isc::eval::EvalParser::make_TRANSID(loc);
+
 .          driver.error (loc, "Invalid character: " + std::string(yytext));
 <<EOF>>    return isc::eval::EvalParser::make_END(loc);
 %%

+ 231 - 181
src/lib/eval/parser.cc

@@ -251,27 +251,31 @@ namespace isc { namespace eval {
   {
       switch (that.type_get ())
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         value.move< TokenOption::RepresentationType > (that.value);
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        value.move< TokenPkt6::FieldType > (that.value);
+        break;
+
+      case 40: // relay6_field
         value.move< TokenRelay6Field::FieldType > (that.value);
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         value.move< std::string > (that.value);
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         value.move< uint16_t > (that.value);
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         value.move< uint8_t > (that.value);
         break;
 
@@ -290,27 +294,31 @@ namespace isc { namespace eval {
     state = that.state;
       switch (that.type_get ())
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         value.copy< TokenOption::RepresentationType > (that.value);
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        value.copy< TokenPkt6::FieldType > (that.value);
+        break;
+
+      case 40: // relay6_field
         value.copy< TokenRelay6Field::FieldType > (that.value);
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         value.copy< std::string > (that.value);
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         value.copy< uint16_t > (that.value);
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         value.copy< uint8_t > (that.value);
         break;
 
@@ -350,67 +358,74 @@ namespace isc { namespace eval {
         << yysym.location << ": ";
     switch (yytype)
     {
-            case 24: // "constant string"
+            case 27: // "constant string"
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 358 "parser.cc" // lalr1.cc:636
+#line 366 "parser.cc" // lalr1.cc:636
         break;
 
-      case 25: // "integer"
+      case 28: // "integer"
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 365 "parser.cc" // lalr1.cc:636
+#line 373 "parser.cc" // lalr1.cc:636
         break;
 
-      case 26: // "constant hexstring"
+      case 29: // "constant hexstring"
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 372 "parser.cc" // lalr1.cc:636
+#line 380 "parser.cc" // lalr1.cc:636
         break;
 
-      case 27: // "option name"
+      case 30: // "option name"
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 379 "parser.cc" // lalr1.cc:636
+#line 387 "parser.cc" // lalr1.cc:636
         break;
 
-      case 28: // "ip address"
+      case 31: // "ip address"
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 386 "parser.cc" // lalr1.cc:636
+#line 394 "parser.cc" // lalr1.cc:636
         break;
 
-      case 33: // option_code
+      case 36: // option_code
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< uint16_t > (); }
-#line 393 "parser.cc" // lalr1.cc:636
+#line 401 "parser.cc" // lalr1.cc:636
         break;
 
-      case 34: // option_repr_type
+      case 37: // option_repr_type
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
-#line 400 "parser.cc" // lalr1.cc:636
+#line 408 "parser.cc" // lalr1.cc:636
         break;
 
-      case 37: // relay6_field
+      case 40: // relay6_field
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< TokenRelay6Field::FieldType > (); }
-#line 407 "parser.cc" // lalr1.cc:636
+#line 415 "parser.cc" // lalr1.cc:636
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
 
-#line 78 "parser.yy" // lalr1.cc:636
+#line 82 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< uint8_t > (); }
-#line 414 "parser.cc" // lalr1.cc:636
+#line 422 "parser.cc" // lalr1.cc:636
+        break;
+
+      case 42: // pkt6_field
+
+#line 82 "parser.yy" // lalr1.cc:636
+        { yyoutput << yysym.value.template as< TokenPkt6::FieldType > (); }
+#line 429 "parser.cc" // lalr1.cc:636
         break;
 
 
@@ -610,27 +625,31 @@ namespace isc { namespace eval {
          when using variants.  */
         switch (yyr1_[yyn])
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         yylhs.value.build< TokenOption::RepresentationType > ();
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        yylhs.value.build< TokenPkt6::FieldType > ();
+        break;
+
+      case 40: // relay6_field
         yylhs.value.build< TokenRelay6Field::FieldType > ();
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         yylhs.value.build< std::string > ();
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         yylhs.value.build< uint16_t > ();
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         yylhs.value.build< uint8_t > ();
         break;
 
@@ -652,52 +671,52 @@ namespace isc { namespace eval {
           switch (yyn)
             {
   case 4:
-#line 92 "parser.yy" // lalr1.cc:859
+#line 96 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenNot());
                     ctx.expression.push_back(neg);
                 }
-#line 661 "parser.cc" // lalr1.cc:859
+#line 680 "parser.cc" // lalr1.cc:859
     break;
 
   case 5:
-#line 97 "parser.yy" // lalr1.cc:859
+#line 101 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenAnd());
                     ctx.expression.push_back(neg);
                 }
-#line 670 "parser.cc" // lalr1.cc:859
+#line 689 "parser.cc" // lalr1.cc:859
     break;
 
   case 6:
-#line 102 "parser.yy" // lalr1.cc:859
+#line 106 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenOr());
                     ctx.expression.push_back(neg);
                 }
-#line 679 "parser.cc" // lalr1.cc:859
+#line 698 "parser.cc" // lalr1.cc:859
     break;
 
   case 7:
-#line 107 "parser.yy" // lalr1.cc:859
+#line 111 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr eq(new TokenEqual());
                     ctx.expression.push_back(eq);
                 }
-#line 688 "parser.cc" // lalr1.cc:859
+#line 707 "parser.cc" // lalr1.cc:859
     break;
 
   case 8:
-#line 112 "parser.yy" // lalr1.cc:859
+#line 116 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
                     ctx.expression.push_back(opt);
                 }
-#line 697 "parser.cc" // lalr1.cc:859
+#line 716 "parser.cc" // lalr1.cc:859
     break;
 
   case 9:
-#line 117 "parser.yy" // lalr1.cc:859
+#line 121 "parser.yy" // lalr1.cc:859
     {
                    switch (ctx.getUniverse()) {
                    case Option::V4:
@@ -717,11 +736,11 @@ namespace isc { namespace eval {
                        error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                    }
                 }
-#line 721 "parser.cc" // lalr1.cc:859
+#line 740 "parser.cc" // lalr1.cc:859
     break;
 
   case 10:
-#line 137 "parser.yy" // lalr1.cc:859
+#line 141 "parser.yy" // lalr1.cc:859
     {
                     switch (ctx.getUniverse()) {
                     case Option::V6:
@@ -735,47 +754,47 @@ namespace isc { namespace eval {
                         error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
                     }
                 }
-#line 739 "parser.cc" // lalr1.cc:859
+#line 758 "parser.cc" // lalr1.cc:859
     break;
 
   case 11:
-#line 153 "parser.yy" // lalr1.cc:859
+#line 157 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 748 "parser.cc" // lalr1.cc:859
+#line 767 "parser.cc" // lalr1.cc:859
     break;
 
   case 12:
-#line 158 "parser.yy" // lalr1.cc:859
+#line 162 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(hex);
                   }
-#line 757 "parser.cc" // lalr1.cc:859
+#line 776 "parser.cc" // lalr1.cc:859
     break;
 
   case 13:
-#line 163 "parser.yy" // lalr1.cc:859
+#line 167 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(ip);
                   }
-#line 766 "parser.cc" // lalr1.cc:859
+#line 785 "parser.cc" // lalr1.cc:859
     break;
 
   case 14:
-#line 168 "parser.yy" // lalr1.cc:859
+#line 172 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), yystack_[0].value.as< TokenOption::RepresentationType > ()));
                       ctx.expression.push_back(opt);
                   }
-#line 775 "parser.cc" // lalr1.cc:859
+#line 794 "parser.cc" // lalr1.cc:859
     break;
 
   case 15:
-#line 173 "parser.yy" // lalr1.cc:859
+#line 177 "parser.yy" // lalr1.cc:859
     {
                      switch (ctx.getUniverse()) {
                      case Option::V4:
@@ -795,11 +814,11 @@ namespace isc { namespace eval {
                          error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                      }
                   }
-#line 799 "parser.cc" // lalr1.cc:859
+#line 818 "parser.cc" // lalr1.cc:859
     break;
 
   case 16:
-#line 194 "parser.yy" // lalr1.cc:859
+#line 198 "parser.yy" // lalr1.cc:859
     {
                      switch (ctx.getUniverse()) {
                      case Option::V6:
@@ -813,11 +832,11 @@ namespace isc { namespace eval {
                          error(yystack_[10].location, "relay6 can only be used in DHCPv6.");
                      }
                   }
-#line 817 "parser.cc" // lalr1.cc:859
+#line 836 "parser.cc" // lalr1.cc:859
     break;
 
   case 17:
-#line 209 "parser.yy" // lalr1.cc:859
+#line 213 "parser.yy" // lalr1.cc:859
     {
                      switch (ctx.getUniverse()) {
                      case Option::V6:
@@ -831,108 +850,129 @@ namespace isc { namespace eval {
                          error(yystack_[5].location, "relay6 can only be used in DHCPv6.");
                      }
                   }
-#line 835 "parser.cc" // lalr1.cc:859
+#line 854 "parser.cc" // lalr1.cc:859
     break;
 
   case 18:
-#line 225 "parser.yy" // lalr1.cc:859
+#line 229 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
                   }
-#line 844 "parser.cc" // lalr1.cc:859
+#line 863 "parser.cc" // lalr1.cc:859
     break;
 
   case 19:
-#line 230 "parser.yy" // lalr1.cc:859
+#line 234 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr conc(new TokenConcat());
                       ctx.expression.push_back(conc);
                   }
-#line 853 "parser.cc" // lalr1.cc:859
+#line 872 "parser.cc" // lalr1.cc:859
     break;
 
   case 20:
-#line 237 "parser.yy" // lalr1.cc:859
+#line 239 "parser.yy" // lalr1.cc:859
+    {
+                      TokenPtr pkt6_field(new TokenPkt6(yystack_[0].value.as< TokenPkt6::FieldType > ()));
+                      ctx.expression.push_back(pkt6_field);
+                  }
+#line 881 "parser.cc" // lalr1.cc:859
+    break;
+
+  case 21:
+#line 246 "parser.yy" // lalr1.cc:859
     {
                      yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 861 "parser.cc" // lalr1.cc:859
+#line 889 "parser.cc" // lalr1.cc:859
     break;
 
-  case 21:
-#line 241 "parser.yy" // lalr1.cc:859
+  case 22:
+#line 250 "parser.yy" // lalr1.cc:859
     {
                      yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 869 "parser.cc" // lalr1.cc:859
+#line 897 "parser.cc" // lalr1.cc:859
     break;
 
-  case 22:
-#line 247 "parser.yy" // lalr1.cc:859
+  case 23:
+#line 256 "parser.yy" // lalr1.cc:859
     {
                           yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                       }
-#line 877 "parser.cc" // lalr1.cc:859
+#line 905 "parser.cc" // lalr1.cc:859
     break;
 
-  case 23:
-#line 251 "parser.yy" // lalr1.cc:859
+  case 24:
+#line 260 "parser.yy" // lalr1.cc:859
     {
                           yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
                       }
-#line 885 "parser.cc" // lalr1.cc:859
+#line 913 "parser.cc" // lalr1.cc:859
     break;
 
-  case 24:
-#line 257 "parser.yy" // lalr1.cc:859
+  case 25:
+#line 266 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                      ctx.expression.push_back(str);
                  }
-#line 894 "parser.cc" // lalr1.cc:859
+#line 922 "parser.cc" // lalr1.cc:859
     break;
 
-  case 25:
-#line 264 "parser.yy" // lalr1.cc:859
+  case 26:
+#line 273 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 903 "parser.cc" // lalr1.cc:859
+#line 931 "parser.cc" // lalr1.cc:859
     break;
 
-  case 26:
-#line 269 "parser.yy" // lalr1.cc:859
+  case 27:
+#line 278 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString("all"));
                      ctx.expression.push_back(str);
                  }
-#line 912 "parser.cc" // lalr1.cc:859
+#line 940 "parser.cc" // lalr1.cc:859
     break;
 
-  case 27:
-#line 275 "parser.yy" // lalr1.cc:859
+  case 28:
+#line 284 "parser.yy" // lalr1.cc:859
     { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR; }
-#line 918 "parser.cc" // lalr1.cc:859
+#line 946 "parser.cc" // lalr1.cc:859
     break;
 
-  case 28:
-#line 276 "parser.yy" // lalr1.cc:859
+  case 29:
+#line 285 "parser.yy" // lalr1.cc:859
     { yylhs.value.as< TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR; }
-#line 924 "parser.cc" // lalr1.cc:859
+#line 952 "parser.cc" // lalr1.cc:859
     break;
 
-  case 29:
-#line 280 "parser.yy" // lalr1.cc:859
+  case 30:
+#line 289 "parser.yy" // lalr1.cc:859
     {
 		 yylhs.value.as< uint8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 932 "parser.cc" // lalr1.cc:859
+#line 960 "parser.cc" // lalr1.cc:859
     break;
 
+  case 31:
+#line 297 "parser.yy" // lalr1.cc:859
+    { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE; }
+#line 966 "parser.cc" // lalr1.cc:859
+    break;
 
-#line 936 "parser.cc" // lalr1.cc:859
+  case 32:
+#line 298 "parser.yy" // lalr1.cc:859
+    { yylhs.value.as< TokenPkt6::FieldType > () = TokenPkt6::TRANSID; }
+#line 972 "parser.cc" // lalr1.cc:859
+    break;
+
+
+#line 976 "parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -1187,100 +1227,108 @@ namespace isc { namespace eval {
   }
 
 
-  const signed char EvalParser::yypact_ninf_ = -47;
+  const signed char EvalParser::yypact_ninf_ = -54;
 
   const signed char EvalParser::yytable_ninf_ = -1;
 
   const signed char
   EvalParser::yypact_[] =
   {
-      11,    11,    11,    -4,    -1,     3,    21,    27,   -47,   -47,
-     -47,    49,    51,    28,    44,   -47,    -2,    -2,    19,    36,
-      36,   -47,    11,    11,    36,   -47,   -47,   -47,    46,    48,
-     -47,    57,    59,    60,    61,    43,    54,   -47,    71,   -47,
-      62,    63,    64,    -2,    -2,    19,    56,    36,    23,    35,
-      -5,    67,    68,    69,   -47,    65,    81,   -47,   -47,   -47,
-     -47,   -47,   -47,    72,   -47,   -47,   -47,    73,    74,    75,
-     -16,   -47,    -2,    53,    53,     6,   -47,   -47,    84,    77,
-      79,   -47,    78,    -2,    50,    80,   -47,   -47,    82,    53
+      29,    29,    29,   -12,    -4,     7,    21,    30,    32,   -54,
+     -54,   -54,    13,    10,    46,    16,   -54,    -3,    -3,     9,
+      52,    52,    42,   -54,    29,    29,    52,   -54,   -54,   -54,
+      40,    54,   -54,    56,    43,    59,    60,    55,    58,   -54,
+     -54,   -54,   -54,    72,   -54,    66,    68,    69,    -3,    -3,
+       9,    61,    52,    25,    28,    -1,    71,    73,    75,   -54,
+      65,    87,   -54,   -54,   -54,   -54,   -54,   -54,    78,   -54,
+     -54,   -54,    77,    79,    80,   -14,   -54,    -3,    33,    33,
+       6,   -54,   -54,    90,    82,    84,   -54,    83,    -3,    47,
+      85,   -54,   -54,    86,    33
   };
 
   const unsigned char
   EvalParser::yydefact_[] =
   {
-       0,     0,     0,     0,     0,     0,     0,     0,    11,    12,
-      13,     0,     2,     0,     0,     4,     0,     0,     0,     0,
-       0,     1,     0,     0,     0,     3,    20,    21,     0,     0,
-      29,     0,     0,     0,     0,     0,     0,     5,     6,     7,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    24,     0,     0,    22,    23,     8,
-      14,     9,    15,     0,    27,    28,    17,     0,     0,     0,
-       0,    19,     0,     0,     0,     0,    26,    25,     0,     0,
-       0,    18,     0,     0,     0,     0,    10,    16,     0,     0
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    11,
+      12,    13,     0,     2,     0,     0,     4,     0,     0,     0,
+       0,     0,     0,     1,     0,     0,     0,     3,    21,    22,
+       0,     0,    30,     0,     0,     0,     0,     0,     0,    31,
+      32,    20,     5,     6,     7,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    25,
+       0,     0,    23,    24,     8,    14,     9,    15,     0,    28,
+      29,    17,     0,     0,     0,     0,    19,     0,     0,     0,
+       0,    27,    26,     0,     0,     0,    18,     0,     0,     0,
+       0,    10,    16,     0,     0
   };
 
   const signed char
   EvalParser::yypgoto_[] =
   {
-     -47,   -47,    10,   -18,   -17,   -46,   -47,   -47,   -47,    52
+     -54,   -54,     4,   -17,   -18,   -53,   -54,   -54,   -54,    51,
+     -54
   };
 
   const signed char
   EvalParser::yydefgoto_[] =
   {
-      -1,    11,    12,    13,    28,    60,    55,    78,    66,    31
+      -1,    12,    13,    14,    30,    65,    60,    83,    71,    33,
+      41
   };
 
   const unsigned char
   EvalParser::yytable_[] =
   {
-      29,    35,    36,    62,    63,    76,    39,    64,    65,    77,
-      16,    14,    15,    17,     1,    80,     2,    18,    64,    65,
-       3,     4,     5,    26,    19,    27,    51,    52,    62,    56,
-      20,     6,    37,    38,     7,     8,    24,     9,    87,    10,
-      57,    58,    59,    87,    30,    32,    33,    34,    25,    21,
-      22,    23,    57,    58,    61,    79,     6,    22,    23,     7,
-       8,    40,     9,    41,    10,    46,    85,    57,    58,    86,
-      57,    58,    42,    43,    44,    45,    47,    22,    48,    49,
-      50,    54,    67,    68,    69,    71,    72,    70,    81,    73,
-      74,    75,    82,    83,    84,    88,     0,    53,    89
+      31,    67,    17,    37,    38,    15,    16,    81,    68,    44,
+      18,    69,    70,    23,    82,    85,    24,    25,    69,    70,
+      27,    19,    24,    25,    20,    28,    67,    29,    42,    43,
+      56,    57,     1,    21,     2,    61,    92,    32,     3,     4,
+       5,    92,    62,    63,    64,    62,    63,    66,    22,     6,
+      62,    63,     7,     8,    26,    45,     9,    48,    10,    84,
+      11,    34,    35,    36,    62,    63,    91,    39,    40,    46,
+      90,    47,     6,    49,    50,     7,     8,    51,    24,     9,
+      52,    10,    53,    11,    54,    55,    72,    75,    73,    59,
+      74,    76,    77,    78,    86,    79,    80,    87,    88,    89,
+      93,    58,    94
   };
 
-  const signed char
+  const unsigned char
   EvalParser::yycheck_[] =
   {
-      17,    19,    20,    49,     9,    21,    24,    12,    13,    25,
-      14,     1,     2,    14,     3,     9,     5,    14,    12,    13,
-       9,    10,    11,    25,     3,    27,    43,    44,    74,    47,
-       3,    20,    22,    23,    23,    24,     8,    26,    84,    28,
-      17,    18,    19,    89,    25,     9,    10,    11,     4,     0,
-       6,     7,    17,    18,    19,    72,    20,     6,     7,    23,
-      24,    15,    26,    15,    28,    22,    83,    17,    18,    19,
-      17,    18,    15,    14,    14,    14,    22,     6,    16,    16,
-      16,    25,    15,    15,    15,     4,    14,    22,     4,    16,
-      16,    16,    15,    14,    16,    15,    -1,    45,    16
+      18,    54,    14,    20,    21,     1,     2,    21,     9,    26,
+      14,    12,    13,     0,    28,     9,     6,     7,    12,    13,
+       4,    14,     6,     7,     3,    28,    79,    30,    24,    25,
+      48,    49,     3,     3,     5,    52,    89,    28,     9,    10,
+      11,    94,    17,    18,    19,    17,    18,    19,    16,    20,
+      17,    18,    23,    24,     8,    15,    27,    14,    29,    77,
+      31,     9,    10,    11,    17,    18,    19,    25,    26,    15,
+      88,    15,    20,    14,    14,    23,    24,    22,     6,    27,
+      22,    29,    16,    31,    16,    16,    15,    22,    15,    28,
+      15,     4,    14,    16,     4,    16,    16,    15,    14,    16,
+      15,    50,    16
   };
 
   const unsigned char
   EvalParser::yystos_[] =
   {
-       0,     3,     5,     9,    10,    11,    20,    23,    24,    26,
-      28,    30,    31,    32,    31,    31,    14,    14,    14,     3,
-       3,     0,     6,     7,     8,     4,    25,    27,    33,    33,
-      25,    38,     9,    10,    11,    32,    32,    31,    31,    32,
-      15,    15,    15,    14,    14,    14,    22,    22,    16,    16,
-      16,    33,    33,    38,    25,    35,    32,    17,    18,    19,
-      34,    19,    34,     9,    12,    13,    37,    15,    15,    15,
-      22,     4,    14,    16,    16,    16,    21,    25,    36,    33,
-       9,     4,    15,    14,    16,    33,    19,    34,    15,    16
+       0,     3,     5,     9,    10,    11,    20,    23,    24,    27,
+      29,    31,    33,    34,    35,    34,    34,    14,    14,    14,
+       3,     3,    16,     0,     6,     7,     8,     4,    28,    30,
+      36,    36,    28,    41,     9,    10,    11,    35,    35,    25,
+      26,    42,    34,    34,    35,    15,    15,    15,    14,    14,
+      14,    22,    22,    16,    16,    16,    36,    36,    41,    28,
+      38,    35,    17,    18,    19,    37,    19,    37,     9,    12,
+      13,    40,    15,    15,    15,    22,     4,    14,    16,    16,
+      16,    21,    28,    39,    36,     9,     4,    15,    14,    16,
+      36,    19,    37,    15,    16
   };
 
   const unsigned char
   EvalParser::yyr1_[] =
   {
-       0,    29,    30,    31,    31,    31,    31,    31,    31,    31,
-      31,    32,    32,    32,    32,    32,    32,    32,    32,    32,
-      33,    33,    34,    34,    35,    36,    36,    37,    37,    38
+       0,    32,    33,    34,    34,    34,    34,    34,    34,    34,
+      34,    35,    35,    35,    35,    35,    35,    35,    35,    35,
+      35,    36,    36,    37,    37,    38,    39,    39,    40,    40,
+      41,    42,    42
   };
 
   const unsigned char
@@ -1288,7 +1336,8 @@ namespace isc { namespace eval {
   {
        0,     2,     1,     3,     2,     3,     3,     3,     6,     6,
       11,     1,     1,     1,     6,     6,    11,     6,     8,     6,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1
+       3,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1
   };
 
 
@@ -1302,20 +1351,21 @@ namespace isc { namespace eval {
   "\"and\"", "\"or\"", "\"==\"", "\"option\"", "\"relay4\"", "\"relay6\"",
   "\"peeraddr\"", "\"linkaddr\"", "\"[\"", "\"]\"", "\".\"", "\"text\"",
   "\"hex\"", "\"exists\"", "\"substring\"", "\"all\"", "\",\"",
-  "\"concat\"", "\"constant string\"", "\"integer\"",
-  "\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept",
-  "expression", "bool_expr", "string_expr", "option_code",
-  "option_repr_type", "start_expr", "length_expr", "relay6_field",
-  "nest_level", YY_NULLPTR
+  "\"concat\"", "\"pkt6\"", "\"msgtype\"", "\"transid\"",
+  "\"constant string\"", "\"integer\"", "\"constant hexstring\"",
+  "\"option name\"", "\"ip address\"", "$accept", "expression",
+  "bool_expr", "string_expr", "option_code", "option_repr_type",
+  "start_expr", "length_expr", "relay6_field", "nest_level", "pkt6_field", YY_NULLPTR
   };
 
 #if YYDEBUG
   const unsigned short int
   EvalParser::yyrline_[] =
   {
-       0,    87,    87,    90,    91,    96,   101,   106,   111,   116,
-     136,   152,   157,   162,   167,   172,   193,   208,   224,   229,
-     236,   240,   246,   250,   256,   263,   268,   275,   276,   279
+       0,    91,    91,    94,    95,   100,   105,   110,   115,   120,
+     140,   156,   161,   166,   171,   176,   197,   212,   228,   233,
+     238,   245,   249,   255,   259,   265,   272,   277,   284,   285,
+     288,   297,   298
   };
 
   // Print the state stack on the debug stream.
@@ -1350,8 +1400,8 @@ namespace isc { namespace eval {
 
 #line 13 "parser.yy" // lalr1.cc:1167
 } } // isc::eval
-#line 1354 "parser.cc" // lalr1.cc:1167
-#line 288 "parser.yy" // lalr1.cc:1168
+#line 1404 "parser.cc" // lalr1.cc:1167
+#line 301 "parser.yy" // lalr1.cc:1168
 
 void
 isc::eval::EvalParser::error(const location_type& loc,

+ 116 - 54
src/lib/eval/parser.h

@@ -298,21 +298,24 @@ namespace isc { namespace eval {
       // option_repr_type
       char dummy1[sizeof(TokenOption::RepresentationType)];
 
+      // pkt6_field
+      char dummy2[sizeof(TokenPkt6::FieldType)];
+
       // relay6_field
-      char dummy2[sizeof(TokenRelay6Field::FieldType)];
+      char dummy3[sizeof(TokenRelay6Field::FieldType)];
 
       // "constant string"
       // "integer"
       // "constant hexstring"
       // "option name"
       // "ip address"
-      char dummy3[sizeof(std::string)];
+      char dummy4[sizeof(std::string)];
 
       // option_code
-      char dummy4[sizeof(uint16_t)];
+      char dummy5[sizeof(uint16_t)];
 
       // nest_level
-      char dummy5[sizeof(uint8_t)];
+      char dummy6[sizeof(uint8_t)];
 };
 
     /// Symbol semantic values.
@@ -357,11 +360,14 @@ namespace isc { namespace eval {
         TOKEN_ALL = 276,
         TOKEN_COMA = 277,
         TOKEN_CONCAT = 278,
-        TOKEN_STRING = 279,
-        TOKEN_INTEGER = 280,
-        TOKEN_HEXSTRING = 281,
-        TOKEN_OPTION_NAME = 282,
-        TOKEN_IP_ADDRESS = 283
+        TOKEN_PKT6 = 279,
+        TOKEN_MSGTYPE = 280,
+        TOKEN_TRANSID = 281,
+        TOKEN_STRING = 282,
+        TOKEN_INTEGER = 283,
+        TOKEN_HEXSTRING = 284,
+        TOKEN_OPTION_NAME = 285,
+        TOKEN_IP_ADDRESS = 286
       };
     };
 
@@ -401,6 +407,8 @@ namespace isc { namespace eval {
 
   basic_symbol (typename Base::kind_type t, const TokenOption::RepresentationType v, const location_type& l);
 
+  basic_symbol (typename Base::kind_type t, const TokenPkt6::FieldType v, const location_type& l);
+
   basic_symbol (typename Base::kind_type t, const TokenRelay6Field::FieldType v, const location_type& l);
 
   basic_symbol (typename Base::kind_type t, const std::string v, const location_type& l);
@@ -566,6 +574,18 @@ namespace isc { namespace eval {
 
     static inline
     symbol_type
+    make_PKT6 (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MSGTYPE (const location_type& l);
+
+    static inline
+    symbol_type
+    make_TRANSID (const location_type& l);
+
+    static inline
+    symbol_type
     make_STRING (const std::string& v, const location_type& l);
 
     static inline
@@ -669,7 +689,7 @@ namespace isc { namespace eval {
   // number is the opposite.  If YYTABLE_NINF, syntax error.
   static const unsigned char yytable_[];
 
-  static const signed char yycheck_[];
+  static const unsigned char yycheck_[];
 
   // YYSTOS[STATE-NUM] -- The (internal number of the) accessing
   // symbol of state STATE-NUM.
@@ -789,12 +809,12 @@ namespace isc { namespace eval {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 98,     ///< Last index in yytable_.
-      yynnts_ = 10,  ///< Number of nonterminal symbols.
-      yyfinal_ = 21, ///< Termination state number.
+      yylast_ = 102,     ///< Last index in yytable_.
+      yynnts_ = 11,  ///< Number of nonterminal symbols.
+      yyfinal_ = 23, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 29  ///< Number of tokens.
+      yyntokens_ = 32  ///< Number of tokens.
     };
 
 
@@ -839,9 +859,9 @@ namespace isc { namespace eval {
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28
+      25,    26,    27,    28,    29,    30,    31
     };
-    const unsigned int user_token_number_max_ = 283;
+    const unsigned int user_token_number_max_ = 286;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -874,27 +894,31 @@ namespace isc { namespace eval {
   {
       switch (other.type_get ())
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         value.copy< TokenOption::RepresentationType > (other.value);
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        value.copy< TokenPkt6::FieldType > (other.value);
+        break;
+
+      case 40: // relay6_field
         value.copy< TokenRelay6Field::FieldType > (other.value);
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         value.copy< std::string > (other.value);
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         value.copy< uint16_t > (other.value);
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         value.copy< uint8_t > (other.value);
         break;
 
@@ -915,27 +939,31 @@ namespace isc { namespace eval {
     (void) v;
       switch (this->type_get ())
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         value.copy< TokenOption::RepresentationType > (v);
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        value.copy< TokenPkt6::FieldType > (v);
+        break;
+
+      case 40: // relay6_field
         value.copy< TokenRelay6Field::FieldType > (v);
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         value.copy< std::string > (v);
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         value.copy< uint16_t > (v);
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         value.copy< uint8_t > (v);
         break;
 
@@ -962,6 +990,13 @@ namespace isc { namespace eval {
   {}
 
   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)
@@ -1015,27 +1050,31 @@ namespace isc { namespace eval {
     // Type destructor.
     switch (yytype)
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         value.template destroy< TokenOption::RepresentationType > ();
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        value.template destroy< TokenPkt6::FieldType > ();
+        break;
+
+      case 40: // relay6_field
         value.template destroy< TokenRelay6Field::FieldType > ();
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         value.template destroy< std::string > ();
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         value.template destroy< uint16_t > ();
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         value.template destroy< uint8_t > ();
         break;
 
@@ -1062,27 +1101,31 @@ namespace isc { namespace eval {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 34: // option_repr_type
+      case 37: // option_repr_type
         value.move< TokenOption::RepresentationType > (s.value);
         break;
 
-      case 37: // relay6_field
+      case 42: // pkt6_field
+        value.move< TokenPkt6::FieldType > (s.value);
+        break;
+
+      case 40: // relay6_field
         value.move< TokenRelay6Field::FieldType > (s.value);
         break;
 
-      case 24: // "constant string"
-      case 25: // "integer"
-      case 26: // "constant hexstring"
-      case 27: // "option name"
-      case 28: // "ip address"
+      case 27: // "constant string"
+      case 28: // "integer"
+      case 29: // "constant hexstring"
+      case 30: // "option name"
+      case 31: // "ip address"
         value.move< std::string > (s.value);
         break;
 
-      case 33: // option_code
+      case 36: // option_code
         value.move< uint16_t > (s.value);
         break;
 
-      case 38: // nest_level
+      case 41: // nest_level
         value.move< uint8_t > (s.value);
         break;
 
@@ -1143,7 +1186,8 @@ namespace isc { namespace eval {
     {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1281,6 +1325,24 @@ namespace isc { namespace eval {
   }
 
   EvalParser::symbol_type
+  EvalParser::make_PKT6 (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_PKT6, l);
+  }
+
+  EvalParser::symbol_type
+  EvalParser::make_MSGTYPE (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MSGTYPE, l);
+  }
+
+  EvalParser::symbol_type
+  EvalParser::make_TRANSID (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_TRANSID, l);
+  }
+
+  EvalParser::symbol_type
   EvalParser::make_STRING (const std::string& v, const location_type& l)
   {
     return symbol_type (token::TOKEN_STRING, v, l);
@@ -1313,7 +1375,7 @@ namespace isc { namespace eval {
 
 #line 13 "parser.yy" // lalr1.cc:377
 } } // isc::eval
-#line 1317 "parser.h" // lalr1.cc:377
+#line 1379 "parser.h" // lalr1.cc:377
 
 
 

+ 13 - 0
src/lib/eval/parser.yy

@@ -58,6 +58,9 @@ using namespace isc::eval;
   ALL "all"
   COMA ","
   CONCAT "concat"
+  PKT6 "pkt6"
+  MSGTYPE "msgtype"
+  TRANSID "transid"
 ;
 
 %token <std::string> STRING "constant string"
@@ -70,6 +73,7 @@ using namespace isc::eval;
 %type <TokenOption::RepresentationType> option_repr_type
 %type <TokenRelay6Field::FieldType> relay6_field
 %type <uint8_t> nest_level
+%type <TokenPkt6::FieldType> pkt6_field
 
 %left OR
 %left AND
@@ -231,6 +235,11 @@ string_expr : STRING
                       TokenPtr conc(new TokenConcat());
                       ctx.expression.push_back(conc);
                   }
+            | PKT6 "." pkt6_field
+                  {
+                      TokenPtr pkt6_field(new TokenPkt6($3));
+                      ctx.expression.push_back(pkt6_field);
+                  }
             ;
 
 option_code : INTEGER
@@ -285,6 +294,10 @@ nest_level : INTEGER
                  // an option or field.
            ;
 
+pkt6_field:MSGTYPE { $$ = TokenPkt6::MSGTYPE; }
+          | TRANSID { $$ = TokenPkt6::TRANSID; }
+          ;
+
 %%
 void
 isc::eval::EvalParser::error(const location_type& loc,

+ 57 - 0
src/lib/eval/tests/context_unittest.cc

@@ -256,6 +256,21 @@ public:
         checkTokenRelay6Field(eval.expression.at(0), exp_level, exp_type);
     }
 
+    /// @brief checks if the given token is Pkt6 of specified type
+    /// @param token token to be checked
+    /// @param exp_type expected type of the Pkt6 field
+    void checkTokenPkt6(const TokenPtr& token,
+                        TokenPkt6::FieldType exp_type) {
+        ASSERT_TRUE(token);
+
+        boost::shared_ptr<TokenPkt6> pkt =
+            boost::dynamic_pointer_cast<TokenPkt6>(token);
+
+        ASSERT_TRUE(pkt);
+
+        EXPECT_EQ(exp_type, pkt->getType());
+    }
+
     /// @brief checks if the given expression raises the expected message
     /// when it is parsed.
     void checkError(const string& expr, const string& msg) {
@@ -280,6 +295,38 @@ public:
         universe_ = universe;
     }
 
+    /// @brief Test that verifies access to the DHCPv6 packet fields.
+    ///
+    /// This test attempts to parse the expression, will check if the number
+    /// of tokens is exactly as planned and then will try to verify if the
+    /// first token represents expected the field in DHCPv6 packet.
+    ///
+    /// @param expr expression to be parsed
+    /// @param exp_type expected field type to be parsed
+    /// @param exp_tokens expected number of tokens
+    void testPkt6Field(std::string expr, TokenPkt6::FieldType exp_type,
+                       int exp_tokens) {
+        EvalContext eval(Option::V6);
+
+        // Parse the expression.
+        try {
+            parsed_ = eval.parseString(expr);
+        }
+        catch (const EvalParseError& ex) {
+            FAIL() << "Exception thrown: " << ex.what();
+            return;
+        }
+
+        // Parsing should succeed and return a token.
+        EXPECT_TRUE(parsed_);
+
+        // There should be the requested number of tokens
+        ASSERT_EQ(exp_tokens, eval.expression.size());
+
+        // Check that the first token is TokenPkt6 instance and has correct type.
+        checkTokenPkt6(eval.expression.at(0), exp_type);
+    }
+
     Option::Universe universe_;
     bool parsed_; ///< Parsing status
 };
@@ -538,6 +585,16 @@ TEST_F(EvalContextTest, relay4Error) {
                "<string>:1.1-6: relay4 can only be used in DHCPv4.");
 }
 
+// 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

+ 26 - 0
src/lib/eval/tests/token_unittest.cc

@@ -1203,3 +1203,29 @@ TEST_F(TokenTest, relay6Option) {
     // Level 2, no encapsulation so no options
     verifyRelay6Option(2, 100, TokenOption::TEXTUAL, "");
 }
+
+// Verifies if the DHCPv6 packet fields can be extracted.
+TEST_F(TokenTest, pkt6Fields) {
+    // The default test creates a v6 DHCPV6_SOLICIT packet with a
+    // transaction id of 12345.
+
+    // Check the message type
+    ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::MSGTYPE)));
+    EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+    ASSERT_EQ(1, values_.size());
+    uint32_t expected = htonl(1);
+    EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+
+    // Check the transaction id field
+    clearStack();
+    ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
+    EXPECT_NO_THROW(t_->evaluate(*pkt6_, values_));
+    ASSERT_EQ(1, values_.size());
+    expected = htonl(12345);
+    EXPECT_EQ(0, memcmp(&expected, &values_.top()[0], 4));
+
+    // Check that working with a v4 packet generates an error
+    clearStack();
+    ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
+    EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+}

+ 43 - 0
src/lib/eval/token.cc

@@ -360,3 +360,46 @@ TokenRelay6Field::evaluate(const Pkt& pkt, ValueStack& values) {
     }
     values.push(value);
 }
+
+void
+TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) {
+
+    vector<uint8_t> binary;
+    try {
+      // Check if it's a Pkt6.  If it's not the dynamic_cast will throw
+      // std::bad_cast (failed dynamic_cast returns NULL for pointers and
+      // throws for references).
+      const Pkt6& pkt6 = dynamic_cast<const Pkt6&>(pkt);
+
+      switch (type_) {
+      case MSGTYPE: {
+          // msg type is an uint8_t integer.  We want a 4 byte string so 0 pad.
+          binary.push_back(0);
+          binary.push_back(0);
+          binary.push_back(0);
+          binary.push_back(pkt6.getType());
+          break;
+      }
+      case TRANSID: {
+          // transaction id is an uint32_t integer.  We want a 4 byte string so copy
+          uint32_t transid = pkt6.getTransid();
+          binary.push_back(transid >> 24);
+          binary.push_back((transid >> 16) & 0xFF);
+          binary.push_back((transid >> 8) & 0xFF);
+          binary.push_back(transid & 0xFF);
+          break;
+      }
+      default:
+          isc_throw(EvalTypeError, "Bad field specified: "
+                    << static_cast<int>(type_) );
+      }
+
+    } catch (const std::bad_cast&) {
+        isc_throw(EvalTypeError, "Specified packet is not Pkt6");
+    }
+
+    string value;
+    value.resize(binary.size());
+    memmove(&value[0], &binary[0], binary.size());
+    values.push(value);
+}

+ 46 - 0
src/lib/eval/token.h

@@ -580,6 +580,52 @@ protected:
     FieldType type_; ///< field to get
 };
 
+/// @brief Token that represents fields of DHCPv6 packet.
+///
+/// For example in the expression pkt6.msgtype == 1
+/// this token represents the message type of the DHCPv6 packet.
+/// The integer values are placed on the value stack as 4 byte
+/// strings.
+///
+/// Currently supported fields are:
+/// - msgtype
+/// - transid
+class TokenPkt6 : public Token {
+public:
+    /// @brief enum value that determines the field.
+    enum FieldType {
+        MSGTYPE, ///< msg type
+        TRANSID  ///< transaction id (integer but manipulated as as string)
+    };
+
+    /// @brief Constructor (does nothing)
+    TokenPkt6(const FieldType type)
+        : type_(type) {}
+
+    /// @brief Gets a value of the specified packet.
+    ///
+    /// The evaluation uses fields that are availabe in the packet.  It does not
+    /// require any values to be present on the stack.
+    ///
+    /// @throw EvalTypeError when called for a DHCPv4 packet
+    ///
+    /// @param pkt - packet from which to extract the fields
+    /// @param values - stack of values, 1 result will be pushed
+    void evaluate(const Pkt& pkt, ValueStack& values);
+
+    /// @brief Returns field type
+    ///
+    /// This method is used only in tests.
+    /// @return type of the field.
+    FieldType getType() {
+        return(type_);
+    }
+
+private:
+    /// @brief Specifies field of the DHCPv6 packet to get
+    FieldType type_;
+};
+
 }; // end of isc::dhcp namespace
 }; // end of isc namespace