Browse Source

[master] Merge branch 'trac5187' (path restrictions removed in config-write)

Tomek Mrugalski 8 years ago
parent
commit
a30ffcc67c
42 changed files with 5796 additions and 5177 deletions
  1. 10 1
      doc/examples/agent/simple.json
  2. 61 36
      doc/examples/ddns/sample1.json
  3. 10 1
      doc/examples/kea4/advanced.json
  4. 10 1
      doc/examples/kea6/advanced.json
  5. 4 5
      doc/guide/ctrl-channel.xml
  6. 686 622
      src/bin/agent/agent_lexer.cc
  7. 27 0
      src/bin/agent/agent_lexer.ll
  8. 268 234
      src/bin/agent/agent_parser.cc
  9. 75 41
      src/bin/agent/agent_parser.h
  10. 28 4
      src/bin/agent/agent_parser.yy
  11. 1 1
      src/bin/agent/location.hh
  12. 1 1
      src/bin/agent/position.hh
  13. 1 1
      src/bin/agent/stack.hh
  14. 754 682
      src/bin/d2/d2_lexer.cc
  15. 27 0
      src/bin/d2/d2_lexer.ll
  16. 359 326
      src/bin/d2/d2_parser.cc
  17. 76 43
      src/bin/d2/d2_parser.h
  18. 28 4
      src/bin/d2/d2_parser.yy
  19. 1 1
      src/bin/d2/location.hh
  20. 1 1
      src/bin/d2/position.hh
  21. 1 1
      src/bin/d2/stack.hh
  22. 3 22
      src/bin/dhcp4/ctrl_dhcp4_srv.cc
  23. 802 759
      src/bin/dhcp4/dhcp4_lexer.cc
  24. 27 0
      src/bin/dhcp4/dhcp4_lexer.ll
  25. 750 710
      src/bin/dhcp4/dhcp4_parser.cc
  26. 96 63
      src/bin/dhcp4/dhcp4_parser.h
  27. 28 4
      src/bin/dhcp4/dhcp4_parser.yy
  28. 1 1
      src/bin/dhcp4/location.hh
  29. 1 1
      src/bin/dhcp4/position.hh
  30. 1 1
      src/bin/dhcp4/stack.hh
  31. 0 36
      src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
  32. 3 22
      src/bin/dhcp6/ctrl_dhcp6_srv.cc
  33. 711 669
      src/bin/dhcp6/dhcp6_lexer.cc
  34. 28 0
      src/bin/dhcp6/dhcp6_lexer.ll
  35. 787 756
      src/bin/dhcp6/dhcp6_parser.cc
  36. 98 64
      src/bin/dhcp6/dhcp6_parser.h
  37. 28 4
      src/bin/dhcp6/dhcp6_parser.yy
  38. 1 1
      src/bin/dhcp6/location.hh
  39. 1 1
      src/bin/dhcp6/position.hh
  40. 1 1
      src/bin/dhcp6/stack.hh
  41. 0 36
      src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
  42. 0 20
      src/lib/process/d_controller.cc

+ 10 - 1
doc/examples/agent/simple.json

@@ -69,7 +69,16 @@
 		"name": "kea-ctrl-agent",
 		"output_options": [
 		    {
-			"output": "/var/log/kea-ctrl-agent.log"
+			"output": "/var/log/kea-ctrl-agent.log",
+                        // Several additional parameters are possible in addition
+                        // to the typical output. Flush determines whether logger
+                        // flushes output to a file. Maxsize determines maximum
+                        // filesize before the file is being rotated. maxver
+                        // specifies the maximum number of rotated files being
+                        // kept.
+                        "flush": true,
+                        "maxsize": 204800,
+                        "maxver": 4
 		    }
 		],
 		"severity": "INFO",

+ 61 - 36
doc/examples/ddns/sample1.json

@@ -1,40 +1,40 @@
-# This is an example configuration file for D2, Kea's DHCP-DDNS processor.
-# It supports updating two Forward DNS zones "four.example.com" and
-# "six.example.com"; and one Reverse DNS zone, "2.0.192.in-addr.arpa."
+// This is an example configuration file for D2, Kea's DHCP-DDNS processor.
+// It supports updating two Forward DNS zones "four.example.com" and
+// "six.example.com"; and one Reverse DNS zone, "2.0.192.in-addr.arpa."
 
 {
-# ------------------ DHCP-DDNS ---------------------
-#
+// ------------------ DHCP-DDNS ---------------------
+//
 "DhcpDdns":
 {
 
-# --------------  Global Parameters ----------------
-#
-#   D2 will listen for update requests for Kea DHCP servers at 172.16.1.10
-#   on port 53001.  Maximum time to we will  wait for a DNS server to
-#   respond to us is 1000 ms.
+// --------------  Global Parameters ----------------
+//
+//   D2 will listen for update requests for Kea DHCP servers at 172.16.1.10
+//   on port 53001.  Maximum time to we will  wait for a DNS server to
+//   respond to us is 1000 ms.
 
     "ip-address": "172.16.1.10",
     "port": 53001,
     "dns-server-timeout" : 1000,
 
-#
-# ----------------- Forward DDNS  ------------------
-#
-#   1. Zone - "four.example.com.
-#      It uses TSIG, key name is "d2.md5.key"
-#      It is served by one DNS server which listens for DDNS requests at
-#      172.16.1.1 on the default port 53 (standard  DNS port)
-#
-#   2. Zone - "six.example.com."
-#      It does not use TSIG.
-#      It is server by one DNS server at "2001:db8:1::10" on port 7802
+//
+// ----------------- Forward DDNS  ------------------
+//
+//   1. Zone - "four.example.com.
+//      It uses TSIG, key name is "d2.md5.key"
+//      It is served by one DNS server which listens for DDNS requests at
+//      172.16.1.1 on the default port 53 (standard  DNS port)
+//
+//   2. Zone - "six.example.com."
+//      It does not use TSIG.
+//      It is server by one DNS server at "2001:db8:1::10" on port 7802
 
     "forward-ddns":
     {
         "ddns-domains":
         [
-#           DdnsDomain for zone "four.example.com."
+//           DdnsDomain for zone "four.example.com."
             {
                 "name": "four.example.com.",
                 "key-name": "d2.md5.key",
@@ -46,7 +46,7 @@
                 ]
             },
 
-#           DdnsDomain for zone "six.example.com."
+//           DdnsDomain for zone "six.example.com."
             {
                 "name": "six.example.com.",
                 "dns-servers":
@@ -60,13 +60,12 @@
         ]
     },
 
-#
-# ----------------- Reverse DDNS  ------------------
-#
-# We will update Reverse DNS for one zone "2.0.192.in-addr-arpa". It
-# uses TSIG with key "d2.sha1.key" and is served by two DNS servers:
-# one listening at "172.16.1.1" on 53001 and the other at "192.168.2.10".
-#
+// ----------------- Reverse DDNS  ------------------
+//
+// We will update Reverse DNS for one zone "2.0.192.in-addr-arpa". It
+// uses TSIG with key "d2.sha1.key" and is served by two DNS servers:
+// one listening at "172.16.1.1" on 53001 and the other at "192.168.2.10".
+//
     "reverse-ddns":
     {
         "ddns-domains":
@@ -88,12 +87,11 @@
         ]
     },
 
-#
-# ------------------ TSIG keys ---------------------
-#
-#   Each key has a name, an algorithm (HMAC-MD5, HMAC-SHA1, HMAC-SHA224...)
-#   and a base-64 encoded shared secret.
-#
+// ------------------ TSIG keys ---------------------
+//
+//   Each key has a name, an algorithm (HMAC-MD5, HMAC-SHA1, HMAC-SHA224...)
+//   and a base-64 encoded shared secret.
+//
     "tsig-keys":
     [
         {
@@ -113,6 +111,33 @@
             "secret": "/4wklkm04jeH4anx2MKGJLcya+ZLHldL5d6mK+4q6UXQP7KJ9mS2QG29hh0SJR4LA0ikxNJTUMvir42gLx6fGQ=="
         }
     ]
+},
+
+// The following configures logging. It assumes that messages with at least
+// informational level (info, warn, error and fatal) should be logged to stdout.
+"Logging": {
+    "loggers": [
+        {
+            "name": "kea-dhcp-ddns",
+            "output_options": [
+                {
+                    "output": "stdout",
+                    // Several additional parameters are possible in addition
+                    // to the typical output. Flush determines whether logger
+                    // flushes output to a file. Maxsize determines maximum
+                    // filesize before the file is being rotated. maxver
+                    // specifies the maximum number of rotated files being
+                    // kept.
+                    "flush": true,
+                    "maxsize": 204800,
+                    "maxver": 4
+                }
+            ],
+            "debuglevel": 0,
+            "severity": "INFO"
+        }
+    ]
 }
+    
 
 }

+ 10 - 1
doc/examples/kea4/advanced.json

@@ -111,7 +111,16 @@
             "name": "kea-dhcp4",
               "output_options": [
                   {
-                      "output": "stdout"
+                      "output": "stdout",
+                      // Several additional parameters are possible in addition
+                      // to the typical output. Flush determines whether logger
+                      // flushes output to a file. Maxsize determines maximum
+                      // filesize before the file is being rotated. maxver
+                      // specifies the maximum number of rotated files being
+                      // kept.
+                      "flush": true,
+                      "maxsize": 204800,
+                      "maxver": 4
                   }
               ],
               "severity": "INFO"

+ 10 - 1
doc/examples/kea6/advanced.json

@@ -116,7 +116,16 @@
             "name": "kea-dhcp6",
             "output_options": [
                 {
-                    "output": "stdout"
+                    "output": "stdout",
+                    // Several additional parameters are possible in addition
+                    // to the typical output. Flush determines whether logger
+                    // flushes output to a file. Maxsize determines maximum
+                    // filesize before the file is being rotated. maxver
+                    // specifies the maximum number of rotated files being
+                    // kept.
+                    "flush": true,
+                    "maxsize": 204800,
+                    "maxver": 4
                 }
             ],
             "debuglevel": 0,

+ 4 - 5
doc/guide/ctrl-channel.xml

@@ -363,16 +363,15 @@ $ curl -X POST -H "Content-Type: application/json" -d '{ "command": "config-get"
         to write its current configuration to a file on disk. It takes one
         optional argument called <emphasis>filename</emphasis> that specifies
         the name of the file to write configuration to. If not specified, the
-        name used when starting Kea (passed as -c argument) will be used. Note
-        that the filename specified must not contain .. or backslashes. Kea
-        should be able to write its files only in the directory it is running
-        and any attempts to step out of that directory will be rejected.</para>
+        name used when starting Kea (passed as -c argument) will be
+        used. If relative path is specified, Kea will write its files
+        only in the directory it is running.</para>
         <para>
           An example command invocation looks like this:
 <screen>
 {
     "command": "config-write",
-    "parameters": {
+    "arguments": {
         "filename": "config-modified-2017-03-15.json"
     }
 }

File diff suppressed because it is too large
+ 686 - 622
src/bin/agent/agent_lexer.cc


+ 27 - 0
src/bin/agent/agent_lexer.ll

@@ -329,6 +329,33 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"flush\" {
+    switch(driver.ctx_) {
+    case ParserContext::OUTPUT_OPTIONS:
+        return AgentParser::make_FLUSH(driver.loc_);
+    default:
+        return AgentParser::make_STRING("flush", driver.loc_);
+    }
+}
+
+\"maxsize\" {
+    switch(driver.ctx_) {
+    case ParserContext::OUTPUT_OPTIONS:
+        return AgentParser::make_MAXSIZE(driver.loc_);
+    default:
+        return AgentParser::make_STRING("maxsize", driver.loc_);
+    }
+}
+
+\"maxver\" {
+    switch(driver.ctx_) {
+    case ParserContext::OUTPUT_OPTIONS:
+        return AgentParser::make_MAXVER(driver.loc_);
+    default:
+        return AgentParser::make_STRING("maxver", driver.loc_);
+    }
+}
+
 \"debuglevel\" {
     switch(driver.ctx_) {
     case ParserContext::LOGGERS:

File diff suppressed because it is too large
+ 268 - 234
src/bin/agent/agent_parser.cc


+ 75 - 41
src/bin/agent/agent_parser.h

@@ -368,16 +368,19 @@ namespace isc { namespace agent {
         TOKEN_OUTPUT = 282,
         TOKEN_DEBUGLEVEL = 283,
         TOKEN_SEVERITY = 284,
-        TOKEN_DHCP4 = 285,
-        TOKEN_DHCP6 = 286,
-        TOKEN_DHCPDDNS = 287,
-        TOKEN_START_JSON = 288,
-        TOKEN_START_AGENT = 289,
-        TOKEN_START_SUB_AGENT = 290,
-        TOKEN_STRING = 291,
-        TOKEN_INTEGER = 292,
-        TOKEN_FLOAT = 293,
-        TOKEN_BOOLEAN = 294
+        TOKEN_FLUSH = 285,
+        TOKEN_MAXSIZE = 286,
+        TOKEN_MAXVER = 287,
+        TOKEN_DHCP4 = 288,
+        TOKEN_DHCP6 = 289,
+        TOKEN_DHCPDDNS = 290,
+        TOKEN_START_JSON = 291,
+        TOKEN_START_AGENT = 292,
+        TOKEN_START_SUB_AGENT = 293,
+        TOKEN_STRING = 294,
+        TOKEN_INTEGER = 295,
+        TOKEN_FLOAT = 296,
+        TOKEN_BOOLEAN = 297
       };
     };
 
@@ -606,6 +609,18 @@ namespace isc { namespace agent {
 
     static inline
     symbol_type
+    make_FLUSH (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXSIZE (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXVER (const location_type& l);
+
+    static inline
+    symbol_type
     make_DHCP4 (const location_type& l);
 
     static inline
@@ -711,7 +726,7 @@ namespace isc { namespace agent {
     // Tables.
   // YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
   // STATE-NUM.
-  static const signed char yypact_[];
+  static const short int yypact_[];
 
   // YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
   // Performed when YYTABLE does not specify something else to do.  Zero
@@ -850,11 +865,11 @@ namespace isc { namespace agent {
     {
       yyeof_ = 0,
       yylast_ = 172,     ///< Last index in yytable_.
-      yynnts_ = 88,  ///< Number of nonterminal symbols.
+      yynnts_ = 92,  ///< Number of nonterminal symbols.
       yyfinal_ = 8, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 40  ///< Number of tokens.
+      yyntokens_ = 43  ///< Number of tokens.
     };
 
 
@@ -900,9 +915,9 @@ namespace isc { namespace agent {
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39
+      35,    36,    37,    38,    39,    40,    41,    42
     };
-    const unsigned int user_token_number_max_ = 294;
+    const unsigned int user_token_number_max_ = 297;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -935,24 +950,24 @@ namespace isc { namespace agent {
   {
       switch (other.type_get ())
     {
-      case 48: // value
-      case 97: // socket_type_value
+      case 51: // value
+      case 100: // socket_type_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 39: // "boolean"
+      case 42: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 38: // "floating point"
+      case 41: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 37: // "integer"
+      case 40: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 36: // "constant string"
+      case 39: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -973,24 +988,24 @@ namespace isc { namespace agent {
     (void) v;
       switch (this->type_get ())
     {
-      case 48: // value
-      case 97: // socket_type_value
+      case 51: // value
+      case 100: // socket_type_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 39: // "boolean"
+      case 42: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 38: // "floating point"
+      case 41: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 37: // "integer"
+      case 40: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 36: // "constant string"
+      case 39: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1070,24 +1085,24 @@ namespace isc { namespace agent {
     // Type destructor.
     switch (yytype)
     {
-      case 48: // value
-      case 97: // socket_type_value
+      case 51: // value
+      case 100: // socket_type_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 39: // "boolean"
+      case 42: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 38: // "floating point"
+      case 41: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 37: // "integer"
+      case 40: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 36: // "constant string"
+      case 39: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1114,24 +1129,24 @@ namespace isc { namespace agent {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 48: // value
-      case 97: // socket_type_value
+      case 51: // value
+      case 100: // socket_type_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 39: // "boolean"
+      case 42: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 38: // "floating point"
+      case 41: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 37: // "integer"
+      case 40: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 36: // "constant string"
+      case 39: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1193,7 +1208,8 @@ namespace isc { namespace agent {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1367,6 +1383,24 @@ namespace isc { namespace agent {
   }
 
   AgentParser::symbol_type
+  AgentParser::make_FLUSH (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_FLUSH, l);
+  }
+
+  AgentParser::symbol_type
+  AgentParser::make_MAXSIZE (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXSIZE, l);
+  }
+
+  AgentParser::symbol_type
+  AgentParser::make_MAXVER (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXVER, l);
+  }
+
+  AgentParser::symbol_type
   AgentParser::make_DHCP4 (const location_type& l)
   {
     return symbol_type (token::TOKEN_DHCP4, l);
@@ -1429,7 +1463,7 @@ namespace isc { namespace agent {
 
 #line 14 "agent_parser.yy" // lalr1.cc:377
 } } // isc::agent
-#line 1433 "agent_parser.h" // lalr1.cc:377
+#line 1467 "agent_parser.h" // lalr1.cc:377
 
 
 

+ 28 - 4
src/bin/agent/agent_parser.yy

@@ -71,6 +71,9 @@ using namespace std;
   OUTPUT "output"
   DEBUGLEVEL "debuglevel"
   SEVERITY "severity"
+  FLUSH "flush"
+  MAXSIZE "maxsize"
+  MAXVER "maxver"
 
   DHCP4 "Dhcp4"
   DHCP6 "Dhcp6"
@@ -549,15 +552,21 @@ output_entry: LCURLY_BRACKET {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
-} output_params RCURLY_BRACKET {
+} output_params_list RCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-output_params: output_param
-             | output_params COMMA output_param
+output_params_list: output_params
+             | output_params_list COMMA output_params
              ;
 
-output_param: OUTPUT {
+output_params: output
+             | flush
+             | maxsize
+             | maxver
+             ;
+
+output: OUTPUT {
     ctx.enter(ctx.NO_KEYWORDS);
 } COLON STRING {
     ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
@@ -565,6 +574,21 @@ output_param: OUTPUT {
     ctx.leave();
 };
 
+flush: FLUSH COLON BOOLEAN {
+    ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("flush", flush);
+}
+
+maxsize: MAXSIZE COLON INTEGER {
+    ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxsize", maxsize);
+}
+
+maxver: MAXVER COLON INTEGER {
+    ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxver", maxver);
+}
+
 %%
 
 void

+ 1 - 1
src/bin/agent/location.hh

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

+ 1 - 1
src/bin/agent/position.hh

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

+ 1 - 1
src/bin/agent/stack.hh

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

File diff suppressed because it is too large
+ 754 - 682
src/bin/d2/d2_lexer.cc


+ 27 - 0
src/bin/d2/d2_lexer.ll

@@ -389,6 +389,33 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"flush\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
+        return isc::d2::D2Parser::make_FLUSH(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("flush", driver.loc_);
+    }
+}
+
+\"maxsize\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
+        return isc::d2::D2Parser::make_MAXSIZE(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("maxsize", driver.loc_);
+    }
+}
+
+\"maxver\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
+        return isc::d2::D2Parser::make_MAXVER(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("maxver", driver.loc_);
+    }
+}
+
 \"name\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::LOGGERS:

File diff suppressed because it is too large
+ 359 - 326
src/bin/d2/d2_parser.cc


+ 76 - 43
src/bin/d2/d2_parser.h

@@ -377,19 +377,22 @@ namespace isc { namespace d2 {
         TOKEN_OUTPUT = 290,
         TOKEN_DEBUGLEVEL = 291,
         TOKEN_SEVERITY = 292,
-        TOKEN_TOPLEVEL_JSON = 293,
-        TOKEN_TOPLEVEL_DHCPDDNS = 294,
-        TOKEN_SUB_DHCPDDNS = 295,
-        TOKEN_SUB_TSIG_KEY = 296,
-        TOKEN_SUB_TSIG_KEYS = 297,
-        TOKEN_SUB_DDNS_DOMAIN = 298,
-        TOKEN_SUB_DDNS_DOMAINS = 299,
-        TOKEN_SUB_DNS_SERVER = 300,
-        TOKEN_SUB_DNS_SERVERS = 301,
-        TOKEN_STRING = 302,
-        TOKEN_INTEGER = 303,
-        TOKEN_FLOAT = 304,
-        TOKEN_BOOLEAN = 305
+        TOKEN_FLUSH = 293,
+        TOKEN_MAXSIZE = 294,
+        TOKEN_MAXVER = 295,
+        TOKEN_TOPLEVEL_JSON = 296,
+        TOKEN_TOPLEVEL_DHCPDDNS = 297,
+        TOKEN_SUB_DHCPDDNS = 298,
+        TOKEN_SUB_TSIG_KEY = 299,
+        TOKEN_SUB_TSIG_KEYS = 300,
+        TOKEN_SUB_DDNS_DOMAIN = 301,
+        TOKEN_SUB_DDNS_DOMAINS = 302,
+        TOKEN_SUB_DNS_SERVER = 303,
+        TOKEN_SUB_DNS_SERVERS = 304,
+        TOKEN_STRING = 305,
+        TOKEN_INTEGER = 306,
+        TOKEN_FLOAT = 307,
+        TOKEN_BOOLEAN = 308
       };
     };
 
@@ -650,6 +653,18 @@ namespace isc { namespace d2 {
 
     static inline
     symbol_type
+    make_FLUSH (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXSIZE (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXVER (const location_type& l);
+
+    static inline
+    symbol_type
     make_TOPLEVEL_JSON (const location_type& l);
 
     static inline
@@ -906,11 +921,11 @@ namespace isc { namespace d2 {
     {
       yyeof_ = 0,
       yylast_ = 247,     ///< Last index in yytable_.
-      yynnts_ = 127,  ///< Number of nonterminal symbols.
+      yynnts_ = 131,  ///< Number of nonterminal symbols.
       yyfinal_ = 20, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 51  ///< Number of tokens.
+      yyntokens_ = 54  ///< Number of tokens.
     };
 
 
@@ -957,9 +972,9 @@ namespace isc { namespace d2 {
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50
+      45,    46,    47,    48,    49,    50,    51,    52,    53
     };
-    const unsigned int user_token_number_max_ = 305;
+    const unsigned int user_token_number_max_ = 308;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -992,24 +1007,24 @@ namespace isc { namespace d2 {
   {
       switch (other.type_get ())
     {
-      case 62: // value
-      case 89: // ncr_protocol_value
+      case 65: // value
+      case 92: // ncr_protocol_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 50: // "boolean"
+      case 53: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 49: // "floating point"
+      case 52: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 48: // "integer"
+      case 51: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 47: // "constant string"
+      case 50: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -1030,24 +1045,24 @@ namespace isc { namespace d2 {
     (void) v;
       switch (this->type_get ())
     {
-      case 62: // value
-      case 89: // ncr_protocol_value
+      case 65: // value
+      case 92: // ncr_protocol_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 50: // "boolean"
+      case 53: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 49: // "floating point"
+      case 52: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 48: // "integer"
+      case 51: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 47: // "constant string"
+      case 50: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1127,24 +1142,24 @@ namespace isc { namespace d2 {
     // Type destructor.
     switch (yytype)
     {
-      case 62: // value
-      case 89: // ncr_protocol_value
+      case 65: // value
+      case 92: // ncr_protocol_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 50: // "boolean"
+      case 53: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 49: // "floating point"
+      case 52: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 48: // "integer"
+      case 51: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 47: // "constant string"
+      case 50: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1171,24 +1186,24 @@ namespace isc { namespace d2 {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 62: // value
-      case 89: // ncr_protocol_value
+      case 65: // value
+      case 92: // ncr_protocol_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 50: // "boolean"
+      case 53: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 49: // "floating point"
+      case 52: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 48: // "integer"
+      case 51: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 47: // "constant string"
+      case 50: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1252,7 +1267,7 @@ namespace isc { namespace d2 {
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
      295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305
+     305,   306,   307,   308
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1474,6 +1489,24 @@ namespace isc { namespace d2 {
   }
 
   D2Parser::symbol_type
+  D2Parser::make_FLUSH (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_FLUSH, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_MAXSIZE (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXSIZE, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_MAXVER (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXVER, l);
+  }
+
+  D2Parser::symbol_type
   D2Parser::make_TOPLEVEL_JSON (const location_type& l)
   {
     return symbol_type (token::TOKEN_TOPLEVEL_JSON, l);
@@ -1554,7 +1587,7 @@ namespace isc { namespace d2 {
 
 #line 14 "d2_parser.yy" // lalr1.cc:377
 } } // isc::d2
-#line 1558 "d2_parser.h" // lalr1.cc:377
+#line 1591 "d2_parser.h" // lalr1.cc:377
 
 
 

+ 28 - 4
src/bin/d2/d2_parser.yy

@@ -79,6 +79,9 @@ using namespace std;
   OUTPUT "output"
   DEBUGLEVEL "debuglevel"
   SEVERITY "severity"
+  FLUSH "flush"
+  MAXSIZE "maxsize"
+  MAXVER "maxver"
 
   // Not real tokens, just a way to signal what the parser is expected to
   // parse.
@@ -711,15 +714,21 @@ output_entry: LCURLY_BRACKET {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
-} output_params RCURLY_BRACKET {
+} output_params_list RCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-output_params: output_param
-             | output_params COMMA output_param
+output_params_list: output_params
+             | output_params_list COMMA output_params
              ;
 
-output_param: OUTPUT {
+output_params: output
+             | flush
+             | maxsize
+             | maxver
+             ;
+
+output: OUTPUT {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
@@ -727,6 +736,21 @@ output_param: OUTPUT {
     ctx.leave();
 };
 
+flush: FLUSH COLON BOOLEAN {
+    ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("flush", flush);
+}
+
+maxsize: MAXSIZE COLON INTEGER {
+    ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxsize", maxsize);
+}
+
+maxver: MAXVER COLON INTEGER {
+    ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxver", maxver);
+}
+
 %%
 
 void

+ 1 - 1
src/bin/d2/location.hh

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

+ 1 - 1
src/bin/d2/position.hh

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

+ 1 - 1
src/bin/d2/stack.hh

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

+ 3 - 22
src/bin/dhcp4/ctrl_dhcp4_srv.cc

@@ -246,30 +246,11 @@ ControlledDhcpv4Srv::commandConfigWriteHandler(const string&,
     if (filename.empty()) {
         // filename parameter was not specified, so let's use whatever we remember
         filename = getConfigFile();
-        if (filename.empty()) {
-            return (createAnswer(CONTROL_RESULT_ERROR, "Unable to determine filename."
-                                 "Please specify filename explicitly."));
-        }
     }
 
-    // Now do the sanity checks on the filename
-    if (filename.find("..") != string::npos) {
-        // Trying to escape the directory.. nope.
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Using '..' in filename is not allowed."));
-    }
-
-    if (filename.find("\\") != string::npos) {
-        // Trying to inject escapes (possibly to inject quotes and something
-        // nasty afterward)
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Using \\ in filename is not allowed."));
-    }
-
-    if (filename[0] == '/') {
-        // Absolute paths are not allowed.
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Absolute path in filename is not allowed."));
+    if (filename.empty()) {
+        return (createAnswer(CONTROL_RESULT_ERROR, "Unable to determine filename."
+                             "Please specify filename explicitly."));
     }
 
     // Ok, it's time to write the file.

File diff suppressed because it is too large
+ 802 - 759
src/bin/dhcp4/dhcp4_lexer.cc


+ 27 - 0
src/bin/dhcp4/dhcp4_lexer.ll

@@ -630,6 +630,33 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"flush\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::OUTPUT_OPTIONS:
+        return isc::dhcp::Dhcp4Parser::make_FLUSH(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("flush", driver.loc_);
+    }
+}
+
+\"maxsize\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::OUTPUT_OPTIONS:
+        return isc::dhcp::Dhcp4Parser::make_MAXSIZE(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("maxsize", driver.loc_);
+    }
+}
+
+\"maxver\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::OUTPUT_OPTIONS:
+        return isc::dhcp::Dhcp4Parser::make_MAXVER(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("maxver", driver.loc_);
+    }
+}
+
 \"severity\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser4Context::LOGGERS:

File diff suppressed because it is too large
+ 750 - 710
src/bin/dhcp4/dhcp4_parser.cc


+ 96 - 63
src/bin/dhcp4/dhcp4_parser.h

@@ -462,23 +462,26 @@ namespace isc { namespace dhcp {
         TOKEN_OUTPUT = 371,
         TOKEN_DEBUGLEVEL = 372,
         TOKEN_SEVERITY = 373,
-        TOKEN_DHCP6 = 374,
-        TOKEN_DHCPDDNS = 375,
-        TOKEN_TOPLEVEL_JSON = 376,
-        TOKEN_TOPLEVEL_DHCP4 = 377,
-        TOKEN_SUB_DHCP4 = 378,
-        TOKEN_SUB_INTERFACES4 = 379,
-        TOKEN_SUB_SUBNET4 = 380,
-        TOKEN_SUB_POOL4 = 381,
-        TOKEN_SUB_RESERVATION = 382,
-        TOKEN_SUB_OPTION_DEF = 383,
-        TOKEN_SUB_OPTION_DATA = 384,
-        TOKEN_SUB_HOOKS_LIBRARY = 385,
-        TOKEN_SUB_DHCP_DDNS = 386,
-        TOKEN_STRING = 387,
-        TOKEN_INTEGER = 388,
-        TOKEN_FLOAT = 389,
-        TOKEN_BOOLEAN = 390
+        TOKEN_FLUSH = 374,
+        TOKEN_MAXSIZE = 375,
+        TOKEN_MAXVER = 376,
+        TOKEN_DHCP6 = 377,
+        TOKEN_DHCPDDNS = 378,
+        TOKEN_TOPLEVEL_JSON = 379,
+        TOKEN_TOPLEVEL_DHCP4 = 380,
+        TOKEN_SUB_DHCP4 = 381,
+        TOKEN_SUB_INTERFACES4 = 382,
+        TOKEN_SUB_SUBNET4 = 383,
+        TOKEN_SUB_POOL4 = 384,
+        TOKEN_SUB_RESERVATION = 385,
+        TOKEN_SUB_OPTION_DEF = 386,
+        TOKEN_SUB_OPTION_DATA = 387,
+        TOKEN_SUB_HOOKS_LIBRARY = 388,
+        TOKEN_SUB_DHCP_DDNS = 389,
+        TOKEN_STRING = 390,
+        TOKEN_INTEGER = 391,
+        TOKEN_FLOAT = 392,
+        TOKEN_BOOLEAN = 393
       };
     };
 
@@ -1063,6 +1066,18 @@ namespace isc { namespace dhcp {
 
     static inline
     symbol_type
+    make_FLUSH (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXSIZE (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXVER (const location_type& l);
+
+    static inline
+    symbol_type
     make_DHCP6 (const location_type& l);
 
     static inline
@@ -1335,11 +1350,11 @@ namespace isc { namespace dhcp {
     {
       yyeof_ = 0,
       yylast_ = 736,     ///< Last index in yytable_.
-      yynnts_ = 309,  ///< Number of nonterminal symbols.
+      yynnts_ = 313,  ///< Number of nonterminal symbols.
       yyfinal_ = 24, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 136  ///< Number of tokens.
+      yyntokens_ = 139  ///< Number of tokens.
     };
 
 
@@ -1395,9 +1410,9 @@ namespace isc { namespace dhcp {
      105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
      115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
      125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
-     135
+     135,   136,   137,   138
     };
-    const unsigned int user_token_number_max_ = 390;
+    const unsigned int user_token_number_max_ = 393;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -1430,28 +1445,28 @@ namespace isc { namespace dhcp {
   {
       switch (other.type_get ())
     {
-      case 149: // value
-      case 153: // map_value
-      case 191: // socket_type
-      case 200: // db_type
-      case 408: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 152: // value
+      case 156: // map_value
+      case 194: // socket_type
+      case 203: // db_type
+      case 411: // ncr_protocol_value
+      case 419: // replace_client_name_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 135: // "boolean"
+      case 138: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 134: // "floating point"
+      case 137: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 133: // "integer"
+      case 136: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 132: // "constant string"
+      case 135: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -1472,28 +1487,28 @@ namespace isc { namespace dhcp {
     (void) v;
       switch (this->type_get ())
     {
-      case 149: // value
-      case 153: // map_value
-      case 191: // socket_type
-      case 200: // db_type
-      case 408: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 152: // value
+      case 156: // map_value
+      case 194: // socket_type
+      case 203: // db_type
+      case 411: // ncr_protocol_value
+      case 419: // replace_client_name_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 135: // "boolean"
+      case 138: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 134: // "floating point"
+      case 137: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 133: // "integer"
+      case 136: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 132: // "constant string"
+      case 135: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1573,28 +1588,28 @@ namespace isc { namespace dhcp {
     // Type destructor.
     switch (yytype)
     {
-      case 149: // value
-      case 153: // map_value
-      case 191: // socket_type
-      case 200: // db_type
-      case 408: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 152: // value
+      case 156: // map_value
+      case 194: // socket_type
+      case 203: // db_type
+      case 411: // ncr_protocol_value
+      case 419: // replace_client_name_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 135: // "boolean"
+      case 138: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 134: // "floating point"
+      case 137: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 133: // "integer"
+      case 136: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 132: // "constant string"
+      case 135: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1621,28 +1636,28 @@ namespace isc { namespace dhcp {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 149: // value
-      case 153: // map_value
-      case 191: // socket_type
-      case 200: // db_type
-      case 408: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 152: // value
+      case 156: // map_value
+      case 194: // socket_type
+      case 203: // db_type
+      case 411: // ncr_protocol_value
+      case 419: // replace_client_name_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 135: // "boolean"
+      case 138: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 134: // "floating point"
+      case 137: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 133: // "integer"
+      case 136: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 132: // "constant string"
+      case 135: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1714,7 +1729,7 @@ namespace isc { namespace dhcp {
      355,   356,   357,   358,   359,   360,   361,   362,   363,   364,
      365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
      375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
-     385,   386,   387,   388,   389,   390
+     385,   386,   387,   388,   389,   390,   391,   392,   393
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -2422,6 +2437,24 @@ namespace isc { namespace dhcp {
   }
 
   Dhcp4Parser::symbol_type
+  Dhcp4Parser::make_FLUSH (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_FLUSH, l);
+  }
+
+  Dhcp4Parser::symbol_type
+  Dhcp4Parser::make_MAXSIZE (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXSIZE, l);
+  }
+
+  Dhcp4Parser::symbol_type
+  Dhcp4Parser::make_MAXVER (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXVER, l);
+  }
+
+  Dhcp4Parser::symbol_type
   Dhcp4Parser::make_DHCP6 (const location_type& l)
   {
     return symbol_type (token::TOKEN_DHCP6, l);
@@ -2526,7 +2559,7 @@ namespace isc { namespace dhcp {
 
 #line 14 "dhcp4_parser.yy" // lalr1.cc:377
 } } // isc::dhcp
-#line 2530 "dhcp4_parser.h" // lalr1.cc:377
+#line 2563 "dhcp4_parser.h" // lalr1.cc:377
 
 
 

+ 28 - 4
src/bin/dhcp4/dhcp4_parser.yy

@@ -173,6 +173,9 @@ using namespace std;
   OUTPUT "output"
   DEBUGLEVEL "debuglevel"
   SEVERITY "severity"
+  FLUSH "flush"
+  MAXSIZE "maxsize"
+  MAXVER "maxver"
 
   DHCP6 "Dhcp6"
   DHCPDDNS "DhcpDdns"
@@ -1731,15 +1734,21 @@ output_entry: LCURLY_BRACKET {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
-} output_params RCURLY_BRACKET {
+} output_params_list RCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-output_params: output_param
-             | output_params COMMA output_param
+output_params_list: output_params
+                  | output_params_list COMMA output_params
+                  ;
+
+output_params: output
+             | flush
+             | maxsize
+             | maxver
              ;
 
-output_param: OUTPUT {
+output: OUTPUT {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
@@ -1747,6 +1756,21 @@ output_param: OUTPUT {
     ctx.leave();
 };
 
+flush: FLUSH COLON BOOLEAN {
+    ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("flush", flush);
+}
+
+maxsize: MAXSIZE COLON INTEGER {
+    ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxsize", maxsize);
+}
+
+maxver: MAXVER COLON INTEGER {
+    ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxver", maxver);
+}
+
 %%
 
 void

+ 1 - 1
src/bin/dhcp4/location.hh

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

+ 1 - 1
src/bin/dhcp4/position.hh

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

+ 1 - 1
src/bin/dhcp4/stack.hh

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

+ 0 - 36
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc

@@ -965,42 +965,6 @@ TEST_F(CtrlChannelDhcpv4SrvTest, writeConfigFilename) {
     ::remove("test2.json");
 }
 
-// Tests if config-write rejects invalid filename (a one that tries to escape
-// the current directory).
-TEST_F(CtrlChannelDhcpv4SrvTest, writeConfigInvalidJailEscape) {
-    createUnixChannelServer();
-    std::string response;
-
-    sendUnixCommand("{ \"command\": \"config-write\", \"arguments\": "
-                    "{ \"filename\": \"../test3.json\" } }", response);
-    checkConfigWrite(response, CONTROL_RESULT_ERROR,
-                     "Using '..' in filename is not allowed.");
-}
-
-// Tests if config-write rejects invalid filename (absolute paths are not allowed)
-TEST_F(CtrlChannelDhcpv4SrvTest, writeConfigInvalidAbsPath) {
-    createUnixChannelServer();
-    std::string response;
-
-    sendUnixCommand("{ \"command\": \"config-write\", \"arguments\": "
-                    "{ \"filename\": \"/tmp/test4.json\" } }", response);
-    checkConfigWrite(response, CONTROL_RESULT_ERROR,
-                     "Absolute path in filename is not allowed.");
-}
-
-// Tests if config-write rejects invalid filename (one with backslashes, which may
-// lead to some other tricks)
-TEST_F(CtrlChannelDhcpv4SrvTest, writeConfigInvalidEscape) {
-    createUnixChannelServer();
-    std::string response;
-
-    // This will be converted to foo(single backslash)test5.json
-    sendUnixCommand("{ \"command\": \"config-write\", \"arguments\": "
-                    "{ \"filename\": \"foo\\\\test5.json\" } }", response);
-    checkConfigWrite(response, CONTROL_RESULT_ERROR,
-                     "Using \\ in filename is not allowed.");
-}
-
 // Tests if config-reload attempts to reload a file and reports that the
 // file is missing.
 TEST_F(CtrlChannelDhcpv4SrvTest, configReloadMissingFile) {

+ 3 - 22
src/bin/dhcp6/ctrl_dhcp6_srv.cc

@@ -249,30 +249,11 @@ ControlledDhcpv6Srv::commandConfigWriteHandler(const string&, ConstElementPtr ar
         // filename parameter was not specified, so let's use whatever we remember
         // from the command-line
         filename = getConfigFile();
-        if (filename.empty()) {
-            return (createAnswer(CONTROL_RESULT_ERROR, "Unable to determine filename."
-                                 "Please specify filename explicitly."));
-        }
     }
 
-    // Now do the sanity checks on the filename
-    if (filename.find("..") != string::npos) {
-        // Trying to escape the directory with .. nope.
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Using '..' in filename is not allowed."));
-    }
-
-    if (filename.find("\\") != string::npos) {
-        // Trying to inject escapes (possibly to inject quotes and something
-        // nasty afterward)
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Using \\ in filename is not allowed."));
-    }
-
-    if (filename[0] == '/') {
-        // Absolute paths are not allowed.
-        return (createAnswer(CONTROL_RESULT_ERROR,
-                             "Absolute path in filename is not allowed."));
+    if (filename.empty()) {
+        return (createAnswer(CONTROL_RESULT_ERROR, "Unable to determine filename."
+                             "Please specify filename explicitly."));
     }
 
     // Ok, it's time to write the file.

File diff suppressed because it is too large
+ 711 - 669
src/bin/dhcp6/dhcp6_lexer.cc


+ 28 - 0
src/bin/dhcp6/dhcp6_lexer.ll

@@ -897,6 +897,34 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"flush\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::OUTPUT_OPTIONS:
+        return isc::dhcp::Dhcp6Parser::make_FLUSH(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("flush", driver.loc_);
+    }
+}
+
+\"maxsize\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::OUTPUT_OPTIONS:
+        return isc::dhcp::Dhcp6Parser::make_MAXSIZE(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("maxsize", driver.loc_);
+    }
+}
+
+\"maxver\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::OUTPUT_OPTIONS:
+        return isc::dhcp::Dhcp6Parser::make_MAXVER(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("maxver", driver.loc_);
+    }
+}
+
+
 \"debuglevel\" {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::LOGGERS:

File diff suppressed because it is too large
+ 787 - 756
src/bin/dhcp6/dhcp6_parser.cc


+ 98 - 64
src/bin/dhcp6/dhcp6_parser.h

@@ -469,24 +469,27 @@ namespace isc { namespace dhcp {
         TOKEN_OUTPUT = 378,
         TOKEN_DEBUGLEVEL = 379,
         TOKEN_SEVERITY = 380,
-        TOKEN_DHCP4 = 381,
-        TOKEN_DHCPDDNS = 382,
-        TOKEN_TOPLEVEL_JSON = 383,
-        TOKEN_TOPLEVEL_DHCP6 = 384,
-        TOKEN_SUB_DHCP6 = 385,
-        TOKEN_SUB_INTERFACES6 = 386,
-        TOKEN_SUB_SUBNET6 = 387,
-        TOKEN_SUB_POOL6 = 388,
-        TOKEN_SUB_PD_POOL = 389,
-        TOKEN_SUB_RESERVATION = 390,
-        TOKEN_SUB_OPTION_DEF = 391,
-        TOKEN_SUB_OPTION_DATA = 392,
-        TOKEN_SUB_HOOKS_LIBRARY = 393,
-        TOKEN_SUB_DHCP_DDNS = 394,
-        TOKEN_STRING = 395,
-        TOKEN_INTEGER = 396,
-        TOKEN_FLOAT = 397,
-        TOKEN_BOOLEAN = 398
+        TOKEN_FLUSH = 381,
+        TOKEN_MAXSIZE = 382,
+        TOKEN_MAXVER = 383,
+        TOKEN_DHCP4 = 384,
+        TOKEN_DHCPDDNS = 385,
+        TOKEN_TOPLEVEL_JSON = 386,
+        TOKEN_TOPLEVEL_DHCP6 = 387,
+        TOKEN_SUB_DHCP6 = 388,
+        TOKEN_SUB_INTERFACES6 = 389,
+        TOKEN_SUB_SUBNET6 = 390,
+        TOKEN_SUB_POOL6 = 391,
+        TOKEN_SUB_PD_POOL = 392,
+        TOKEN_SUB_RESERVATION = 393,
+        TOKEN_SUB_OPTION_DEF = 394,
+        TOKEN_SUB_OPTION_DATA = 395,
+        TOKEN_SUB_HOOKS_LIBRARY = 396,
+        TOKEN_SUB_DHCP_DDNS = 397,
+        TOKEN_STRING = 398,
+        TOKEN_INTEGER = 399,
+        TOKEN_FLOAT = 400,
+        TOKEN_BOOLEAN = 401
       };
     };
 
@@ -1099,6 +1102,18 @@ namespace isc { namespace dhcp {
 
     static inline
     symbol_type
+    make_FLUSH (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXSIZE (const location_type& l);
+
+    static inline
+    symbol_type
+    make_MAXVER (const location_type& l);
+
+    static inline
+    symbol_type
     make_DHCP4 (const location_type& l);
 
     static inline
@@ -1375,11 +1390,11 @@ namespace isc { namespace dhcp {
     {
       yyeof_ = 0,
       yylast_ = 784,     ///< Last index in yytable_.
-      yynnts_ = 324,  ///< Number of nonterminal symbols.
+      yynnts_ = 328,  ///< Number of nonterminal symbols.
       yyfinal_ = 26, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 144  ///< Number of tokens.
+      yyntokens_ = 147  ///< Number of tokens.
     };
 
 
@@ -1435,9 +1450,10 @@ namespace isc { namespace dhcp {
      105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
      115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
      125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
-     135,   136,   137,   138,   139,   140,   141,   142,   143
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146
     };
-    const unsigned int user_token_number_max_ = 398;
+    const unsigned int user_token_number_max_ = 401;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -1470,28 +1486,28 @@ namespace isc { namespace dhcp {
   {
       switch (other.type_get ())
     {
-      case 158: // value
-      case 162: // map_value
-      case 203: // db_type
-      case 398: // duid_type
-      case 431: // ncr_protocol_value
-      case 439: // replace_client_name_value
+      case 161: // value
+      case 165: // map_value
+      case 206: // db_type
+      case 401: // duid_type
+      case 434: // ncr_protocol_value
+      case 442: // replace_client_name_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 143: // "boolean"
+      case 146: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 142: // "floating point"
+      case 145: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 141: // "integer"
+      case 144: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 140: // "constant string"
+      case 143: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -1512,28 +1528,28 @@ namespace isc { namespace dhcp {
     (void) v;
       switch (this->type_get ())
     {
-      case 158: // value
-      case 162: // map_value
-      case 203: // db_type
-      case 398: // duid_type
-      case 431: // ncr_protocol_value
-      case 439: // replace_client_name_value
+      case 161: // value
+      case 165: // map_value
+      case 206: // db_type
+      case 401: // duid_type
+      case 434: // ncr_protocol_value
+      case 442: // replace_client_name_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 143: // "boolean"
+      case 146: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 142: // "floating point"
+      case 145: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 141: // "integer"
+      case 144: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 140: // "constant string"
+      case 143: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1613,28 +1629,28 @@ namespace isc { namespace dhcp {
     // Type destructor.
     switch (yytype)
     {
-      case 158: // value
-      case 162: // map_value
-      case 203: // db_type
-      case 398: // duid_type
-      case 431: // ncr_protocol_value
-      case 439: // replace_client_name_value
+      case 161: // value
+      case 165: // map_value
+      case 206: // db_type
+      case 401: // duid_type
+      case 434: // ncr_protocol_value
+      case 442: // replace_client_name_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 143: // "boolean"
+      case 146: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 142: // "floating point"
+      case 145: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 141: // "integer"
+      case 144: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 140: // "constant string"
+      case 143: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1661,28 +1677,28 @@ namespace isc { namespace dhcp {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 158: // value
-      case 162: // map_value
-      case 203: // db_type
-      case 398: // duid_type
-      case 431: // ncr_protocol_value
-      case 439: // replace_client_name_value
+      case 161: // value
+      case 165: // map_value
+      case 206: // db_type
+      case 401: // duid_type
+      case 434: // ncr_protocol_value
+      case 442: // replace_client_name_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 143: // "boolean"
+      case 146: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 142: // "floating point"
+      case 145: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 141: // "integer"
+      case 144: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 140: // "constant string"
+      case 143: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1755,7 +1771,7 @@ namespace isc { namespace dhcp {
      365,   366,   367,   368,   369,   370,   371,   372,   373,   374,
      375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
      385,   386,   387,   388,   389,   390,   391,   392,   393,   394,
-     395,   396,   397,   398
+     395,   396,   397,   398,   399,   400,   401
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -2505,6 +2521,24 @@ namespace isc { namespace dhcp {
   }
 
   Dhcp6Parser::symbol_type
+  Dhcp6Parser::make_FLUSH (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_FLUSH, l);
+  }
+
+  Dhcp6Parser::symbol_type
+  Dhcp6Parser::make_MAXSIZE (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXSIZE, l);
+  }
+
+  Dhcp6Parser::symbol_type
+  Dhcp6Parser::make_MAXVER (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_MAXVER, l);
+  }
+
+  Dhcp6Parser::symbol_type
   Dhcp6Parser::make_DHCP4 (const location_type& l)
   {
     return symbol_type (token::TOKEN_DHCP4, l);
@@ -2615,7 +2649,7 @@ namespace isc { namespace dhcp {
 
 #line 14 "dhcp6_parser.yy" // lalr1.cc:377
 } } // isc::dhcp
-#line 2619 "dhcp6_parser.h" // lalr1.cc:377
+#line 2653 "dhcp6_parser.h" // lalr1.cc:377
 
 
 

+ 28 - 4
src/bin/dhcp6/dhcp6_parser.yy

@@ -180,6 +180,9 @@ using namespace std;
   OUTPUT "output"
   DEBUGLEVEL "debuglevel"
   SEVERITY "severity"
+  FLUSH "flush"
+  MAXSIZE "maxsize"
+  MAXVER "maxver"
 
   DHCP4 "Dhcp4"
   DHCPDDNS "DhcpDdns"
@@ -1820,15 +1823,21 @@ output_entry: LCURLY_BRACKET {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
-} output_params RCURLY_BRACKET {
+} output_params_list RCURLY_BRACKET {
     ctx.stack_.pop_back();
 };
 
-output_params: output_param
-             | output_params COMMA output_param
+output_params_list: output_params
+                  | output_params_list COMMA output_params
+                  ;
+
+output_params: output
+             | flush
+             | maxsize
+             | maxver
              ;
 
-output_param: OUTPUT {
+output: OUTPUT {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
@@ -1836,6 +1845,21 @@ output_param: OUTPUT {
     ctx.leave();
 };
 
+flush: FLUSH COLON BOOLEAN {
+    ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("flush", flush);
+}
+
+maxsize: MAXSIZE COLON INTEGER {
+    ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxsize", maxsize);
+}
+
+maxver: MAXVER COLON INTEGER {
+    ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("maxver", maxver);
+}
+
 %%
 
 void

+ 1 - 1
src/bin/dhcp6/location.hh

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

+ 1 - 1
src/bin/dhcp6/position.hh

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

+ 1 - 1
src/bin/dhcp6/stack.hh

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

+ 0 - 36
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc

@@ -991,42 +991,6 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configWriteFilename) {
     ::remove("test2.json");
 }
 
-// Tests if config-write rejects invalid filename (a one that tries to escape
-// the current directory).
-TEST_F(CtrlChannelDhcpv6SrvTest, configWriteInvalidJailEscape) {
-    createUnixChannelServer();
-    std::string response;
-
-    sendUnixCommand("{ \"command\": \"config-write\", \"arguments\": "
-                    "{ \"filename\": \"../test3.json\" } }", response);
-    checkConfigWrite(response, CONTROL_RESULT_ERROR,
-                     "Using '..' in filename is not allowed.");
-}
-
-// Tests if config-write rejects invalid filename (absolute paths are not allowed)
-TEST_F(CtrlChannelDhcpv6SrvTest, configWriteInvalidAbsPath) {
-    createUnixChannelServer();
-    std::string response;
-
-    sendUnixCommand("{ \"command\": \"config-write\", \"arguments\": "
-                    "{ \"filename\": \"/tmp/test4.json\" } }", response);
-    checkConfigWrite(response, CONTROL_RESULT_ERROR,
-                     "Absolute path in filename is not allowed.");
-}
-
-// Tests if config-write rejects invalid filename (one with backslashes, which may
-// lead to some other tricks)
-TEST_F(CtrlChannelDhcpv6SrvTest, configWriteInvalidEscape) {
-    createUnixChannelServer();
-    std::string response;
-
-    // This will be converted to foo(single backslash)test5.json
-    sendUnixCommand("{ \"command\": \"config-write\", \"arguments\": "
-                    "{ \"filename\": \"foo\\\\test5.json\" } }", response);
-    checkConfigWrite(response, CONTROL_RESULT_ERROR,
-                     "Using \\ in filename is not allowed.");
-}
-
 // Tests if config-reload attempts to reload a file and reports that the
 // file is missing.
 TEST_F(CtrlChannelDhcpv6SrvTest, configReloadMissingFile) {

+ 0 - 20
src/lib/process/d_controller.cc

@@ -446,26 +446,6 @@ DControllerBase::configWriteHandler(const std::string&,
         }
     }
 
-    // Now do the sanity checks on the filename
-    if (filename.find("..") != std::string::npos) {
-        // Trying to escape the directory.. nope.
-        return (createAnswer(COMMAND_ERROR,
-                             "Using '..' in filename is not allowed."));
-    }
-
-    if (filename.find("\\") != std::string::npos) {
-        // Trying to inject escapes (possibly to inject quotes and something
-        // nasty afterward)
-        return (createAnswer(COMMAND_ERROR,
-                             "Using \\ in filename is not allowed."));
-    }
-
-    if (filename[0] == '/') {
-        // Absolute paths are not allowed.
-        return (createAnswer(COMMAND_ERROR,
-                             "Absolute path in filename is not allowed."));
-    }
-
     // Ok, it's time to write the file.
     size_t size = 0;
     try {