Browse Source

[4232a] Rebased and removed @

Francis Dupont 9 years ago
parent
commit
de00f69bc5

+ 6 - 2
src/lib/eval/Makefile.am

@@ -32,10 +32,14 @@ nodist_libkea_eval_la_SOURCES = eval_messages.h eval_messages.cc
 
 libkea_eval_la_CXXFLAGS = $(AM_CXXFLAGS)
 libkea_eval_la_CPPFLAGS = $(AM_CPPFLAGS)
-libkea_eval_la_LIBADD   = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
-libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+libkea_eval_la_LIBADD   = $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/dns/libkea-dns++.la
+libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
 libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/log/libkea-log.la
+libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/util/threads/libkea-threads.la
 libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/util/libkea-util.la
+libkea_eval_la_LIBADD  += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 libkea_eval_la_LIBADD  += $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS)
 
 libkea_eval_la_LDFLAGS  = -no-undefined -version-info 3:0:0

+ 198 - 180
src/lib/eval/lexer.cc

@@ -460,8 +460,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 26
-#define YY_END_OF_BUFFER 27
+#define YY_NUM_RULES 27
+#define YY_END_OF_BUFFER 28
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -469,35 +469,38 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_acclist[128] =
+static yyconst flex_int16_t yy_acclist[138] =
     {   0,
-       27,   25,   26,    1,   25,   26,    2,   26,   25,   26,
-       20,   25,   26,   21,   25,   26,   24,   25,   26,   25,
-       26,   19,   25,   26,    5,   25,   26,    5,   25,   26,
-       25,   26,   25,   26,16390,   22,   25,   26,   23,   25,
-       26,   25,   26,16390,   25,   26,16390,   25,   26,16390,
-       25,   26,16390,   25,   26,16390,   25,   26,16390,   25,
-       26,16390,   25,   26,16390,   25,   26,16390,    1,    2,
-        3,    5,    7,16390, 8198,16390,16390,16390,16390,16390,
-    16390,16390,   18,16390,16390,16390,16390,    4,   14,16390,
-       17,16390,16390,16390,   10,16390,   16,16390,16390,16390,
-
-    16390,16390,16390,16390,16390,16390,16390,    9,16390,16390,
-    16390,16390,16390,16390,   15,16390,   11,16390,    8,16390,
-       12,16390,16390,16390,16390,   13,16390
+       28,   26,   27,    1,   26,   27,    2,   27,   26,   27,
+       21,   26,   27,   22,   26,   27,   25,   26,   27,   26,
+       27,   20,   26,   27,    5,   26,   27,    5,   26,   27,
+       26,   27,   26,   27,   26,   27,16390,   26,   27,16390,
+       23,   26,   27,   24,   26,   27,   26,   27,16390,   26,
+       27,16390,   26,   27,16390,   26,   27,16390,   26,   27,
+    16390,   26,   27,16390,   26,   27,16390,   26,   27,16390,
+       26,   27,16390,    1,    2,    3,    5,    5,    7,    8,
+    16390,16390, 8198,16390,16390,16390,16390,16390,16390,16390,
+       19,16390,16390,16390,16390,    4,    7,   15,16390,   18,
+
+    16390,16390,16390,   11,16390,   17,16390,16390,16390,16390,
+    16390,16390,16390,16390,16390,16390,   10,16390,16390,16390,
+    16390,16390,16390,   16,16390,   12,16390,    9,16390,   13,
+    16390,16390,    7,16390,16390,   14,16390
     } ;
 
-static yyconst flex_int16_t yy_accept[82] =
+static yyconst flex_int16_t yy_accept[97] =
     {   0,
         1,    1,    1,    2,    4,    7,    9,   11,   14,   17,
-       20,   22,   25,   28,   31,   33,   36,   39,   42,   45,
-       48,   51,   54,   57,   60,   63,   66,   69,   70,   71,
-       71,   72,   73,   73,   74,   74,   74,   75,   76,   77,
-       78,   79,   80,   81,   82,   83,   85,   86,   87,   88,
-       89,   91,   93,   94,   95,   97,   99,  100,  101,  102,
-      103,  104,  105,  106,  107,  108,  110,  111,  112,  113,
-      114,  115,  117,  119,  121,  123,  124,  125,  126,  128,
-      128
+       20,   22,   25,   28,   31,   33,   35,   38,   41,   44,
+       47,   50,   53,   56,   59,   62,   65,   68,   71,   74,
+       75,   76,   76,   77,   78,   78,   79,   79,   79,   79,
+       79,   80,   81,   81,   81,   82,   83,   84,   85,   86,
+       87,   88,   89,   90,   91,   93,   94,   95,   96,   96,
+       97,   98,  100,  102,  103,  104,  106,  108,  109,  110,
+      111,  112,  112,  113,  114,  115,  116,  117,  119,  119,
+      120,  121,  122,  123,  124,  124,  126,  128,  130,  132,
+      133,  134,  135,  136,  138,  138
+
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -507,15 +510,15 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    2,    1,    1,    1,    1,    1,    1,    4,    5,
         6,    1,    1,    7,    8,    9,    1,   10,   11,   11,
-       11,   12,   11,   11,   11,   11,   11,    1,    1,    1,
-       13,    1,    1,    1,   14,   14,   14,   14,   14,   14,
-       15,   15,   15,   15,   15,   15,   15,   15,   15,   15,
-       15,   15,   15,   15,   15,   15,   15,   16,   15,   15,
-       17,    1,   18,    1,   19,    1,   20,   21,   22,   23,
-
-       24,   14,   25,   26,   27,   15,   15,   28,   15,   29,
-       30,   31,   15,   32,   33,   34,   35,   15,   15,   36,
-       37,   15,    1,    1,    1,    1,    1,    1,    1,    1,
+       11,   12,   11,   11,   11,   11,   11,   13,    1,    1,
+       14,    1,    1,    1,   15,   15,   15,   15,   15,   15,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   17,   16,   16,
+       18,    1,   19,    1,   20,    1,   21,   22,   23,   24,
+
+       25,   15,   26,   27,   28,   16,   16,   29,   16,   30,
+       31,   32,   16,   33,   34,   35,   36,   16,   16,   37,
+       38,   16,    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,
@@ -532,118 +535,116 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[38] =
+static yyconst flex_int32_t yy_meta[39] =
     {   0,
-        1,    2,    3,    1,    1,    1,    1,    2,    1,    4,
-        4,    4,    1,    4,    2,    2,    1,    2,    2,    4,
-        4,    4,    4,    4,    2,    2,    2,    2,    2,    2,
-        2,    2,    2,    2,    2,    2,    2
+        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
     } ;
 
-static yyconst flex_int16_t yy_base[84] =
+static yyconst flex_int16_t yy_base[101] =
     {   0,
-        0,    0,  202,  219,  167,  155,  138,  219,  219,  219,
-       28,  219,   31,   34,   94,   46,  219,  219,   66,   22,
-       27,   29,   31,   44,   42,   51,   53,  103,   80,   74,
-      219,   77,    0,  219,   88,   90,   68,  219,   70,   81,
-       72,   84,   86,   92,   95,   74,   88,  104,   99,    0,
-      102,  108,  112,  110,  116,  118,  121,  131,  124,  127,
-      134,  136,  138,  143,  145,  147,  149,  153,  156,  175,
-      160,  162,  165,  167,  169,  172,  177,  182,  180,  219,
-      211,  214,   58
+        0,    0,  191,  192,  188,  186,  184,  192,  192,  192,
+       29,  192,   33,   30,  174,  172,   69,   98,  192,  192,
+       22,  154,  147,  158,  151,   27,  156,  144,  154,  176,
+      174,  172,  192,   51,   54,   32,  162,  161,    0,  160,
+        0,  192,  112,  114,    0,    0,  192,  143,  147,  140,
+      141,  131,  132,  131,    0,  136,  142,  126,   64,    0,
+        0,    0,    0,  139,  127,    0,    0,  132,  138,  124,
+      122,  114,  135,  120,  123,  115,  117,    0,  118,  106,
+       98,   88,  100,   54,  124,    0,    0,    0,    0,   55,
+      127,   48,   42,    0,  192,  139,  141,  143,   49,  146
+
     } ;
 
-static yyconst flex_int16_t yy_def[84] =
+static yyconst flex_int16_t yy_def[101] =
     {   0,
-       80,    1,   80,   80,   80,   80,   81,   80,   80,   80,
-       80,   80,   80,   80,   80,   82,   80,   80,   82,   19,
-       19,   19,   19,   19,   19,   19,   19,   80,   80,   81,
-       80,   80,   83,   80,   80,   19,   19,   80,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,   19,   83,
-       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,   19,    0,
-       80,   80,   80
+       95,    1,   95,   95,   95,   95,   96,   95,   95,   95,
+       95,   95,   95,   13,   97,   95,   95,   17,   95,   95,
+       17,   17,   17,   18,   18,   18,   18,   18,   18,   95,
+       95,   96,   95,   95,   95,   13,   97,   98,   99,   97,
+      100,   95,   95,   18,   17,   18,   95,   18,   18,   18,
+       18,   18,   18,   18,   18,   18,   18,   18,   95,   99,
+      100,   18,   18,   18,   18,   18,   18,   18,   18,   18,
+       18,   95,   18,   18,   18,   18,   18,   18,   95,   18,
+       18,   18,   18,   18,   95,   18,   18,   18,   18,   18,
+       95,   18,   18,   18,    0,   95,   95,   95,   95,   95
+
     } ;
 
-static yyconst flex_int16_t yy_nxt[257] =
+static yyconst flex_int16_t yy_nxt[231] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   14,   15,   16,   16,   16,   17,   18,    4,   19,
-       16,   20,   16,   21,   16,   22,   16,   16,   23,   24,
-       16,   25,   26,   27,   16,   16,   16,   32,   32,   32,
-       32,   32,   32,   32,   32,   32,   33,   35,   35,   37,
-       37,   41,   43,   36,   37,   37,   37,   37,   37,   37,
-       44,   50,   42,   38,   36,   47,   33,   35,   35,   37,
-       37,   37,   37,   36,   45,   46,   49,   31,   37,   37,
-       37,   37,   29,   38,   36,   48,   32,   32,   32,   35,
-       35,   80,   80,   39,   40,   37,   37,   51,   37,   37,
-
-       53,   37,   37,   52,   28,   38,   34,   80,   37,   37,
-       54,   37,   37,   37,   37,   58,   37,   37,   37,   37,
-       37,   55,   37,   37,   59,   56,   37,   37,   57,   37,
-       37,   37,   37,   61,   60,   37,   37,   37,   37,   37,
-       37,   31,   62,   37,   37,   37,   37,   63,   37,   37,
-       64,   37,   37,   67,   37,   37,   65,   29,   37,   37,
-       66,   37,   37,   37,   37,   37,   37,   69,   28,   68,
-       37,   37,   37,   37,   37,   37,   37,   37,   71,   70,
-       37,   37,   72,   37,   74,   73,   75,   37,   37,   37,
-       37,   76,   37,   37,   37,   37,   37,   37,   77,   37,
-
-       37,   80,   37,   37,   37,   78,   79,   37,   37,   37,
-       37,   30,   30,   80,   30,   37,   37,   37,    3,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80
+       14,   14,   15,   16,   17,   18,   18,   19,   20,    4,
+       21,   17,   22,   17,   23,   18,   24,   18,   18,   25,
+       26,   18,   27,   28,   29,   18,   18,   18,   34,   34,
+       34,   35,   36,   36,   36,   37,   95,   38,   95,   39,
+       48,   49,   60,   38,   38,   38,   38,   38,   54,   55,
+       34,   34,   34,   59,   59,   59,   95,   94,   95,   39,
+       43,   43,   72,   59,   59,   59,   44,   93,   45,   45,
+       45,   37,   92,   45,   46,   46,   90,   47,   44,   45,
+       45,   45,   45,   45,   46,   46,   46,   46,   46,   46,
+
+       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
+       95,   89,   46,   43,   43,   95,   95,   88,   46,   46,
+       46,   46,   46,   79,   79,   79,   85,   79,   79,   79,
+       47,   87,   95,   91,   91,   91,   91,   91,   91,   32,
+       86,   32,   32,   32,   40,   40,   38,   38,   61,   61,
+       61,   84,   83,   82,   81,   80,   78,   77,   76,   75,
+       74,   73,   71,   70,   69,   68,   67,   66,   65,   64,
+       63,   62,   41,   37,   41,   33,   31,   30,   58,   57,
+       56,   53,   52,   51,   50,   42,   41,   33,   31,   30,
+       95,    3,   95,   95,   95,   95,   95,   95,   95,   95,
+
+       95,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,   95,   95
     } ;
 
-static yyconst flex_int16_t yy_chk[257] =
+static yyconst flex_int16_t yy_chk[231] =
     {   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,   11,   11,   11,
-       13,   13,   13,   14,   14,   14,   13,   16,   16,   20,
-       20,   20,   22,   16,   21,   21,   22,   22,   23,   23,
-       23,   83,   21,   16,   16,   25,   13,   19,   19,   25,
-       25,   24,   24,   19,   24,   24,   27,   30,   26,   26,
-       27,   27,   29,   19,   19,   26,   32,   32,   32,   35,
-       35,   36,   36,   19,   19,   37,   37,   39,   39,   41,
-
-       41,   46,   46,   40,   28,   35,   15,   36,   40,   40,
-       42,   42,   42,   43,   43,   47,   47,   36,   36,   44,
-       44,   43,   45,   45,   48,   44,   49,   49,   45,   51,
-       51,   48,   48,   53,   49,   52,   52,   54,   54,   53,
-       53,    7,   54,   55,   55,   56,   56,   57,   57,   57,
-       58,   59,   59,   61,   60,   60,   59,    6,   58,   58,
-       60,   61,   61,   62,   62,   63,   63,   63,    5,   62,
-       64,   64,   65,   65,   66,   66,   67,   67,   65,   64,
-       68,   68,   67,   69,   69,   68,   70,   71,   71,   72,
-       72,   71,   73,   73,   74,   74,   75,   75,   76,   76,
-
-       76,    3,   70,   70,   77,   77,   78,   79,   79,   78,
-       78,   81,   81,    0,   81,   82,   82,   82,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
-       80,   80,   80,   80,   80,   80
+        1,    1,    1,    1,    1,    1,    1,    1,   11,   11,
+       11,   13,   13,   13,   13,   13,   14,   13,   36,   13,
+       21,   21,   99,   13,   13,   13,   13,   13,   26,   26,
+       34,   34,   34,   35,   35,   35,   14,   93,   36,   13,
+       17,   17,   59,   59,   59,   59,   17,   92,   17,   17,
+       17,   17,   90,   17,   17,   17,   84,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17,   17,   17,
+
+       17,   17,   17,   17,   17,   17,   17,   18,   18,   18,
+       18,   83,   18,   43,   43,   44,   44,   82,   18,   18,
+       18,   18,   18,   72,   72,   72,   79,   79,   79,   79,
+       43,   81,   44,   85,   85,   85,   91,   91,   91,   96,
+       80,   96,   96,   96,   97,   97,   98,   98,  100,  100,
+      100,   77,   76,   75,   74,   73,   71,   70,   69,   68,
+       65,   64,   58,   57,   56,   54,   53,   52,   51,   50,
+       49,   48,   40,   38,   37,   32,   31,   30,   29,   28,
+       27,   25,   24,   23,   22,   16,   15,    7,    6,    5,
+        3,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+
+       95,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,   95,   95,
+       95,   95,   95,   95,   95,   95,   95,   95,   95,   95
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[27] =
+static yyconst flex_int32_t yy_rule_can_match_eol[28] =
     {   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,     };
 
 extern int yy_flex_debug;
 int yy_flex_debug = 1;
 
-static yyconst flex_int16_t yy_rule_linenum[26] =
+static yyconst flex_int16_t yy_rule_linenum[27] =
     {   0,
-       78,   82,   88,   98,  104,  118,  125,  126,  127,  128,
-      129,  130,  131,  132,  133,  134,  135,  136,  137,  138,
-      139,  140,  141,  142,  144
+       81,   85,   91,  101,  107,  121,  128,  141,  142,  143,
+      144,  145,  146,  147,  148,  149,  150,  151,  152,  153,
+      154,  155,  156,  157,  158,  160
     } ;
 
 static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
@@ -682,6 +683,7 @@ char *yytext;
 #include <string>
 #include <eval/eval_context.h>
 #include <eval/parser.h>
+#include <asiolink/io_address.h>
 #include <boost/lexical_cast.hpp>
 
 // Work around an incompatibility in flex (at least versions
@@ -715,12 +717,12 @@ static isc::eval::location loc;
    useful in more complex cases. */
 /* These are not token expressions yet, just convenience expressions that
    can be used during actual token definitions. */
-#line 65 "lexer.ll"
+#line 68 "lexer.ll"
 // This code run each time a pattern is matched. It updates the location
 // by moving it ahead by yyleng bytes. yyleng specifies the length of the
 // currently matched token.
 #define YY_USER_ACTION  loc.columns(yyleng);
-#line 724 "lexer.cc"
+#line 726 "lexer.cc"
 
 #define INITIAL 0
 
@@ -960,7 +962,7 @@ YY_DECL
 	register int yy_act;
     
 /* %% [7.0] user's declarations go here */
-#line 71 "lexer.ll"
+#line 74 "lexer.ll"
 
 
 
@@ -968,7 +970,7 @@ YY_DECL
     loc.step();
 
 
-#line 972 "lexer.cc"
+#line 974 "lexer.cc"
 
 	if ( !(yy_init) )
 		{
@@ -1036,14 +1038,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 >= 81 )
+				if ( yy_current_state >= 96 )
 					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 != 80 );
+		while ( yy_current_state != 95 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1107,13 +1109,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 < 26 )
+			else if ( yy_act < 27 )
 				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
 				         (long)yy_rule_linenum[yy_act], yytext );
-			else if ( yy_act == 26 )
+			else if ( yy_act == 27 )
 				fprintf( stderr, "--accepting default rule (\"%s\")\n",
 				         yytext );
-			else if ( yy_act == 27 )
+			else if ( yy_act == 28 )
 				fprintf( stderr, "--(end of buffer or a NUL)\n" );
 			else
 				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1124,7 +1126,7 @@ do_action:	/* This label is used only to access EOF actions. */
 /* %% [13.0] actions go here */
 case 1:
 YY_RULE_SETUP
-#line 78 "lexer.ll"
+#line 81 "lexer.ll"
 {
     // Ok, we found a with space. Let's ignore it and update loc variable.
     loc.step();
@@ -1133,7 +1135,7 @@ YY_RULE_SETUP
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 82 "lexer.ll"
+#line 85 "lexer.ll"
 {
     // Newline found. Let's update the location and continue.
     loc.lines(yyleng);
@@ -1142,7 +1144,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 88 "lexer.ll"
+#line 91 "lexer.ll"
 {
     // A string has been matched. It contains the actual string and single quotes.
     // We need to get those quotes out of the way and just use its content, e.g.
@@ -1155,7 +1157,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 98 "lexer.ll"
+#line 101 "lexer.ll"
 {
     // A hex string has been matched. It contains the '0x' or '0X' header
     // followed by at least one hexadecimal digit.
@@ -1164,7 +1166,7 @@ YY_RULE_SETUP
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 104 "lexer.ll"
+#line 107 "lexer.ll"
 {
     // An integer was found.
     std::string tmp(yytext);
@@ -1182,7 +1184,7 @@ YY_RULE_SETUP
 case 6:
 /* rule 6 can match eol */
 YY_RULE_SETUP
-#line 118 "lexer.ll"
+#line 121 "lexer.ll"
 {
     // This string specifies option name starting with a letter
     // and further containing letters, digits, hyphens and
@@ -1192,109 +1194,125 @@ YY_RULE_SETUP
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 125 "lexer.ll"
-return isc::eval::EvalParser::make_EQUAL(loc);
+#line 128 "lexer.ll"
+{
+    // IPv4 or IPv6 address
+    std::string tmp(yytext);
+
+    try {
+        isc::asiolink::IOAddress ip(tmp);
+    } catch (...) {
+        driver.error(loc, "Failed to convert " + tmp + " to an IP address.");
+    }
+
+    return isc::eval::EvalParser::make_IP_ADDRESS(yytext, loc);
+}
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 126 "lexer.ll"
-return isc::eval::EvalParser::make_OPTION(loc);
+#line 141 "lexer.ll"
+return isc::eval::EvalParser::make_EQUAL(loc);
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 127 "lexer.ll"
-return isc::eval::EvalParser::make_TEXT(loc);
+#line 142 "lexer.ll"
+return isc::eval::EvalParser::make_OPTION(loc);
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 128 "lexer.ll"
-return isc::eval::EvalParser::make_HEX(loc);
+#line 143 "lexer.ll"
+return isc::eval::EvalParser::make_TEXT(loc);
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 129 "lexer.ll"
-return isc::eval::EvalParser::make_EXISTS(loc);
+#line 144 "lexer.ll"
+return isc::eval::EvalParser::make_HEX(loc);
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 130 "lexer.ll"
-return isc::eval::EvalParser::make_RELAY4(loc);
+#line 145 "lexer.ll"
+return isc::eval::EvalParser::make_EXISTS(loc);
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 131 "lexer.ll"
-return isc::eval::EvalParser::make_SUBSTRING(loc);
+#line 146 "lexer.ll"
+return isc::eval::EvalParser::make_RELAY4(loc);
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 132 "lexer.ll"
-return isc::eval::EvalParser::make_ALL(loc);
+#line 147 "lexer.ll"
+return isc::eval::EvalParser::make_SUBSTRING(loc);
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 133 "lexer.ll"
-return isc::eval::EvalParser::make_CONCAT(loc);
+#line 148 "lexer.ll"
+return isc::eval::EvalParser::make_ALL(loc);
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 134 "lexer.ll"
-return isc::eval::EvalParser::make_NOT(loc);
+#line 149 "lexer.ll"
+return isc::eval::EvalParser::make_CONCAT(loc);
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 135 "lexer.ll"
-return isc::eval::EvalParser::make_AND(loc);
+#line 150 "lexer.ll"
+return isc::eval::EvalParser::make_NOT(loc);
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 136 "lexer.ll"
-return isc::eval::EvalParser::make_OR(loc);
+#line 151 "lexer.ll"
+return isc::eval::EvalParser::make_AND(loc);
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 137 "lexer.ll"
-return isc::eval::EvalParser::make_DOT(loc);
+#line 152 "lexer.ll"
+return isc::eval::EvalParser::make_OR(loc);
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 138 "lexer.ll"
-return isc::eval::EvalParser::make_LPAREN(loc);
+#line 153 "lexer.ll"
+return isc::eval::EvalParser::make_DOT(loc);
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 139 "lexer.ll"
-return isc::eval::EvalParser::make_RPAREN(loc);
+#line 154 "lexer.ll"
+return isc::eval::EvalParser::make_LPAREN(loc);
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 140 "lexer.ll"
-return isc::eval::EvalParser::make_LBRACKET(loc);
+#line 155 "lexer.ll"
+return isc::eval::EvalParser::make_RPAREN(loc);
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 141 "lexer.ll"
-return isc::eval::EvalParser::make_RBRACKET(loc);
+#line 156 "lexer.ll"
+return isc::eval::EvalParser::make_LBRACKET(loc);
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 142 "lexer.ll"
-return isc::eval::EvalParser::make_COMA(loc);
+#line 157 "lexer.ll"
+return isc::eval::EvalParser::make_RBRACKET(loc);
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 144 "lexer.ll"
+#line 158 "lexer.ll"
+return isc::eval::EvalParser::make_COMA(loc);
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 160 "lexer.ll"
 driver.error (loc, "Invalid character: " + std::string(yytext));
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 145 "lexer.ll"
+#line 161 "lexer.ll"
 return isc::eval::EvalParser::make_END(loc);
 	YY_BREAK
-case 26:
+case 27:
 YY_RULE_SETUP
-#line 146 "lexer.ll"
+#line 162 "lexer.ll"
 ECHO;
 	YY_BREAK
-#line 1298 "lexer.cc"
+#line 1316 "lexer.cc"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1574,7 +1592,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 >= 81 )
+			if ( yy_current_state >= 96 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1602,11 +1620,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 >= 81 )
+		if ( yy_current_state >= 96 )
 			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 == 80);
+	yy_is_jam = (yy_current_state == 95);
 	if ( ! yy_is_jam )
 		*(yy_state_ptr)++ = yy_current_state;
 
@@ -2364,7 +2382,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 146 "lexer.ll"
+#line 162 "lexer.ll"
 
 
 

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

@@ -11,6 +11,7 @@
 #include <string>
 #include <eval/eval_context.h>
 #include <eval/parser.h>
+#include <asiolink/io_address.h>
 #include <boost/lexical_cast.hpp>
 
 // Work around an incompatibility in flex (at least versions
@@ -60,6 +61,8 @@ static isc::eval::location loc;
 int   \-?[0-9]+
 hex   [0-9a-fA-F]+
 blank [ \t]
+addr4 [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
+addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
 
 %{
 // This code run each time a pattern is matched. It updates the location
@@ -122,6 +125,19 @@ blank [ \t]
     return isc::eval::EvalParser::make_OPTION_NAME(yytext, loc);
 }
 
+{addr4}|{addr6} {
+    // IPv4 or IPv6 address
+    std::string tmp(yytext);
+
+    try {
+        isc::asiolink::IOAddress ip(tmp);
+    } catch (...) {
+        driver.error(loc, "Failed to convert " + tmp + " to an IP address.");
+    }
+
+    return isc::eval::EvalParser::make_IP_ADDRESS(yytext, loc);
+}
+
 "=="        return isc::eval::EvalParser::make_EQUAL(loc);
 "option"    return isc::eval::EvalParser::make_OPTION(loc);
 "text"      return isc::eval::EvalParser::make_TEXT(loc);

+ 1 - 1
src/lib/eval/location.hh

@@ -1,4 +1,4 @@
-// Generated 20160219
+// Generated 20160227
 // A Bison parser, made by GNU Bison 3.0.4.
 
 // Locations for Bison parsers in C++

+ 134 - 115
src/lib/eval/parser.cc

@@ -251,7 +251,7 @@ namespace isc { namespace eval {
   {
       switch (that.type_get ())
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         value.move< TokenOption::RepresentationType > (that.value);
         break;
 
@@ -259,10 +259,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         value.move< std::string > (that.value);
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         value.move< uint16_t > (that.value);
         break;
 
@@ -281,7 +282,7 @@ namespace isc { namespace eval {
     state = that.state;
       switch (that.type_get ())
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         value.copy< TokenOption::RepresentationType > (that.value);
         break;
 
@@ -289,10 +290,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         value.copy< std::string > (that.value);
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         value.copy< uint16_t > (that.value);
         break;
 
@@ -334,44 +336,51 @@ namespace isc { namespace eval {
     {
             case 21: // "constant string"
 
-#line 71 "parser.yy" // lalr1.cc:636
+#line 72 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 340 "parser.cc" // lalr1.cc:636
+#line 342 "parser.cc" // lalr1.cc:636
         break;
 
       case 22: // "integer"
 
-#line 71 "parser.yy" // lalr1.cc:636
+#line 72 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 347 "parser.cc" // lalr1.cc:636
+#line 349 "parser.cc" // lalr1.cc:636
         break;
 
       case 23: // "constant hexstring"
 
-#line 71 "parser.yy" // lalr1.cc:636
+#line 72 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 354 "parser.cc" // lalr1.cc:636
+#line 356 "parser.cc" // lalr1.cc:636
         break;
 
       case 24: // "option name"
 
-#line 71 "parser.yy" // lalr1.cc:636
+#line 72 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
-#line 361 "parser.cc" // lalr1.cc:636
+#line 363 "parser.cc" // lalr1.cc:636
         break;
 
-      case 29: // option_code
+      case 25: // "ip address"
 
-#line 71 "parser.yy" // lalr1.cc:636
+#line 72 "parser.yy" // lalr1.cc:636
+        { yyoutput << yysym.value.template as< std::string > (); }
+#line 370 "parser.cc" // lalr1.cc:636
+        break;
+
+      case 30: // option_code
+
+#line 72 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< uint16_t > (); }
-#line 368 "parser.cc" // lalr1.cc:636
+#line 377 "parser.cc" // lalr1.cc:636
         break;
 
-      case 30: // option_repr_type
+      case 31: // option_repr_type
 
-#line 71 "parser.yy" // lalr1.cc:636
+#line 72 "parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< TokenOption::RepresentationType > (); }
-#line 375 "parser.cc" // lalr1.cc:636
+#line 384 "parser.cc" // lalr1.cc:636
         break;
 
 
@@ -571,7 +580,7 @@ namespace isc { namespace eval {
          when using variants.  */
         switch (yyr1_[yyn])
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         yylhs.value.build< TokenOption::RepresentationType > ();
         break;
 
@@ -579,10 +588,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         yylhs.value.build< std::string > ();
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         yylhs.value.build< uint16_t > ();
         break;
 
@@ -604,79 +614,88 @@ namespace isc { namespace eval {
           switch (yyn)
             {
   case 4:
-#line 85 "parser.yy" // lalr1.cc:859
+#line 86 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenNot());
                     ctx.expression.push_back(neg);
                 }
-#line 613 "parser.cc" // lalr1.cc:859
+#line 623 "parser.cc" // lalr1.cc:859
     break;
 
   case 5:
-#line 90 "parser.yy" // lalr1.cc:859
+#line 91 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenAnd());
                     ctx.expression.push_back(neg);
                 }
-#line 622 "parser.cc" // lalr1.cc:859
+#line 632 "parser.cc" // lalr1.cc:859
     break;
 
   case 6:
-#line 95 "parser.yy" // lalr1.cc:859
+#line 96 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr neg(new TokenOr());
                     ctx.expression.push_back(neg);
                 }
-#line 631 "parser.cc" // lalr1.cc:859
+#line 641 "parser.cc" // lalr1.cc:859
     break;
 
   case 7:
-#line 100 "parser.yy" // lalr1.cc:859
+#line 101 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr eq(new TokenEqual());
                     ctx.expression.push_back(eq);
                 }
-#line 640 "parser.cc" // lalr1.cc:859
+#line 650 "parser.cc" // lalr1.cc:859
     break;
 
   case 8:
-#line 105 "parser.yy" // lalr1.cc:859
+#line 106 "parser.yy" // lalr1.cc:859
     {
                     TokenPtr opt(new TokenOption(yystack_[3].value.as< uint16_t > (), TokenOption::EXISTS));
                     ctx.expression.push_back(opt);
                 }
-#line 649 "parser.cc" // lalr1.cc:859
+#line 659 "parser.cc" // lalr1.cc:859
     break;
 
   case 9:
-#line 112 "parser.yy" // lalr1.cc:859
+#line 113 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 658 "parser.cc" // lalr1.cc:859
+#line 668 "parser.cc" // lalr1.cc:859
     break;
 
   case 10:
-#line 117 "parser.yy" // lalr1.cc:859
+#line 118 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr hex(new TokenHexString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(hex);
                   }
-#line 667 "parser.cc" // lalr1.cc:859
+#line 677 "parser.cc" // lalr1.cc:859
     break;
 
   case 11:
-#line 122 "parser.yy" // lalr1.cc:859
+#line 123 "parser.yy" // lalr1.cc:859
+    {
+                      TokenPtr ip(new TokenIpAddress(yystack_[0].value.as< std::string > ()));
+                      ctx.expression.push_back(ip);
+                  }
+#line 686 "parser.cc" // lalr1.cc:859
+    break;
+
+  case 12:
+#line 128 "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 676 "parser.cc" // lalr1.cc:859
+#line 695 "parser.cc" // lalr1.cc:859
     break;
 
-  case 12:
-#line 127 "parser.yy" // lalr1.cc:859
+  case 13:
+#line 133 "parser.yy" // lalr1.cc:859
     {
                      switch (ctx.getUniverse()) {
                      case Option::V4:
@@ -696,88 +715,88 @@ namespace isc { namespace eval {
                          error(yystack_[5].location, "relay4 can only be used in DHCPv4.");
                      }
                   }
-#line 700 "parser.cc" // lalr1.cc:859
+#line 719 "parser.cc" // lalr1.cc:859
     break;
 
-  case 13:
-#line 147 "parser.yy" // lalr1.cc:859
+  case 14:
+#line 153 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
                   }
-#line 709 "parser.cc" // lalr1.cc:859
+#line 728 "parser.cc" // lalr1.cc:859
     break;
 
-  case 14:
-#line 152 "parser.yy" // lalr1.cc:859
+  case 15:
+#line 158 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr conc(new TokenConcat());
                       ctx.expression.push_back(conc);
                   }
-#line 718 "parser.cc" // lalr1.cc:859
+#line 737 "parser.cc" // lalr1.cc:859
     break;
 
-  case 15:
-#line 159 "parser.yy" // lalr1.cc:859
+  case 16:
+#line 165 "parser.yy" // lalr1.cc:859
     {
                      yylhs.value.as< uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 726 "parser.cc" // lalr1.cc:859
+#line 745 "parser.cc" // lalr1.cc:859
     break;
 
-  case 16:
-#line 163 "parser.yy" // lalr1.cc:859
+  case 17:
+#line 169 "parser.yy" // lalr1.cc:859
     {
                      yylhs.value.as< uint16_t > () = ctx.convertOptionName(yystack_[0].value.as< std::string > (), yystack_[0].location);
                  }
-#line 734 "parser.cc" // lalr1.cc:859
+#line 753 "parser.cc" // lalr1.cc:859
     break;
 
-  case 17:
-#line 169 "parser.yy" // lalr1.cc:859
+  case 18:
+#line 175 "parser.yy" // lalr1.cc:859
     {
                           yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                       }
-#line 742 "parser.cc" // lalr1.cc:859
+#line 761 "parser.cc" // lalr1.cc:859
     break;
 
-  case 18:
-#line 173 "parser.yy" // lalr1.cc:859
+  case 19:
+#line 179 "parser.yy" // lalr1.cc:859
     {
                           yylhs.value.as< TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
                       }
-#line 750 "parser.cc" // lalr1.cc:859
+#line 769 "parser.cc" // lalr1.cc:859
     break;
 
-  case 19:
-#line 179 "parser.yy" // lalr1.cc:859
+  case 20:
+#line 185 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                      ctx.expression.push_back(str);
                  }
-#line 759 "parser.cc" // lalr1.cc:859
+#line 778 "parser.cc" // lalr1.cc:859
     break;
 
-  case 20:
-#line 186 "parser.yy" // lalr1.cc:859
+  case 21:
+#line 192 "parser.yy" // lalr1.cc:859
     {
                       TokenPtr str(new TokenString(yystack_[0].value.as< std::string > ()));
                       ctx.expression.push_back(str);
                   }
-#line 768 "parser.cc" // lalr1.cc:859
+#line 787 "parser.cc" // lalr1.cc:859
     break;
 
-  case 21:
-#line 191 "parser.yy" // lalr1.cc:859
+  case 22:
+#line 197 "parser.yy" // lalr1.cc:859
     {
                      TokenPtr str(new TokenString("all"));
                      ctx.expression.push_back(str);
                  }
-#line 777 "parser.cc" // lalr1.cc:859
+#line 796 "parser.cc" // lalr1.cc:859
     break;
 
 
-#line 781 "parser.cc" // lalr1.cc:859
+#line 800 "parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -1032,93 +1051,93 @@ namespace isc { namespace eval {
   }
 
 
-  const signed char EvalParser::yypact_ninf_ = -14;
+  const signed char EvalParser::yypact_ninf_ = -18;
 
   const signed char EvalParser::yytable_ninf_ = -1;
 
   const signed char
   EvalParser::yypact_[] =
   {
-      -2,   -12,    -4,     3,    -2,    14,    -2,   -14,   -14,    39,
-      33,    40,    16,     6,     6,   -14,    16,    17,   -14,    -2,
-      -2,     6,   -14,   -14,    25,    27,    28,    31,    29,   -14,
-     -14,    42,   -14,    36,    16,    26,     6,    37,    24,    34,
-     -14,    41,    35,    18,   -14,   -14,   -14,   -14,    43,     0,
-     -14,   -14,    18,   -14,   -14,    38,   -14
+      -1,   -17,    -8,     4,    -1,    12,    -1,   -18,   -18,   -18,
+      35,     6,    36,    20,     7,     7,   -18,    20,    18,   -18,
+      -1,    -1,     7,   -18,   -18,    26,    29,    31,    34,    32,
+     -18,   -18,    41,   -18,    38,    20,    37,     7,    39,    28,
+      40,   -18,    42,    43,    33,   -18,   -18,   -18,   -18,    47,
+      15,   -18,   -18,    33,   -18,   -18,    45,   -18
   };
 
   const unsigned char
   EvalParser::yydefact_[] =
   {
-       0,     0,     0,     0,     0,     0,     0,     9,    10,     0,
-       2,     0,     0,     0,     0,     4,     0,     0,     1,     0,
-       0,     0,    15,    16,     0,     0,     0,     0,     0,     3,
-       5,     6,     7,     0,     0,     0,     0,     0,     0,     0,
-      19,     0,     0,     0,    17,    18,     8,    11,     0,     0,
-      14,    12,     0,    21,    20,     0,    13
+       0,     0,     0,     0,     0,     0,     0,     9,    10,    11,
+       0,     2,     0,     0,     0,     0,     4,     0,     0,     1,
+       0,     0,     0,    16,    17,     0,     0,     0,     0,     0,
+       3,     5,     6,     7,     0,     0,     0,     0,     0,     0,
+       0,    20,     0,     0,     0,    18,    19,     8,    12,     0,
+       0,    15,    13,     0,    22,    21,     0,    14
   };
 
   const signed char
   EvalParser::yypgoto_[] =
   {
-     -14,   -14,    12,   -13,   -10,    19,   -14,   -14
+     -18,   -18,    13,   -14,   -10,    11,   -18,   -18
   };
 
   const signed char
   EvalParser::yydefgoto_[] =
   {
-      -1,     9,    10,    11,    24,    47,    41,    55
+      -1,    10,    11,    12,    25,    48,    42,    56
   };
 
   const unsigned char
   EvalParser::yytable_[] =
   {
-      26,    27,     1,     2,     3,     4,    28,    12,    32,     5,
-      25,     2,     3,    13,    53,     6,    15,     5,    17,     7,
-      14,     8,    54,    42,    39,    19,    20,     7,    44,     8,
-      45,    30,    31,    16,    44,    29,    45,    46,    22,    18,
-      23,    19,    20,    21,    35,    33,    34,    36,    40,    37,
-      19,    38,    43,    50,    48,     0,    56,    49,    52,     0,
-       0,     0,    51
+      27,    28,    13,     1,     2,     3,     4,    29,    33,    14,
+       5,    26,     2,     3,    20,    21,     6,    16,     5,    18,
+       7,    15,     8,    43,     9,    40,    20,    21,     7,    54,
+       8,    17,     9,    31,    32,    19,    30,    55,    45,    22,
+      46,    47,    23,    45,    24,    46,    34,    36,    35,    20,
+      37,     0,    38,    39,    44,    52,     0,     0,    50,    41,
+      49,    51,    53,    57
   };
 
   const signed char
   EvalParser::yycheck_[] =
   {
-      13,    14,     4,     5,     6,     7,    16,    19,    21,    11,
-       4,     5,     6,    17,    14,    17,     4,    11,     6,    21,
-      17,    23,    22,    36,    34,     8,     9,    21,    10,    23,
-      12,    19,    20,    19,    10,    18,    12,    13,    22,     0,
-      24,     8,     9,     3,    16,    20,    19,    16,    22,    20,
-       8,    15,    15,    18,    20,    -1,    18,    16,    15,    -1,
-      -1,    -1,    43
+      14,    15,    19,     4,     5,     6,     7,    17,    22,    17,
+      11,     4,     5,     6,     8,     9,    17,     4,    11,     6,
+      21,    17,    23,    37,    25,    35,     8,     9,    21,    14,
+      23,    19,    25,    20,    21,     0,    18,    22,    10,     3,
+      12,    13,    22,    10,    24,    12,    20,    16,    19,     8,
+      16,    -1,    20,    15,    15,    44,    -1,    -1,    16,    22,
+      20,    18,    15,    18
   };
 
   const unsigned char
   EvalParser::yystos_[] =
   {
-       0,     4,     5,     6,     7,    11,    17,    21,    23,    26,
-      27,    28,    19,    17,    17,    27,    19,    27,     0,     8,
-       9,     3,    22,    24,    29,     4,    28,    28,    29,    18,
-      27,    27,    28,    20,    19,    16,    16,    20,    15,    29,
-      22,    31,    28,    15,    10,    12,    13,    30,    20,    16,
-      18,    30,    15,    14,    22,    32,    18
+       0,     4,     5,     6,     7,    11,    17,    21,    23,    25,
+      27,    28,    29,    19,    17,    17,    28,    19,    28,     0,
+       8,     9,     3,    22,    24,    30,     4,    29,    29,    30,
+      18,    28,    28,    29,    20,    19,    16,    16,    20,    15,
+      30,    22,    32,    29,    15,    10,    12,    13,    31,    20,
+      16,    18,    31,    15,    14,    22,    33,    18
   };
 
   const unsigned char
   EvalParser::yyr1_[] =
   {
-       0,    25,    26,    27,    27,    27,    27,    27,    27,    28,
-      28,    28,    28,    28,    28,    29,    29,    30,    30,    31,
-      32,    32
+       0,    26,    27,    28,    28,    28,    28,    28,    28,    29,
+      29,    29,    29,    29,    29,    29,    30,    30,    31,    31,
+      32,    33,    33
   };
 
   const unsigned char
   EvalParser::yyr2_[] =
   {
        0,     2,     1,     3,     2,     3,     3,     3,     6,     1,
-       1,     6,     6,     8,     6,     1,     1,     1,     1,     1,
-       1,     1
+       1,     1,     6,     6,     8,     6,     1,     1,     1,     1,
+       1,     1,     1
   };
 
 
@@ -1132,18 +1151,18 @@ namespace isc { namespace eval {
   "\"substring\"", "\"concat\"", "\"not\"", "\"and\"", "\"or\"",
   "\"text\"", "\"relay4\"", "\"hex\"", "\"exists\"", "\"all\"", "\".\"",
   "\",\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", "\"constant string\"",
-  "\"integer\"", "\"constant hexstring\"", "\"option name\"", "$accept",
-  "expression", "bool_expr", "string_expr", "option_code",
-  "option_repr_type", "start_expr", "length_expr", YY_NULLPTR
+  "\"integer\"", "\"constant hexstring\"", "\"option name\"",
+  "\"ip address\"", "$accept", "expression", "bool_expr", "string_expr",
+  "option_code", "option_repr_type", "start_expr", "length_expr", YY_NULLPTR
   };
 
 #if YYDEBUG
   const unsigned char
   EvalParser::yyrline_[] =
   {
-       0,    80,    80,    83,    84,    89,    94,    99,   104,   111,
-     116,   121,   126,   146,   151,   158,   162,   168,   172,   178,
-     185,   190
+       0,    81,    81,    84,    85,    90,    95,   100,   105,   112,
+     117,   122,   127,   132,   152,   157,   164,   168,   174,   178,
+     184,   191,   196
   };
 
   // Print the state stack on the debug stream.
@@ -1178,8 +1197,8 @@ namespace isc { namespace eval {
 
 #line 13 "parser.yy" // lalr1.cc:1167
 } } // isc::eval
-#line 1182 "parser.cc" // lalr1.cc:1167
-#line 197 "parser.yy" // lalr1.cc:1168
+#line 1201 "parser.cc" // lalr1.cc:1167
+#line 203 "parser.yy" // lalr1.cc:1168
 
 void
 isc::eval::EvalParser::error(const location_type& loc,

+ 33 - 16
src/lib/eval/parser.h

@@ -302,6 +302,7 @@ namespace isc { namespace eval {
       // "integer"
       // "constant hexstring"
       // "option name"
+      // "ip address"
       char dummy2[sizeof(std::string)];
 
       // option_code
@@ -350,7 +351,8 @@ namespace isc { namespace eval {
         TOKEN_STRING = 276,
         TOKEN_INTEGER = 277,
         TOKEN_HEXSTRING = 278,
-        TOKEN_OPTION_NAME = 279
+        TOKEN_OPTION_NAME = 279,
+        TOKEN_IP_ADDRESS = 280
       };
     };
 
@@ -553,6 +555,10 @@ namespace isc { namespace eval {
     symbol_type
     make_OPTION_NAME (const std::string& v, const location_type& l);
 
+    static inline
+    symbol_type
+    make_IP_ADDRESS (const std::string& v, const location_type& l);
+
 
     /// Build a parser object.
     EvalParser (EvalContext& ctx_yyarg);
@@ -758,12 +764,12 @@ namespace isc { namespace eval {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 62,     ///< Last index in yytable_.
+      yylast_ = 63,     ///< Last index in yytable_.
       yynnts_ = 8,  ///< Number of nonterminal symbols.
-      yyfinal_ = 18, ///< Termination state number.
+      yyfinal_ = 19, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 25  ///< Number of tokens.
+      yyntokens_ = 26  ///< Number of tokens.
     };
 
 
@@ -807,9 +813,10 @@ namespace isc { namespace eval {
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        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
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25
     };
-    const unsigned int user_token_number_max_ = 279;
+    const unsigned int user_token_number_max_ = 280;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -842,7 +849,7 @@ namespace isc { namespace eval {
   {
       switch (other.type_get ())
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         value.copy< TokenOption::RepresentationType > (other.value);
         break;
 
@@ -850,10 +857,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         value.copy< std::string > (other.value);
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         value.copy< uint16_t > (other.value);
         break;
 
@@ -874,7 +882,7 @@ namespace isc { namespace eval {
     (void) v;
       switch (this->type_get ())
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         value.copy< TokenOption::RepresentationType > (v);
         break;
 
@@ -882,10 +890,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         value.copy< std::string > (v);
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         value.copy< uint16_t > (v);
         break;
 
@@ -951,7 +960,7 @@ namespace isc { namespace eval {
     // Type destructor.
     switch (yytype)
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         value.template destroy< TokenOption::RepresentationType > ();
         break;
 
@@ -959,10 +968,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         value.template destroy< std::string > ();
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         value.template destroy< uint16_t > ();
         break;
 
@@ -989,7 +999,7 @@ namespace isc { namespace eval {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 30: // option_repr_type
+      case 31: // option_repr_type
         value.move< TokenOption::RepresentationType > (s.value);
         break;
 
@@ -997,10 +1007,11 @@ namespace isc { namespace eval {
       case 22: // "integer"
       case 23: // "constant hexstring"
       case 24: // "option name"
+      case 25: // "ip address"
         value.move< std::string > (s.value);
         break;
 
-      case 29: // option_code
+      case 30: // option_code
         value.move< uint16_t > (s.value);
         break;
 
@@ -1061,7 +1072,7 @@ 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
+     275,   276,   277,   278,   279,   280
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1204,10 +1215,16 @@ namespace isc { namespace eval {
     return symbol_type (token::TOKEN_OPTION_NAME, v, l);
   }
 
+  EvalParser::symbol_type
+  EvalParser::make_IP_ADDRESS (const std::string& v, const location_type& l)
+  {
+    return symbol_type (token::TOKEN_IP_ADDRESS, v, l);
+  }
+
 
 #line 13 "parser.yy" // lalr1.cc:392
 } } // isc::eval
-#line 1211 "parser.h" // lalr1.cc:392
+#line 1228 "parser.h" // lalr1.cc:392
 
 
 

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

@@ -60,6 +60,7 @@ using namespace isc::eval;
 %token <std::string> INTEGER "integer"
 %token <std::string> HEXSTRING "constant hexstring"
 %token <std::string> OPTION_NAME "option name"
+%token <std::string> IP_ADDRESS "ip address"
 
 %type <uint16_t> option_code
 %type <TokenOption::RepresentationType> option_repr_type
@@ -118,6 +119,11 @@ string_expr : STRING
                       TokenPtr hex(new TokenHexString($1));
                       ctx.expression.push_back(hex);
                   }
+            | IP_ADDRESS
+                  {
+                      TokenPtr ip(new TokenIpAddress($1));
+                      ctx.expression.push_back(ip);
+                  }
             | OPTION "[" option_code "]" "." option_repr_type
                   {
                       TokenPtr opt(new TokenOption($3, $6));

+ 1 - 1
src/lib/eval/position.hh

@@ -1,4 +1,4 @@
-// Generated 20160219
+// Generated 20160227
 // A Bison parser, made by GNU Bison 3.0.4.
 
 // Positions for Bison parsers in C++

+ 1 - 1
src/lib/eval/stack.hh

@@ -1,4 +1,4 @@
-// Generated 20160219
+// Generated 20160227
 // A Bison parser, made by GNU Bison 3.0.4.
 
 // Stack handling for Bison parsers in C++

+ 5 - 0
src/lib/eval/tests/Makefile.am

@@ -36,7 +36,12 @@ libeval_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 libeval_unittests_LDFLAGS  = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
 libeval_unittests_LDADD    = $(top_builddir)/src/lib/eval/libkea-eval.la
 libeval_unittests_LDADD   += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+libeval_unittests_LDADD   += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
+libeval_unittests_LDADD   += $(top_builddir)/src/lib/dns/libkea-dns++.la
+libeval_unittests_LDADD   += $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
 libeval_unittests_LDADD   += $(top_builddir)/src/lib/log/libkea-log.la
+libeval_unittests_LDADD   += $(top_builddir)/src/lib/util/threads/libkea-threads.la
+libeval_unittests_LDADD   += $(top_builddir)/src/lib/util/libkea-util.la
 libeval_unittests_LDADD   += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
 libeval_unittests_LDADD   += $(CRYPTO_LIBS) $(LOG4CPLUS_LIBS)
 libeval_unittests_LDADD   += $(BOOST_LIBS) $(GTEST_LDADD)

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

@@ -10,12 +10,14 @@
 #include <eval/token.h>
 #include <dhcp/option.h>
 #include <dhcp/pkt4.h>
+#include <asiolink/io_address.h>
 
 #include <boost/shared_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <gtest/gtest.h>
 
 using namespace std;
+using namespace isc::asiolink;
 using namespace isc::dhcp;
 
 namespace {
@@ -63,6 +65,29 @@ public:
         EXPECT_EQ(expected, values.top());
     }
 
+    /// @brief checks if the given token is an IP address with the expected value
+    void checkTokenIpAddress(const TokenPtr& token,
+                             const std::string& expected) {
+        ASSERT_TRUE(token);
+        boost::shared_ptr<TokenIpAddress> ipaddr =
+            boost::dynamic_pointer_cast<TokenIpAddress>(token);
+        ASSERT_TRUE(ipaddr);
+
+        Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
+        ValueStack values;
+
+        EXPECT_NO_THROW(token->evaluate(*pkt4, values));
+
+        ASSERT_EQ(1, values.size());
+        string value = values.top();
+
+        boost::scoped_ptr<IOAddress> exp_ip;
+        ASSERT_NO_THROW(exp_ip.reset(new IOAddress(expected)));
+        vector<uint8_t> exp_addr = exp_ip->toBytes();
+        ASSERT_EQ(exp_addr.size(), value.size());
+        EXPECT_EQ(0, memcmp(&exp_addr[0], &value[0], value.size()));
+    }
+
     /// @brief checks if the given token is an equal operator
     void checkTokenEq(const TokenPtr& token) {
         ASSERT_TRUE(token);
@@ -201,6 +226,63 @@ TEST_F(EvalContextTest, oddHexstring) {
     checkTokenHexString(tmp, "\a");
 }
 
+// Test the parsing of an IPv4 address
+TEST_F(EvalContextTest, ipaddress4) {
+    EvalContext eval(Option::V6);
+
+    EXPECT_NO_THROW(parsed_ = eval.parseString("10.0.0.1 == 'foo'"));
+    EXPECT_TRUE(parsed_);
+
+    ASSERT_EQ(3, eval.expression.size());
+
+    TokenPtr tmp = eval.expression.at(0);
+
+    checkTokenIpAddress(tmp, "10.0.0.1");
+}
+
+// Test the parsing of an IPv6 address
+TEST_F(EvalContextTest, ipaddress6) {
+    EvalContext eval(Option::V6);
+
+    EXPECT_NO_THROW(parsed_ = eval.parseString("2001:db8::1 == 'foo'"));
+    EXPECT_TRUE(parsed_);
+
+    ASSERT_EQ(3, eval.expression.size());
+
+    TokenPtr tmp = eval.expression.at(0);
+
+    checkTokenIpAddress(tmp, "2001:db8::1");
+}
+
+// Test the parsing of an IPv4 mapped IPv6 address
+TEST_F(EvalContextTest, ipaddress46) {
+    EvalContext eval(Option::V6);
+
+    EXPECT_NO_THROW(parsed_ = eval.parseString("::10.0.0.1 == 'foo'"));
+    EXPECT_TRUE(parsed_);
+
+    ASSERT_EQ(3, eval.expression.size());
+
+    TokenPtr tmp = eval.expression.at(0);
+
+    checkTokenIpAddress(tmp, "::10.0.0.1");
+}
+
+// Test the parsing of the unspecified IPv6 address
+TEST_F(EvalContextTest, ipaddress6unspec) {
+    EvalContext eval(Option::V6);
+
+    EXPECT_NO_THROW(parsed_ = eval.parseString(":: == 'foo'"));
+    EXPECT_TRUE(parsed_);
+
+    ASSERT_EQ(3, eval.expression.size());
+
+    TokenPtr tmp = eval.expression.at(0);
+
+    checkTokenIpAddress(tmp, "::");
+}
+
+
 // Test the parsing of an equal expression
 TEST_F(EvalContextTest, equal) {
     EvalContext eval(Option::V4);
@@ -462,6 +544,7 @@ TEST_F(EvalContextTest, scanErrors) {
     checkError("'\''", "<string>:1.3: Invalid character: '");
     checkError("'\n'", "<string>:1.1: Invalid character: '");
     checkError("0x123h", "<string>:1.6: Invalid character: h");
+    checkError(":1", "<string>:1.1: Invalid character: :");
     checkError("=", "<string>:1.1: Invalid character: =");
     checkError("subtring", "<string>:1.1: Invalid character: s");
     checkError("foo", "<string>:1.1: Invalid character: f");
@@ -476,6 +559,12 @@ TEST_F(EvalContextTest, scanParseErrors) {
     checkError("0x", "<string>:1.1: syntax error, unexpected integer");
     checkError("0abc",
                "<string>:1.1: syntax error, unexpected integer");
+    checkError("10.0.1", "<string>:1.1-2: syntax error, unexpected integer");
+    checkError("10.256.0.1",
+               "<string>:1.1-10: Failed to convert 10.256.0.1 to "
+               "an IP address.");
+    checkError(":::",
+               "<string>:1.1-3: Failed to convert ::: to an IP address.");
     checkError("===", "<string>:1.1-2: syntax error, unexpected ==");
     checkError("option[-1].text",
                "<string>:1.8-9: Option code has invalid "

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

@@ -283,6 +283,51 @@ TEST_F(TokenTest, hexstring6) {
     EXPECT_EQ("", values_.top());
 }
 
+// This test checks that a TokenIpAddress, representing an IP address as
+// a constant string, can be used in Pkt4/Pkt6 evaluation.
+// (The actual packet is not used)
+TEST_F(TokenTest, ipaddress6) {
+    TokenPtr bad4;
+    TokenPtr bad6;
+    TokenPtr ip4;
+    TokenPtr ip6;
+
+    // Bad IP addresses
+    ASSERT_NO_THROW(bad4.reset(new TokenIpAddress("10.0.0.0.1")));
+    ASSERT_NO_THROW(bad6.reset(new TokenIpAddress(":::")));
+
+    // IP addresses
+    ASSERT_NO_THROW(ip4.reset(new TokenIpAddress("10.0.0.1")));
+    ASSERT_NO_THROW(ip6.reset(new TokenIpAddress("2001:db8::1")));
+
+    // Make sure that tokens can be evaluated without exceptions.
+    ASSERT_NO_THROW(ip4->evaluate(*pkt4_, values_));
+    ASSERT_NO_THROW(ip6->evaluate(*pkt6_, values_));
+    ASSERT_NO_THROW(bad4->evaluate(*pkt4_, values_));
+    ASSERT_NO_THROW(bad6->evaluate(*pkt6_, values_));
+
+    // Check that the evaluation put its value on the values stack.
+    ASSERT_EQ(4, values_.size());
+
+    // Check bad addresses (they pushed '' on the value stack)
+    EXPECT_EQ(0, values_.top().size());
+    values_.pop();
+    EXPECT_EQ(0, values_.top().size());
+    values_.pop();
+
+    // Check IPv6 address
+    uint8_t expected6[] = { 0x20, 1, 0xd, 0xb8, 0, 0, 0, 0,
+                            0, 0, 0, 0, 0, 0, 0, 1 };
+    EXPECT_EQ(16, values_.top().size());
+    EXPECT_EQ(0, memcmp(expected6, &values_.top()[0], 16));
+    values_.pop();
+
+    // Check IPv4 address
+    uint8_t expected4[] = { 10, 0, 0, 1 };
+    EXPECT_EQ(4, values_.top().size());
+    EXPECT_EQ(0, memcmp(expected4, &values_.top()[0], 4));
+}
+
 // This test checks if a token representing an option value is able to extract
 // the option from an IPv4 packet and properly store the option's value.
 TEST_F(TokenTest, optionString4) {

+ 28 - 6
src/lib/eval/token.cc

@@ -7,6 +7,7 @@
 #include <eval/token.h>
 #include <eval/eval_log.h>
 #include <util/encode/hex.h>
+#include <asiolink/io_address.h>
 #include <boost/lexical_cast.hpp>
 #include <cstring>
 #include <string>
@@ -54,6 +55,27 @@ TokenHexString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
     values.push(value_);
 }
 
+TokenIpAddress::TokenIpAddress(const string& addr) : value_("") {
+    // Transform IP address into binary format
+    vector<uint8_t> binary;
+    try {
+        asiolink::IOAddress ip(addr);
+        binary = ip.toBytes();
+    } catch (...) {
+        return;
+    }
+
+    // Convert to a string (note that binary.size() is 4 or 16, so not 0)
+    value_.resize(binary.size());
+    memmove(&value_[0], &binary[0], binary.size());
+}
+
+void
+TokenIpAddress::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
+    // Literals only push, nothing to pop
+    values.push(value_);
+}
+
 OptionPtr
 TokenOption::getOption(const Pkt& pkt) {
     return (pkt.getOption(option_code_));
@@ -224,9 +246,9 @@ TokenNot::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
     bool val = toBool(op);
 
     if (!val) {
-	values.push("true");
+        values.push("true");
     } else {
-	values.push("false");
+        values.push("false");
     }
 }
 
@@ -246,9 +268,9 @@ TokenAnd::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
     bool val2 = toBool(op2);
 
     if (val1 && val2) {
-	values.push("true");
+        values.push("true");
     } else {
-	values.push("false");
+        values.push("false");
     }
 }
 
@@ -268,8 +290,8 @@ TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
     bool val2 = toBool(op2);
 
     if (val1 || val2) {
-	values.push("true");
+        values.push("true");
     } else {
-	values.push("false");
+        values.push("false");
     }
 }

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

@@ -147,6 +147,29 @@ protected:
     std::string value_; ///< Constant value
 };
 
+/// @brief Token representing an IP address as a constant string
+///
+/// This token holds value of an IP address as a constant string,
+/// for instance 10.0.0.1 is 0x10000001
+class TokenIpAddress : public Token {
+public:
+    /// Value is set during token construction.
+    ///
+    /// @param addr IP address to be represented as a constant string
+    TokenIpAddress(const std::string& addr);
+
+    /// @brief Token evaluation (puts value of the constant string on
+    /// the stack after decoding)
+    ///
+    /// @param pkt (ignored)
+    /// @param values (represented IP address will be pushed here)
+    void evaluate(const Pkt& pkt, ValueStack& values);
+
+protected:
+    ///< Constant value (empty string if the IP address cannot be converted)
+    std::string value_;
+};
+
 /// @brief Token that represents a value of an option
 ///
 /// This represents a reference to a given option, e.g. in the expression