]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3840] backport #3831 to 2_6
authorRazvan Becheriu <razvan@isc.org>
Tue, 13 May 2025 09:21:41 +0000 (12:21 +0300)
committerRazvan Becheriu <razvan@isc.org>
Tue, 13 May 2025 16:57:09 +0000 (16:57 +0000)
49 files changed:
doc/examples/kea4/all-keys-netconf.json
doc/examples/kea4/all-keys.json
doc/examples/kea4/dhcpv4-over-dhcpv6.json
doc/examples/kea6/all-keys-netconf.json
doc/examples/kea6/all-keys.json
doc/examples/kea6/dhcpv4-over-dhcpv6.json
doc/sphinx/arm/dhcp4-srv.rst
doc/sphinx/arm/dhcp6-srv.rst
src/bin/admin/tests/memfile_tests.sh.in
src/bin/dhcp4/tests/dhcp4_process_tests.sh.in
src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp6/dhcp6_messages.cc
src/bin/dhcp6/dhcp6_messages.h
src/bin/dhcp6/dhcp6_messages.mes
src/bin/dhcp6/dhcp6_parser.cc
src/bin/dhcp6/dhcp6_parser.yy
src/bin/dhcp6/json_config_parser.cc
src/bin/dhcp6/tests/Makefile.am
src/bin/dhcp6/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/dhcp6_process_tests.sh.in
src/bin/dhcp6/tests/dhcp6_test_utils.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h
src/bin/dhcp6/tests/hooks_unittest.cc
src/bin/dhcp6/tests/parser_unittest.cc
src/lib/dhcpsrv/cfgmgr.cc
src/lib/dhcpsrv/cfgmgr.h
src/lib/dhcpsrv/dhcpsrv_messages.cc
src/lib/dhcpsrv/dhcpsrv_messages.h
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/lease_mgr_factory.cc
src/lib/dhcpsrv/memfile_lease_mgr.cc
src/lib/dhcpsrv/memfile_lease_mgr.h
src/lib/dhcpsrv/srv_config.cc
src/lib/dhcpsrv/tests/Makefile.am
src/lib/dhcpsrv/tests/cfg_duid_unittest.cc
src/lib/dhcpsrv/tests/cfgmgr_unittest.cc
src/lib/dhcpsrv/tests/csv_lease_file4_unittest.cc
src/lib/dhcpsrv/tests/csv_lease_file6_unittest.cc
src/lib/dhcpsrv/tests/lease_file_loader_unittest.cc
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
src/lib/hooks/hooks_parser.cc
src/lib/hooks/hooks_parser.h
src/lib/hooks/tests/hooks_manager_unittest.cc
src/lib/testutils/Makefile.am
src/lib/testutils/env_var_wrapper.cc [new file with mode: 0644]
src/lib/testutils/env_var_wrapper.h [new file with mode: 0644]
src/lib/util/filesystem.cc
src/lib/util/filesystem.h
src/lib/util/tests/filesystem_unittests.cc

index e03d71d10a6d1bfb31206bcf4acfd5111bf01459..8d018fb0e8891d6ceb256fc5ab08038ab63fb39a 100644 (file)
 
             // Name of the lease file. In the case of a database it specifies the
             // database name.
-            "name": "/tmp/kea-dhcp4.csv",
+            "name": "kea-dhcp4.csv",
 
             // memfile-specific parameter indicating whether leases should
             // be saved on persistent storage (disk) or not. The true value
index ff62093877659ef7bf3d2bc6af7882dbb5d49f77..2b0eeb1342aa372719bbc11e0ca9f410d489d32c 100644 (file)
 
             // Name of the lease file. In the case of a database it specifies the
             // database name.
-            "name": "/tmp/kea-dhcp4.csv",
+            "name": "kea-dhcp4.csv",
 
             // memfile-specific parameter indicating whether leases should
             // be saved on persistent storage (disk) or not. The true value
index c622c4225e43e08670d8090b967971e0cf48d898..8cf61b7782f63f9faa69bb0660383a931cb3390b 100644 (file)
@@ -12,7 +12,7 @@
 
   "lease-database": {
       "type": "memfile",
-      "name": "/tmp/kea-dhcp4.csv",
+      "name": "kea-dhcp4.csv",
       "lfc-interval": 3600
   },
 
index 2466dd123081832cf6abb9c5dcf10367380d6472..2df5b02b6941873c6175f3dd7f36895f62ada77f 100644 (file)
 
             // Name of the lease file. In the case of a database it specifies the
             // database name.
-            "name": "/tmp/kea-dhcp6.csv",
+            "name": "kea-dhcp6.csv",
 
             // memfile-specific parameter indicating whether leases should
             // be saved on persistent storage (disk) or not. The true value
         // "subnet6" levels.
         "reservations-out-of-pool": false,
 
-        // Data directory.
-        "data-directory": "/tmp",
-
         // Global compute T1 and T2 timers.
         "calculate-tee-times": true,
 
index 9ccbfc2d84c3e7bf6b66b4a0f10f302c3ab8f59f..4dfd76753c70031832b3c4d1bb24f783f0734eeb 100644 (file)
 
             // Name of the lease file. In the case of a database it specifies the
             // database name.
-            "name": "/tmp/kea-dhcp6.csv",
+            "name": "kea-dhcp6.csv",
 
             // memfile-specific parameter indicating whether leases should
             // be saved on persistent storage (disk) or not. The true value
         // "subnet6" levels.
         "reservations-out-of-pool": false,
 
-        // Data directory.
-        "data-directory": "/tmp",
-
         // Global compute T1 and T2 timers.
         "calculate-tee-times": true,
 
index 56e371e3ceeb921b53c213f4d70740ab3f3e26d9..d832ca56516434e6ab7c3364cb68dbeb1bb258e8 100644 (file)
@@ -13,7 +13,7 @@
 
   "lease-database": {
       "type": "memfile",
-      "name": "/tmp/kea-dhcp6.csv"
+      "name": "kea-dhcp6.csv"
   },
 
   "preferred-lifetime": 3000,
index d47f55c866643dbfbcaa8ce0bab63ec18a7dbd36..3107783446d1eb1d29a548ee2be81484c618f7f9 100644 (file)
@@ -361,9 +361,19 @@ that can be used to configure the memfile backend.
    default value of the ``persist`` parameter is ``true``, which enables
    writing lease updates to the lease file.
 
--  ``name``: specifies an absolute location of the lease file in which
-   new leases and lease updates are recorded. The default value for
-   this parameter is ``"[kea-install-dir]/var/lib/kea/kea-leases4.csv"``.
+-  ``name``: specifies the lease file in which new leases and lease updates
+   are recorded. The default value for this parameter is
+   ``"[kea-install-dir]/var/lib/kea/kea-leases4.csv"``.
+
+.. note::
+
+    As of Kea 2.7.9, lease files may only be loaded from the data directory
+    determined during compilation: ``"[kea-install-dir]/var/lib/kea"``. This
+    path may be overridden at startup by setting the environment variable
+    ``KEA_DHCP_DATA_DIRECTORY`` to the desired path.  If a path other than
+    this value is used in ``name``, Kea will emit an error and refuse to start
+    or, if already running, log an unrecoverable error.  For ease of use in
+    specifying a custom file name simply omit the path component from ``name``.
 
 -  ``lfc-interval``: specifies the interval, in seconds, at which the
    server will perform a lease file cleanup (LFC). This removes
index b9318effe66f7c055522d8983066544ebe768993..c5b82e741e16ab69dc0a24ac26594e3f40bfc919 100644 (file)
@@ -317,9 +317,19 @@ that can be used to configure the memfile backend.
    default value of the ``persist`` parameter is ``true``, which enables
    writing lease updates to the lease file.
 
--  ``name``: specifies an absolute location of the lease file in which
-   new leases and lease updates are recorded. The default value for
-   this parameter is ``"[kea-install-dir]/var/lib/kea/kea-leases6.csv"``.
+-  ``name``: specifies the lease file in which new leases and lease updates
+   are recorded. The default value for this parameter is
+   ``"[kea-install-dir]/var/lib/kea/kea-leases6.csv"``.
+
+.. note::
+
+    As of Kea 2.7.9, lease files may only be loaded from the data directory
+    determined during compilation: ``"[kea-install-dir]/var/lib/kea"``. This
+    path may be overridden at startup by setting the environment variable
+    ``KEA_DHCP_DATA_DIRECTORY`` to the desired path.  If a path other than
+    this value is used in ``name``, Kea will emit an error and refuse to start
+    or, if already running, log an unrecoverable error.  For ease of use in
+    specifying a custom file name simply omit the path component from ``name``.
 
 -  ``lfc-interval``: specifies the interval, in seconds, at which the
    server will perform a lease file cleanup (LFC). This removes
@@ -6224,6 +6234,16 @@ memory lease file into its data directory. By default this directory is
        ...
    }
 
+.. note::
+
+    As of Kea 2.7.9, ``data-directory`` is deprecated. The duid and lease
+    files may only be loaded from the directory determined at
+    compilation: ``"[kea-install-dir]/var/lib/kea"``. This path may be
+    overridden at startup by setting the environment variable
+    ``KEA_DHCP_DATA_DIRECTORY`` to the desired path.  If a path other than
+    this value is used in ``data-directory``, Kea will emit an error and
+    refuse to start or, if already running, log an unrecoverable error.
+
 .. _stateless-dhcp6:
 
 Stateless DHCPv6 (INFORMATION-REQUEST Message)
index 0fdc5f557e9fc7ad70b9eb1c86c2c943e3b8f7a3..bd92ed672be4b657c6e9bffec782db08b71be04f 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2014-2025 Internet Systems Consortium, Inc. ("ISC")
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -14,6 +14,8 @@ set -eu
 # shellcheck source=src/lib/testutils/dhcp_test_lib.sh.in
 . "@abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh"
 
+export KEA_DHCP_DATA_DIR="@abs_top_builddir@/src/bin/admin/tests"
+
 # Locations of memfile tools
 kea_admin="@abs_top_builddir@/src/bin/admin/kea-admin"
 kea_lfc="@abs_top_builddir@/src/bin/lfc/kea-lfc"
index 8d7cb45df9ea8cb4a80e70e6768cb4704ee1221b..987c919630f964f2bc9238ef84834f47e99ee11f 100644 (file)
@@ -15,6 +15,7 @@ CFG_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_config.json"
 # Path to the Kea log file.
 LOG_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test.log"
 # Path to the Kea lease file.
+export KEA_DHCP_DATA_DIR="@abs_top_builddir@/src/bin/dhcp4/tests"
 LEASE_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_leases.csv"
 # Path to the Kea LFC application
 export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
index 94dfe6f48f92109d155258bd839f876e0849a1ea..93e51324356ec29dc158476a4d40b971ea7d2790 100644 (file)
@@ -41,7 +41,7 @@ namespace test {
 
 BaseServerTest::BaseServerTest()
     : original_datadir_(CfgMgr::instance().getDataDir()) {
-    CfgMgr::instance().setDataDir(TEST_DATA_BUILDDIR);
+    CfgMgr::instance().getDataDir(true, TEST_DATA_BUILDDIR);
 }
 
 BaseServerTest::~BaseServerTest() {
@@ -50,8 +50,12 @@ BaseServerTest::~BaseServerTest() {
     s2 << CfgMgr::instance().getDataDir() << "/kea-leases4.csv";
     static_cast<void>(::remove(s2.str().c_str()));
 
+    std::ostringstream s3;
+    s3 << CfgMgr::instance().getDataDir() << "/kea-dhcp4.csv";
+    static_cast<void>(::remove(s3.str().c_str()));
+
     // Revert to original data directory.
-    CfgMgr::instance().setDataDir(original_datadir_);
+    CfgMgr::instance().getDataDir(true, original_datadir_);
 
     // Revert to unit test logging, in case the test reconfigured it.
     isc::log::initLogger();
index a02f172ee5ad3b7dbfc956cc4f8dfd922ba199a7..c57440d932858e6043b765cf22968dc20f65e5fb 100644 (file)
@@ -33,6 +33,7 @@ extern const isc::log::MessageID DHCP6_CONFIG_SYNTAX_WARNING = "DHCP6_CONFIG_SYN
 extern const isc::log::MessageID DHCP6_CONFIG_UNRECOVERABLE_ERROR = "DHCP6_CONFIG_UNRECOVERABLE_ERROR";
 extern const isc::log::MessageID DHCP6_CONFIG_UNSUPPORTED_OBJECT = "DHCP6_CONFIG_UNSUPPORTED_OBJECT";
 extern const isc::log::MessageID DHCP6_CONFIG_UPDATE = "DHCP6_CONFIG_UPDATE";
+extern const isc::log::MessageID DHCP6_DATA_DIRECTORY_DEPRECATED = "DHCP6_DATA_DIRECTORY_DEPRECATED";
 extern const isc::log::MessageID DHCP6_DB_BACKEND_STARTED = "DHCP6_DB_BACKEND_STARTED";
 extern const isc::log::MessageID DHCP6_DB_RECONNECT_DISABLED = "DHCP6_DB_RECONNECT_DISABLED";
 extern const isc::log::MessageID DHCP6_DB_RECONNECT_FAILED = "DHCP6_DB_RECONNECT_FAILED";
@@ -208,6 +209,7 @@ const char* values[] = {
     "DHCP6_CONFIG_UNRECOVERABLE_ERROR", "DHCPv6 server new configuration failed with an error which cannot be recovered",
     "DHCP6_CONFIG_UNSUPPORTED_OBJECT", "DHCPv6 server configuration includes an unsupported object: %1",
     "DHCP6_CONFIG_UPDATE", "updated configuration received: %1",
+    "DHCP6_DATA_DIRECTORY_DEPRECATED", "'data-directory' has been deprecated and should no longer be used.",
     "DHCP6_DB_BACKEND_STARTED", "lease database started (type: %1, name: %2)",
     "DHCP6_DB_RECONNECT_DISABLED", "database reconnect is disabled: retries left: %1, reconnect wait time: %2, manager ID: %3, timer: %4",
     "DHCP6_DB_RECONNECT_FAILED", "maximum number of database reconnect attempts: %1, has been exhausted without success, manager ID: %2, timer: %3",
index 6203303c5c8e2fb1b23bcdda292ef11c745e95c7..7d429d75bb3da57ba9f5f22862474c29a5df6809 100644 (file)
@@ -34,6 +34,7 @@ extern const isc::log::MessageID DHCP6_CONFIG_SYNTAX_WARNING;
 extern const isc::log::MessageID DHCP6_CONFIG_UNRECOVERABLE_ERROR;
 extern const isc::log::MessageID DHCP6_CONFIG_UNSUPPORTED_OBJECT;
 extern const isc::log::MessageID DHCP6_CONFIG_UPDATE;
+extern const isc::log::MessageID DHCP6_DATA_DIRECTORY_DEPRECATED;
 extern const isc::log::MessageID DHCP6_DB_BACKEND_STARTED;
 extern const isc::log::MessageID DHCP6_DB_RECONNECT_DISABLED;
 extern const isc::log::MessageID DHCP6_DB_RECONNECT_FAILED;
index cdcbf8ff12de030e7fd73ce409d994683d9d9028..90b5d115493b719cf3d242e874edde6d8980aed0 100644 (file)
@@ -1064,3 +1064,10 @@ such modification. The clients will remember previous server-id, and will
 use it to extend their leases. As a result, they will have to go through
 a rebinding phase to re-acquire their leases and associate them with a
 new server id.
+
+% DHCP6_DATA_DIRECTORY_DEPRECATED 'data-directory' has been deprecated and should no longer be used.
+This warning message is emitted when the configuration parsing detects
+that the `data-directory` parameter has been specified.  This parameter
+is no longer supported. This supported path, determined at compile time,
+may be overridden at runtime by setting the environment variable
+'KEA_DHCP_DATA_DIR'.
index eb7ef0e5bf4095d053e0e606cd305dd4e47fc654..239109a1fb6c28b1d39f6f2e7263a85554157ed1 100644 (file)
@@ -1133,291 +1133,292 @@ namespace isc { namespace dhcp {
 #line 573 "dhcp6_parser.yy"
                {
     ElementPtr datadir(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
+    ctx.warning(yystack_[2].location, "data-directory is deprecated and will be ignored");
     ctx.stack_.back()->set("data-directory", datadir);
     ctx.leave();
 }
-#line 1140 "dhcp6_parser.cc"
+#line 1141 "dhcp6_parser.cc"
     break;
 
   case 142: // preferred_lifetime: "preferred-lifetime" ":" "integer"
-#line 579 "dhcp6_parser.yy"
+#line 580 "dhcp6_parser.yy"
                                                      {
     ctx.unique("preferred-lifetime", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("preferred-lifetime", prf);
 }
-#line 1150 "dhcp6_parser.cc"
+#line 1151 "dhcp6_parser.cc"
     break;
 
   case 143: // min_preferred_lifetime: "min-preferred-lifetime" ":" "integer"
-#line 585 "dhcp6_parser.yy"
+#line 586 "dhcp6_parser.yy"
                                                              {
     ctx.unique("min-preferred-lifetime", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("min-preferred-lifetime", prf);
 }
-#line 1160 "dhcp6_parser.cc"
+#line 1161 "dhcp6_parser.cc"
     break;
 
   case 144: // max_preferred_lifetime: "max-preferred-lifetime" ":" "integer"
-#line 591 "dhcp6_parser.yy"
+#line 592 "dhcp6_parser.yy"
                                                              {
     ctx.unique("max-preferred-lifetime", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-preferred-lifetime", prf);
 }
-#line 1170 "dhcp6_parser.cc"
+#line 1171 "dhcp6_parser.cc"
     break;
 
   case 145: // valid_lifetime: "valid-lifetime" ":" "integer"
-#line 597 "dhcp6_parser.yy"
+#line 598 "dhcp6_parser.yy"
                                              {
     ctx.unique("valid-lifetime", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("valid-lifetime", prf);
 }
-#line 1180 "dhcp6_parser.cc"
+#line 1181 "dhcp6_parser.cc"
     break;
 
   case 146: // min_valid_lifetime: "min-valid-lifetime" ":" "integer"
-#line 603 "dhcp6_parser.yy"
+#line 604 "dhcp6_parser.yy"
                                                      {
     ctx.unique("min-valid-lifetime", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("min-valid-lifetime", prf);
 }
-#line 1190 "dhcp6_parser.cc"
+#line 1191 "dhcp6_parser.cc"
     break;
 
   case 147: // max_valid_lifetime: "max-valid-lifetime" ":" "integer"
-#line 609 "dhcp6_parser.yy"
+#line 610 "dhcp6_parser.yy"
                                                      {
     ctx.unique("max-valid-lifetime", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-valid-lifetime", prf);
 }
-#line 1200 "dhcp6_parser.cc"
+#line 1201 "dhcp6_parser.cc"
     break;
 
   case 148: // renew_timer: "renew-timer" ":" "integer"
-#line 615 "dhcp6_parser.yy"
+#line 616 "dhcp6_parser.yy"
                                        {
     ctx.unique("renew-timer", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("renew-timer", prf);
 }
-#line 1210 "dhcp6_parser.cc"
+#line 1211 "dhcp6_parser.cc"
     break;
 
   case 149: // rebind_timer: "rebind-timer" ":" "integer"
-#line 621 "dhcp6_parser.yy"
+#line 622 "dhcp6_parser.yy"
                                          {
     ctx.unique("rebind-timer", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("rebind-timer", prf);
 }
-#line 1220 "dhcp6_parser.cc"
+#line 1221 "dhcp6_parser.cc"
     break;
 
   case 150: // calculate_tee_times: "calculate-tee-times" ":" "boolean"
-#line 627 "dhcp6_parser.yy"
+#line 628 "dhcp6_parser.yy"
                                                        {
     ctx.unique("calculate-tee-times", ctx.loc2pos(yystack_[2].location));
     ElementPtr ctt(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("calculate-tee-times", ctt);
 }
-#line 1230 "dhcp6_parser.cc"
+#line 1231 "dhcp6_parser.cc"
     break;
 
   case 151: // t1_percent: "t1-percent" ":" "floating point"
-#line 633 "dhcp6_parser.yy"
+#line 634 "dhcp6_parser.yy"
                                    {
     ctx.unique("t1-percent", ctx.loc2pos(yystack_[2].location));
     ElementPtr t1(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("t1-percent", t1);
 }
-#line 1240 "dhcp6_parser.cc"
+#line 1241 "dhcp6_parser.cc"
     break;
 
   case 152: // t2_percent: "t2-percent" ":" "floating point"
-#line 639 "dhcp6_parser.yy"
+#line 640 "dhcp6_parser.yy"
                                    {
     ctx.unique("t2-percent", ctx.loc2pos(yystack_[2].location));
     ElementPtr t2(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("t2-percent", t2);
 }
-#line 1250 "dhcp6_parser.cc"
+#line 1251 "dhcp6_parser.cc"
     break;
 
   case 153: // cache_threshold: "cache-threshold" ":" "floating point"
-#line 645 "dhcp6_parser.yy"
+#line 646 "dhcp6_parser.yy"
                                              {
     ctx.unique("cache-threshold", ctx.loc2pos(yystack_[2].location));
     ElementPtr ct(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("cache-threshold", ct);
 }
-#line 1260 "dhcp6_parser.cc"
+#line 1261 "dhcp6_parser.cc"
     break;
 
   case 154: // cache_max_age: "cache-max-age" ":" "integer"
-#line 651 "dhcp6_parser.yy"
+#line 652 "dhcp6_parser.yy"
                                            {
     ctx.unique("cache-max-age", ctx.loc2pos(yystack_[2].location));
     ElementPtr cm(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("cache-max-age", cm);
 }
-#line 1270 "dhcp6_parser.cc"
+#line 1271 "dhcp6_parser.cc"
     break;
 
   case 155: // decline_probation_period: "decline-probation-period" ":" "integer"
-#line 657 "dhcp6_parser.yy"
+#line 658 "dhcp6_parser.yy"
                                                                  {
     ctx.unique("decline-probation-period", ctx.loc2pos(yystack_[2].location));
     ElementPtr dpp(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("decline-probation-period", dpp);
 }
-#line 1280 "dhcp6_parser.cc"
+#line 1281 "dhcp6_parser.cc"
     break;
 
   case 156: // ddns_send_updates: "ddns-send-updates" ":" "boolean"
-#line 663 "dhcp6_parser.yy"
+#line 664 "dhcp6_parser.yy"
                                                    {
     ctx.unique("ddns-send-updates", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-send-updates", b);
 }
-#line 1290 "dhcp6_parser.cc"
+#line 1291 "dhcp6_parser.cc"
     break;
 
   case 157: // ddns_override_no_update: "ddns-override-no-update" ":" "boolean"
-#line 669 "dhcp6_parser.yy"
+#line 670 "dhcp6_parser.yy"
                                                                {
     ctx.unique("ddns-override-no-update", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-override-no-update", b);
 }
-#line 1300 "dhcp6_parser.cc"
+#line 1301 "dhcp6_parser.cc"
     break;
 
   case 158: // ddns_override_client_update: "ddns-override-client-update" ":" "boolean"
-#line 675 "dhcp6_parser.yy"
+#line 676 "dhcp6_parser.yy"
                                                                        {
     ctx.unique("ddns-override-client-update", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-override-client-update", b);
 }
-#line 1310 "dhcp6_parser.cc"
+#line 1311 "dhcp6_parser.cc"
     break;
 
   case 159: // $@22: %empty
-#line 681 "dhcp6_parser.yy"
+#line 682 "dhcp6_parser.yy"
                                                    {
     ctx.enter(ctx.REPLACE_CLIENT_NAME);
     ctx.unique("ddns-replace-client-name", ctx.loc2pos(yystack_[0].location));
 }
-#line 1319 "dhcp6_parser.cc"
+#line 1320 "dhcp6_parser.cc"
     break;
 
   case 160: // ddns_replace_client_name: "ddns-replace-client-name" $@22 ":" ddns_replace_client_name_value
-#line 684 "dhcp6_parser.yy"
+#line 685 "dhcp6_parser.yy"
                                        {
     ctx.stack_.back()->set("ddns-replace-client-name", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 1328 "dhcp6_parser.cc"
+#line 1329 "dhcp6_parser.cc"
     break;
 
   case 161: // ddns_replace_client_name_value: "when-present"
-#line 690 "dhcp6_parser.yy"
+#line 691 "dhcp6_parser.yy"
                  {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("when-present", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1336 "dhcp6_parser.cc"
+#line 1337 "dhcp6_parser.cc"
     break;
 
   case 162: // ddns_replace_client_name_value: "never"
-#line 693 "dhcp6_parser.yy"
+#line 694 "dhcp6_parser.yy"
           {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("never", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1344 "dhcp6_parser.cc"
+#line 1345 "dhcp6_parser.cc"
     break;
 
   case 163: // ddns_replace_client_name_value: "always"
-#line 696 "dhcp6_parser.yy"
+#line 697 "dhcp6_parser.yy"
            {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("always", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1352 "dhcp6_parser.cc"
+#line 1353 "dhcp6_parser.cc"
     break;
 
   case 164: // ddns_replace_client_name_value: "when-not-present"
-#line 699 "dhcp6_parser.yy"
+#line 700 "dhcp6_parser.yy"
                      {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1360 "dhcp6_parser.cc"
+#line 1361 "dhcp6_parser.cc"
     break;
 
   case 165: // ddns_replace_client_name_value: "boolean"
-#line 702 "dhcp6_parser.yy"
+#line 703 "dhcp6_parser.yy"
             {
       error(yystack_[0].location, "boolean values for the ddns-replace-client-name are "
                 "no longer supported");
       }
-#line 1369 "dhcp6_parser.cc"
+#line 1370 "dhcp6_parser.cc"
     break;
 
   case 166: // $@23: %empty
-#line 708 "dhcp6_parser.yy"
+#line 709 "dhcp6_parser.yy"
                                              {
     ctx.unique("ddns-generated-prefix", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1378 "dhcp6_parser.cc"
+#line 1379 "dhcp6_parser.cc"
     break;
 
   case 167: // ddns_generated_prefix: "ddns-generated-prefix" $@23 ":" "constant string"
-#line 711 "dhcp6_parser.yy"
+#line 712 "dhcp6_parser.yy"
                {
     ElementPtr s(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-generated-prefix", s);
     ctx.leave();
 }
-#line 1388 "dhcp6_parser.cc"
+#line 1389 "dhcp6_parser.cc"
     break;
 
   case 168: // $@24: %empty
-#line 717 "dhcp6_parser.yy"
+#line 718 "dhcp6_parser.yy"
                                                {
     ctx.unique("ddns-qualifying-suffix", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1397 "dhcp6_parser.cc"
+#line 1398 "dhcp6_parser.cc"
     break;
 
   case 169: // ddns_qualifying_suffix: "ddns-qualifying-suffix" $@24 ":" "constant string"
-#line 720 "dhcp6_parser.yy"
+#line 721 "dhcp6_parser.yy"
                {
     ElementPtr s(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-qualifying-suffix", s);
     ctx.leave();
 }
-#line 1407 "dhcp6_parser.cc"
+#line 1408 "dhcp6_parser.cc"
     break;
 
   case 170: // ddns_update_on_renew: "ddns-update-on-renew" ":" "boolean"
-#line 726 "dhcp6_parser.yy"
+#line 727 "dhcp6_parser.yy"
                                                          {
     ctx.unique("ddns-update-on-renew", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-update-on-renew", b);
 }
-#line 1417 "dhcp6_parser.cc"
+#line 1418 "dhcp6_parser.cc"
     break;
 
   case 171: // ddns_use_conflict_resolution: "ddns-use-conflict-resolution" ":" "boolean"
-#line 735 "dhcp6_parser.yy"
+#line 736 "dhcp6_parser.yy"
                                                                          {
     ctx.unique("ddns-use-conflict-resolution", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
@@ -1427,236 +1428,236 @@ namespace isc { namespace dhcp {
                                       : "no-check-with-dhcid"));
     ctx.stack_.back()->set("ddns-conflict-resolution-mode", mode);
 }
-#line 1431 "dhcp6_parser.cc"
+#line 1432 "dhcp6_parser.cc"
     break;
 
   case 172: // $@25: %empty
-#line 745 "dhcp6_parser.yy"
+#line 746 "dhcp6_parser.yy"
                                                              {
     ctx.unique("ddns-conflict-resolution-mode", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.DDNS_CONFLICT_RESOLUTION_MODE);
 }
-#line 1440 "dhcp6_parser.cc"
+#line 1441 "dhcp6_parser.cc"
     break;
 
   case 173: // ddns_conflict_resolution_mode: "ddns-conflict-resolution-mode" $@25 ":" ddns_conflict_resolution_mode_value
-#line 748 "dhcp6_parser.yy"
+#line 749 "dhcp6_parser.yy"
                                             {
     ctx.stack_.back()->set("ddns-conflict-resolution-mode", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 1449 "dhcp6_parser.cc"
+#line 1450 "dhcp6_parser.cc"
     break;
 
   case 174: // ddns_conflict_resolution_mode_value: "check-with-dhcid"
-#line 754 "dhcp6_parser.yy"
+#line 755 "dhcp6_parser.yy"
                      {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("check-with-dhcid", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1457 "dhcp6_parser.cc"
+#line 1458 "dhcp6_parser.cc"
     break;
 
   case 175: // ddns_conflict_resolution_mode_value: "no-check-with-dhcid"
-#line 757 "dhcp6_parser.yy"
+#line 758 "dhcp6_parser.yy"
                         {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("no-check-with-dhcid", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1465 "dhcp6_parser.cc"
+#line 1466 "dhcp6_parser.cc"
     break;
 
   case 176: // ddns_conflict_resolution_mode_value: "check-exists-with-dhcid"
-#line 760 "dhcp6_parser.yy"
+#line 761 "dhcp6_parser.yy"
                             {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("check-exists-with-dhcid", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1473 "dhcp6_parser.cc"
+#line 1474 "dhcp6_parser.cc"
     break;
 
   case 177: // ddns_conflict_resolution_mode_value: "no-check-without-dhcid"
-#line 763 "dhcp6_parser.yy"
+#line 764 "dhcp6_parser.yy"
                            {
       yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("no-check-without-dhcid", ctx.loc2pos(yystack_[0].location)));
       }
-#line 1481 "dhcp6_parser.cc"
+#line 1482 "dhcp6_parser.cc"
     break;
 
   case 178: // ddns_ttl_percent: "ddns-ttl-percent" ":" "floating point"
-#line 768 "dhcp6_parser.yy"
+#line 769 "dhcp6_parser.yy"
                                                {
     ctx.unique("ddns-ttl-percent", ctx.loc2pos(yystack_[2].location));
     ElementPtr ttl(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ddns-ttl-percent", ttl);
 }
-#line 1491 "dhcp6_parser.cc"
+#line 1492 "dhcp6_parser.cc"
     break;
 
   case 179: // $@26: %empty
-#line 774 "dhcp6_parser.yy"
+#line 775 "dhcp6_parser.yy"
                                      {
     ctx.unique("hostname-char-set", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1500 "dhcp6_parser.cc"
+#line 1501 "dhcp6_parser.cc"
     break;
 
   case 180: // hostname_char_set: "hostname-char-set" $@26 ":" "constant string"
-#line 777 "dhcp6_parser.yy"
+#line 778 "dhcp6_parser.yy"
                {
     ElementPtr s(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname-char-set", s);
     ctx.leave();
 }
-#line 1510 "dhcp6_parser.cc"
+#line 1511 "dhcp6_parser.cc"
     break;
 
   case 181: // $@27: %empty
-#line 783 "dhcp6_parser.yy"
+#line 784 "dhcp6_parser.yy"
                                                      {
     ctx.unique("hostname-char-replacement", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1519 "dhcp6_parser.cc"
+#line 1520 "dhcp6_parser.cc"
     break;
 
   case 182: // hostname_char_replacement: "hostname-char-replacement" $@27 ":" "constant string"
-#line 786 "dhcp6_parser.yy"
+#line 787 "dhcp6_parser.yy"
                {
     ElementPtr s(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname-char-replacement", s);
     ctx.leave();
 }
-#line 1529 "dhcp6_parser.cc"
+#line 1530 "dhcp6_parser.cc"
     break;
 
   case 183: // store_extended_info: "store-extended-info" ":" "boolean"
-#line 792 "dhcp6_parser.yy"
+#line 793 "dhcp6_parser.yy"
                                                        {
     ctx.unique("store-extended-info", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("store-extended-info", b);
 }
-#line 1539 "dhcp6_parser.cc"
+#line 1540 "dhcp6_parser.cc"
     break;
 
   case 184: // statistic_default_sample_count: "statistic-default-sample-count" ":" "integer"
-#line 798 "dhcp6_parser.yy"
+#line 799 "dhcp6_parser.yy"
                                                                              {
     ctx.unique("statistic-default-sample-count", ctx.loc2pos(yystack_[2].location));
     ElementPtr count(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("statistic-default-sample-count", count);
 }
-#line 1549 "dhcp6_parser.cc"
+#line 1550 "dhcp6_parser.cc"
     break;
 
   case 185: // statistic_default_sample_age: "statistic-default-sample-age" ":" "integer"
-#line 804 "dhcp6_parser.yy"
+#line 805 "dhcp6_parser.yy"
                                                                          {
     ctx.unique("statistic-default-sample-age", ctx.loc2pos(yystack_[2].location));
     ElementPtr age(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("statistic-default-sample-age", age);
 }
-#line 1559 "dhcp6_parser.cc"
+#line 1560 "dhcp6_parser.cc"
     break;
 
   case 186: // $@28: %empty
-#line 810 "dhcp6_parser.yy"
+#line 811 "dhcp6_parser.yy"
                        {
     ctx.unique("server-tag", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1568 "dhcp6_parser.cc"
+#line 1569 "dhcp6_parser.cc"
     break;
 
   case 187: // server_tag: "server-tag" $@28 ":" "constant string"
-#line 813 "dhcp6_parser.yy"
+#line 814 "dhcp6_parser.yy"
                {
     ElementPtr stag(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-tag", stag);
     ctx.leave();
 }
-#line 1578 "dhcp6_parser.cc"
+#line 1579 "dhcp6_parser.cc"
     break;
 
   case 188: // parked_packet_limit: "parked-packet-limit" ":" "integer"
-#line 819 "dhcp6_parser.yy"
+#line 820 "dhcp6_parser.yy"
                                                        {
     ctx.unique("parked-packet-limit", ctx.loc2pos(yystack_[2].location));
     ElementPtr ppl(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("parked-packet-limit", ppl);
 }
-#line 1588 "dhcp6_parser.cc"
+#line 1589 "dhcp6_parser.cc"
     break;
 
   case 189: // $@29: %empty
-#line 825 "dhcp6_parser.yy"
+#line 826 "dhcp6_parser.yy"
                      {
     ctx.unique("allocator", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1597 "dhcp6_parser.cc"
+#line 1598 "dhcp6_parser.cc"
     break;
 
   case 190: // allocator: "allocator" $@29 ":" "constant string"
-#line 828 "dhcp6_parser.yy"
+#line 829 "dhcp6_parser.yy"
                {
     ElementPtr al(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("allocator", al);
     ctx.leave();
 }
-#line 1607 "dhcp6_parser.cc"
+#line 1608 "dhcp6_parser.cc"
     break;
 
   case 191: // $@30: %empty
-#line 834 "dhcp6_parser.yy"
+#line 835 "dhcp6_parser.yy"
                            {
     ctx.unique("pd-allocator", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1616 "dhcp6_parser.cc"
+#line 1617 "dhcp6_parser.cc"
     break;
 
   case 192: // pd_allocator: "pd-allocator" $@30 ":" "constant string"
-#line 837 "dhcp6_parser.yy"
+#line 838 "dhcp6_parser.yy"
                {
     ElementPtr al(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("pd-allocator", al);
     ctx.leave();
 }
-#line 1626 "dhcp6_parser.cc"
+#line 1627 "dhcp6_parser.cc"
     break;
 
   case 193: // early_global_reservations_lookup: "early-global-reservations-lookup" ":" "boolean"
-#line 843 "dhcp6_parser.yy"
+#line 844 "dhcp6_parser.yy"
                                                                                  {
     ctx.unique("early-global-reservations-lookup", ctx.loc2pos(yystack_[2].location));
     ElementPtr early(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("early-global-reservations-lookup", early);
 }
-#line 1636 "dhcp6_parser.cc"
+#line 1637 "dhcp6_parser.cc"
     break;
 
   case 194: // ip_reservations_unique: "ip-reservations-unique" ":" "boolean"
-#line 849 "dhcp6_parser.yy"
+#line 850 "dhcp6_parser.yy"
                                                              {
     ctx.unique("ip-reservations-unique", ctx.loc2pos(yystack_[2].location));
     ElementPtr unique(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ip-reservations-unique", unique);
 }
-#line 1646 "dhcp6_parser.cc"
+#line 1647 "dhcp6_parser.cc"
     break;
 
   case 195: // reservations_lookup_first: "reservations-lookup-first" ":" "boolean"
-#line 855 "dhcp6_parser.yy"
+#line 856 "dhcp6_parser.yy"
                                                                    {
     ctx.unique("reservations-lookup-first", ctx.loc2pos(yystack_[2].location));
     ElementPtr first(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("reservations-lookup-first", first);
 }
-#line 1656 "dhcp6_parser.cc"
+#line 1657 "dhcp6_parser.cc"
     break;
 
   case 196: // $@31: %empty
-#line 861 "dhcp6_parser.yy"
+#line 862 "dhcp6_parser.yy"
                                      {
     ctx.unique("interfaces-config", ctx.loc2pos(yystack_[0].location));
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -1664,48 +1665,48 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(i);
     ctx.enter(ctx.INTERFACES_CONFIG);
 }
-#line 1668 "dhcp6_parser.cc"
+#line 1669 "dhcp6_parser.cc"
     break;
 
   case 197: // interfaces_config: "interfaces-config" $@31 ":" "{" interfaces_config_params "}"
-#line 867 "dhcp6_parser.yy"
+#line 868 "dhcp6_parser.yy"
                                                                {
     // No interfaces config param is required
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 1678 "dhcp6_parser.cc"
+#line 1679 "dhcp6_parser.cc"
     break;
 
   case 198: // $@32: %empty
-#line 873 "dhcp6_parser.yy"
+#line 874 "dhcp6_parser.yy"
                                 {
     // Parse the interfaces-config map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 1688 "dhcp6_parser.cc"
+#line 1689 "dhcp6_parser.cc"
     break;
 
   case 199: // sub_interfaces6: "{" $@32 interfaces_config_params "}"
-#line 877 "dhcp6_parser.yy"
+#line 878 "dhcp6_parser.yy"
                                           {
     // No interfaces config param is required
     // parsing completed
 }
-#line 1697 "dhcp6_parser.cc"
+#line 1698 "dhcp6_parser.cc"
     break;
 
   case 202: // interfaces_config_params: interfaces_config_params ","
-#line 884 "dhcp6_parser.yy"
+#line 885 "dhcp6_parser.yy"
                                                          {
                             ctx.warnAboutExtraCommas(yystack_[0].location);
                             }
-#line 1705 "dhcp6_parser.cc"
+#line 1706 "dhcp6_parser.cc"
     break;
 
   case 211: // $@33: %empty
-#line 899 "dhcp6_parser.yy"
+#line 900 "dhcp6_parser.yy"
                             {
     ctx.unique("interfaces", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -1713,60 +1714,60 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1717 "dhcp6_parser.cc"
+#line 1718 "dhcp6_parser.cc"
     break;
 
   case 212: // interfaces_list: "interfaces" $@33 ":" list_strings
-#line 905 "dhcp6_parser.yy"
+#line 906 "dhcp6_parser.yy"
                      {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 1726 "dhcp6_parser.cc"
+#line 1727 "dhcp6_parser.cc"
     break;
 
   case 213: // re_detect: "re-detect" ":" "boolean"
-#line 910 "dhcp6_parser.yy"
+#line 911 "dhcp6_parser.yy"
                                    {
     ctx.unique("re-detect", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("re-detect", b);
 }
-#line 1736 "dhcp6_parser.cc"
+#line 1737 "dhcp6_parser.cc"
     break;
 
   case 214: // service_sockets_require_all: "service-sockets-require-all" ":" "boolean"
-#line 916 "dhcp6_parser.yy"
+#line 917 "dhcp6_parser.yy"
                                                                        {
     ctx.unique("service-sockets-require-all", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("service-sockets-require-all", b);
 }
-#line 1746 "dhcp6_parser.cc"
+#line 1747 "dhcp6_parser.cc"
     break;
 
   case 215: // service_sockets_retry_wait_time: "service-sockets-retry-wait-time" ":" "integer"
-#line 922 "dhcp6_parser.yy"
+#line 923 "dhcp6_parser.yy"
                                                                                {
     ctx.unique("service-sockets-retry-wait-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("service-sockets-retry-wait-time", n);
 }
-#line 1756 "dhcp6_parser.cc"
+#line 1757 "dhcp6_parser.cc"
     break;
 
   case 216: // service_sockets_max_retries: "service-sockets-max-retries" ":" "integer"
-#line 928 "dhcp6_parser.yy"
+#line 929 "dhcp6_parser.yy"
                                                                        {
     ctx.unique("service-sockets-max-retries", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("service-sockets-max-retries", n);
 }
-#line 1766 "dhcp6_parser.cc"
+#line 1767 "dhcp6_parser.cc"
     break;
 
   case 217: // $@34: %empty
-#line 934 "dhcp6_parser.yy"
+#line 935 "dhcp6_parser.yy"
                                {
     ctx.unique("lease-database", ctx.loc2pos(yystack_[0].location));
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -1774,22 +1775,22 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(i);
     ctx.enter(ctx.LEASE_DATABASE);
 }
-#line 1778 "dhcp6_parser.cc"
+#line 1779 "dhcp6_parser.cc"
     break;
 
   case 218: // lease_database: "lease-database" $@34 ":" "{" database_map_params "}"
-#line 940 "dhcp6_parser.yy"
+#line 941 "dhcp6_parser.yy"
                                                           {
     // The type parameter is required
     ctx.require("type", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 1789 "dhcp6_parser.cc"
+#line 1790 "dhcp6_parser.cc"
     break;
 
   case 219: // $@35: %empty
-#line 947 "dhcp6_parser.yy"
+#line 948 "dhcp6_parser.yy"
                                {
     ctx.unique("hosts-database", ctx.loc2pos(yystack_[0].location));
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -1797,22 +1798,22 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(i);
     ctx.enter(ctx.HOSTS_DATABASE);
 }
-#line 1801 "dhcp6_parser.cc"
+#line 1802 "dhcp6_parser.cc"
     break;
 
   case 220: // hosts_database: "hosts-database" $@35 ":" "{" database_map_params "}"
-#line 953 "dhcp6_parser.yy"
+#line 954 "dhcp6_parser.yy"
                                                           {
     // The type parameter is required
     ctx.require("type", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 1812 "dhcp6_parser.cc"
+#line 1813 "dhcp6_parser.cc"
     break;
 
   case 221: // $@36: %empty
-#line 960 "dhcp6_parser.yy"
+#line 961 "dhcp6_parser.yy"
                                  {
     ctx.unique("hosts-databases", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -1820,400 +1821,400 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.HOSTS_DATABASE);
 }
-#line 1824 "dhcp6_parser.cc"
+#line 1825 "dhcp6_parser.cc"
     break;
 
   case 222: // hosts_databases: "hosts-databases" $@36 ":" "[" database_list "]"
-#line 966 "dhcp6_parser.yy"
+#line 967 "dhcp6_parser.yy"
                                                       {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 1833 "dhcp6_parser.cc"
+#line 1834 "dhcp6_parser.cc"
     break;
 
   case 227: // not_empty_database_list: not_empty_database_list ","
-#line 977 "dhcp6_parser.yy"
+#line 978 "dhcp6_parser.yy"
                                                        {
                            ctx.warnAboutExtraCommas(yystack_[0].location);
                            }
-#line 1841 "dhcp6_parser.cc"
+#line 1842 "dhcp6_parser.cc"
     break;
 
   case 228: // $@37: %empty
-#line 982 "dhcp6_parser.yy"
+#line 983 "dhcp6_parser.yy"
                          {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 1851 "dhcp6_parser.cc"
+#line 1852 "dhcp6_parser.cc"
     break;
 
   case 229: // database: "{" $@37 database_map_params "}"
-#line 986 "dhcp6_parser.yy"
+#line 987 "dhcp6_parser.yy"
                                      {
     // The type parameter is required
     ctx.require("type", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 1861 "dhcp6_parser.cc"
+#line 1862 "dhcp6_parser.cc"
     break;
 
   case 232: // database_map_params: database_map_params ","
-#line 994 "dhcp6_parser.yy"
+#line 995 "dhcp6_parser.yy"
                                                {
                        ctx.warnAboutExtraCommas(yystack_[0].location);
                        }
-#line 1869 "dhcp6_parser.cc"
+#line 1870 "dhcp6_parser.cc"
     break;
 
   case 256: // $@38: %empty
-#line 1024 "dhcp6_parser.yy"
+#line 1025 "dhcp6_parser.yy"
                     {
     ctx.unique("type", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.DATABASE_TYPE);
 }
-#line 1878 "dhcp6_parser.cc"
+#line 1879 "dhcp6_parser.cc"
     break;
 
   case 257: // database_type: "type" $@38 ":" db_type
-#line 1027 "dhcp6_parser.yy"
+#line 1028 "dhcp6_parser.yy"
                 {
     ctx.stack_.back()->set("type", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 1887 "dhcp6_parser.cc"
+#line 1888 "dhcp6_parser.cc"
     break;
 
   case 258: // db_type: "memfile"
-#line 1032 "dhcp6_parser.yy"
+#line 1033 "dhcp6_parser.yy"
                  { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("memfile", ctx.loc2pos(yystack_[0].location))); }
-#line 1893 "dhcp6_parser.cc"
+#line 1894 "dhcp6_parser.cc"
     break;
 
   case 259: // db_type: "mysql"
-#line 1033 "dhcp6_parser.yy"
+#line 1034 "dhcp6_parser.yy"
                { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("mysql", ctx.loc2pos(yystack_[0].location))); }
-#line 1899 "dhcp6_parser.cc"
+#line 1900 "dhcp6_parser.cc"
     break;
 
   case 260: // db_type: "postgresql"
-#line 1034 "dhcp6_parser.yy"
+#line 1035 "dhcp6_parser.yy"
                     { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("postgresql", ctx.loc2pos(yystack_[0].location))); }
-#line 1905 "dhcp6_parser.cc"
+#line 1906 "dhcp6_parser.cc"
     break;
 
   case 261: // $@39: %empty
-#line 1037 "dhcp6_parser.yy"
+#line 1038 "dhcp6_parser.yy"
            {
     ctx.unique("user", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1914 "dhcp6_parser.cc"
+#line 1915 "dhcp6_parser.cc"
     break;
 
   case 262: // user: "user" $@39 ":" "constant string"
-#line 1040 "dhcp6_parser.yy"
+#line 1041 "dhcp6_parser.yy"
                {
     ElementPtr user(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("user", user);
     ctx.leave();
 }
-#line 1924 "dhcp6_parser.cc"
+#line 1925 "dhcp6_parser.cc"
     break;
 
   case 263: // $@40: %empty
-#line 1046 "dhcp6_parser.yy"
+#line 1047 "dhcp6_parser.yy"
                    {
     ctx.unique("password", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1933 "dhcp6_parser.cc"
+#line 1934 "dhcp6_parser.cc"
     break;
 
   case 264: // password: "password" $@40 ":" "constant string"
-#line 1049 "dhcp6_parser.yy"
+#line 1050 "dhcp6_parser.yy"
                {
     ElementPtr pwd(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("password", pwd);
     ctx.leave();
 }
-#line 1943 "dhcp6_parser.cc"
+#line 1944 "dhcp6_parser.cc"
     break;
 
   case 265: // $@41: %empty
-#line 1055 "dhcp6_parser.yy"
+#line 1056 "dhcp6_parser.yy"
            {
     ctx.unique("host", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1952 "dhcp6_parser.cc"
+#line 1953 "dhcp6_parser.cc"
     break;
 
   case 266: // host: "host" $@41 ":" "constant string"
-#line 1058 "dhcp6_parser.yy"
+#line 1059 "dhcp6_parser.yy"
                {
     ElementPtr h(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("host", h);
     ctx.leave();
 }
-#line 1962 "dhcp6_parser.cc"
+#line 1963 "dhcp6_parser.cc"
     break;
 
   case 267: // port: "port" ":" "integer"
-#line 1064 "dhcp6_parser.yy"
+#line 1065 "dhcp6_parser.yy"
                          {
     ctx.unique("port", ctx.loc2pos(yystack_[2].location));
     ElementPtr p(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("port", p);
 }
-#line 1972 "dhcp6_parser.cc"
+#line 1973 "dhcp6_parser.cc"
     break;
 
   case 268: // $@42: %empty
-#line 1070 "dhcp6_parser.yy"
+#line 1071 "dhcp6_parser.yy"
            {
     ctx.unique("name", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1981 "dhcp6_parser.cc"
+#line 1982 "dhcp6_parser.cc"
     break;
 
   case 269: // name: "name" $@42 ":" "constant string"
-#line 1073 "dhcp6_parser.yy"
+#line 1074 "dhcp6_parser.yy"
                {
     ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("name", name);
     ctx.leave();
 }
-#line 1991 "dhcp6_parser.cc"
+#line 1992 "dhcp6_parser.cc"
     break;
 
   case 270: // persist: "persist" ":" "boolean"
-#line 1079 "dhcp6_parser.yy"
+#line 1080 "dhcp6_parser.yy"
                                {
     ctx.unique("persist", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("persist", n);
 }
-#line 2001 "dhcp6_parser.cc"
+#line 2002 "dhcp6_parser.cc"
     break;
 
   case 271: // lfc_interval: "lfc-interval" ":" "integer"
-#line 1085 "dhcp6_parser.yy"
+#line 1086 "dhcp6_parser.yy"
                                          {
     ctx.unique("lfc-interval", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("lfc-interval", n);
 }
-#line 2011 "dhcp6_parser.cc"
+#line 2012 "dhcp6_parser.cc"
     break;
 
   case 272: // readonly: "readonly" ":" "boolean"
-#line 1091 "dhcp6_parser.yy"
+#line 1092 "dhcp6_parser.yy"
                                  {
     ctx.unique("readonly", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("readonly", n);
 }
-#line 2021 "dhcp6_parser.cc"
+#line 2022 "dhcp6_parser.cc"
     break;
 
   case 273: // connect_timeout: "connect-timeout" ":" "integer"
-#line 1097 "dhcp6_parser.yy"
+#line 1098 "dhcp6_parser.yy"
                                                {
     ctx.unique("connect-timeout", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("connect-timeout", n);
 }
-#line 2031 "dhcp6_parser.cc"
+#line 2032 "dhcp6_parser.cc"
     break;
 
   case 274: // read_timeout: "read-timeout" ":" "integer"
-#line 1103 "dhcp6_parser.yy"
+#line 1104 "dhcp6_parser.yy"
                                          {
     ctx.unique("read-timeout", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("read-timeout", n);
 }
-#line 2041 "dhcp6_parser.cc"
+#line 2042 "dhcp6_parser.cc"
     break;
 
   case 275: // write_timeout: "write-timeout" ":" "integer"
-#line 1109 "dhcp6_parser.yy"
+#line 1110 "dhcp6_parser.yy"
                                            {
     ctx.unique("write-timeout", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("write-timeout", n);
 }
-#line 2051 "dhcp6_parser.cc"
+#line 2052 "dhcp6_parser.cc"
     break;
 
   case 276: // tcp_user_timeout: "tcp-user-timeout" ":" "integer"
-#line 1115 "dhcp6_parser.yy"
+#line 1116 "dhcp6_parser.yy"
                                                  {
     ctx.unique("tcp-user-timeout", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("tcp-user-timeout", n);
 }
-#line 2061 "dhcp6_parser.cc"
+#line 2062 "dhcp6_parser.cc"
     break;
 
   case 277: // reconnect_wait_time: "reconnect-wait-time" ":" "integer"
-#line 1122 "dhcp6_parser.yy"
+#line 1123 "dhcp6_parser.yy"
                                                        {
     ctx.unique("reconnect-wait-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("reconnect-wait-time", n);
 }
-#line 2071 "dhcp6_parser.cc"
+#line 2072 "dhcp6_parser.cc"
     break;
 
   case 278: // $@43: %empty
-#line 1128 "dhcp6_parser.yy"
+#line 1129 "dhcp6_parser.yy"
                  {
     ctx.unique("on-fail", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.DATABASE_ON_FAIL);
 }
-#line 2080 "dhcp6_parser.cc"
+#line 2081 "dhcp6_parser.cc"
     break;
 
   case 279: // on_fail: "on-fail" $@43 ":" on_fail_mode
-#line 1131 "dhcp6_parser.yy"
+#line 1132 "dhcp6_parser.yy"
                      {
     ctx.stack_.back()->set("on-fail", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 2089 "dhcp6_parser.cc"
+#line 2090 "dhcp6_parser.cc"
     break;
 
   case 280: // on_fail_mode: "stop-retry-exit"
-#line 1136 "dhcp6_parser.yy"
+#line 1137 "dhcp6_parser.yy"
                               { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("stop-retry-exit", ctx.loc2pos(yystack_[0].location))); }
-#line 2095 "dhcp6_parser.cc"
+#line 2096 "dhcp6_parser.cc"
     break;
 
   case 281: // on_fail_mode: "serve-retry-exit"
-#line 1137 "dhcp6_parser.yy"
+#line 1138 "dhcp6_parser.yy"
                                { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("serve-retry-exit", ctx.loc2pos(yystack_[0].location))); }
-#line 2101 "dhcp6_parser.cc"
+#line 2102 "dhcp6_parser.cc"
     break;
 
   case 282: // on_fail_mode: "serve-retry-continue"
-#line 1138 "dhcp6_parser.yy"
+#line 1139 "dhcp6_parser.yy"
                                    { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("serve-retry-continue", ctx.loc2pos(yystack_[0].location))); }
-#line 2107 "dhcp6_parser.cc"
+#line 2108 "dhcp6_parser.cc"
     break;
 
   case 283: // retry_on_startup: "retry-on-startup" ":" "boolean"
-#line 1141 "dhcp6_parser.yy"
+#line 1142 "dhcp6_parser.yy"
                                                  {
     ctx.unique("retry-on-startup", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("retry-on-startup", n);
 }
-#line 2117 "dhcp6_parser.cc"
+#line 2118 "dhcp6_parser.cc"
     break;
 
   case 284: // max_row_errors: "max-row-errors" ":" "integer"
-#line 1147 "dhcp6_parser.yy"
+#line 1148 "dhcp6_parser.yy"
                                              {
     ctx.unique("max-row-errors", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-row-errors", n);
 }
-#line 2127 "dhcp6_parser.cc"
+#line 2128 "dhcp6_parser.cc"
     break;
 
   case 285: // max_reconnect_tries: "max-reconnect-tries" ":" "integer"
-#line 1153 "dhcp6_parser.yy"
+#line 1154 "dhcp6_parser.yy"
                                                        {
     ctx.unique("max-reconnect-tries", ctx.loc2pos(yystack_[2].location));
     ElementPtr n(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-reconnect-tries", n);
 }
-#line 2137 "dhcp6_parser.cc"
+#line 2138 "dhcp6_parser.cc"
     break;
 
   case 286: // $@44: %empty
-#line 1159 "dhcp6_parser.yy"
+#line 1160 "dhcp6_parser.yy"
                            {
     ctx.unique("trust-anchor", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2146 "dhcp6_parser.cc"
+#line 2147 "dhcp6_parser.cc"
     break;
 
   case 287: // trust_anchor: "trust-anchor" $@44 ":" "constant string"
-#line 1162 "dhcp6_parser.yy"
+#line 1163 "dhcp6_parser.yy"
                {
     ElementPtr ca(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("trust-anchor", ca);
     ctx.leave();
 }
-#line 2156 "dhcp6_parser.cc"
+#line 2157 "dhcp6_parser.cc"
     break;
 
   case 288: // $@45: %empty
-#line 1168 "dhcp6_parser.yy"
+#line 1169 "dhcp6_parser.yy"
                      {
     ctx.unique("cert-file", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2165 "dhcp6_parser.cc"
+#line 2166 "dhcp6_parser.cc"
     break;
 
   case 289: // cert_file: "cert-file" $@45 ":" "constant string"
-#line 1171 "dhcp6_parser.yy"
+#line 1172 "dhcp6_parser.yy"
                {
     ElementPtr cert(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("cert-file", cert);
     ctx.leave();
 }
-#line 2175 "dhcp6_parser.cc"
+#line 2176 "dhcp6_parser.cc"
     break;
 
   case 290: // $@46: %empty
-#line 1177 "dhcp6_parser.yy"
+#line 1178 "dhcp6_parser.yy"
                    {
     ctx.unique("key-file", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2184 "dhcp6_parser.cc"
+#line 2185 "dhcp6_parser.cc"
     break;
 
   case 291: // key_file: "key-file" $@46 ":" "constant string"
-#line 1180 "dhcp6_parser.yy"
+#line 1181 "dhcp6_parser.yy"
                {
     ElementPtr key(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("key-file", key);
     ctx.leave();
 }
-#line 2194 "dhcp6_parser.cc"
+#line 2195 "dhcp6_parser.cc"
     break;
 
   case 292: // $@47: %empty
-#line 1186 "dhcp6_parser.yy"
+#line 1187 "dhcp6_parser.yy"
                          {
     ctx.unique("cipher-list", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2203 "dhcp6_parser.cc"
+#line 2204 "dhcp6_parser.cc"
     break;
 
   case 293: // cipher_list: "cipher-list" $@47 ":" "constant string"
-#line 1189 "dhcp6_parser.yy"
+#line 1190 "dhcp6_parser.yy"
                {
     ElementPtr cl(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("cipher-list", cl);
     ctx.leave();
 }
-#line 2213 "dhcp6_parser.cc"
+#line 2214 "dhcp6_parser.cc"
     break;
 
   case 294: // $@48: %empty
-#line 1195 "dhcp6_parser.yy"
+#line 1196 "dhcp6_parser.yy"
                              {
     ctx.unique("sanity-checks", ctx.loc2pos(yystack_[0].location));
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -2221,37 +2222,37 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(m);
     ctx.enter(ctx.SANITY_CHECKS);
 }
-#line 2225 "dhcp6_parser.cc"
+#line 2226 "dhcp6_parser.cc"
     break;
 
   case 295: // sanity_checks: "sanity-checks" $@48 ":" "{" sanity_checks_params "}"
-#line 1201 "dhcp6_parser.yy"
+#line 1202 "dhcp6_parser.yy"
                                                            {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2234 "dhcp6_parser.cc"
+#line 2235 "dhcp6_parser.cc"
     break;
 
   case 298: // sanity_checks_params: sanity_checks_params ","
-#line 1208 "dhcp6_parser.yy"
+#line 1209 "dhcp6_parser.yy"
                                                  {
                         ctx.warnAboutExtraCommas(yystack_[0].location);
                         }
-#line 2242 "dhcp6_parser.cc"
+#line 2243 "dhcp6_parser.cc"
     break;
 
   case 301: // $@49: %empty
-#line 1217 "dhcp6_parser.yy"
+#line 1218 "dhcp6_parser.yy"
                            {
     ctx.unique("lease-checks", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2251 "dhcp6_parser.cc"
+#line 2252 "dhcp6_parser.cc"
     break;
 
   case 302: // lease_checks: "lease-checks" $@49 ":" "constant string"
-#line 1220 "dhcp6_parser.yy"
+#line 1221 "dhcp6_parser.yy"
                {
 
     if ( (string(yystack_[0].value.as < std::string > ()) == "none") ||
@@ -2267,20 +2268,20 @@ namespace isc { namespace dhcp {
               ", supported values are: none, warn, fix, fix-del, del");
     }
 }
-#line 2271 "dhcp6_parser.cc"
+#line 2272 "dhcp6_parser.cc"
     break;
 
   case 303: // $@50: %empty
-#line 1236 "dhcp6_parser.yy"
+#line 1237 "dhcp6_parser.yy"
                                            {
     ctx.unique("extended-info-checks", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2280 "dhcp6_parser.cc"
+#line 2281 "dhcp6_parser.cc"
     break;
 
   case 304: // extended_info_checks: "extended-info-checks" $@50 ":" "constant string"
-#line 1239 "dhcp6_parser.yy"
+#line 1240 "dhcp6_parser.yy"
                {
 
     if ( (string(yystack_[0].value.as < std::string > ()) == "none") ||
@@ -2295,11 +2296,11 @@ namespace isc { namespace dhcp {
               ", supported values are: none, fix, strict, pedantic");
     }
 }
-#line 2299 "dhcp6_parser.cc"
+#line 2300 "dhcp6_parser.cc"
     break;
 
   case 305: // $@51: %empty
-#line 1254 "dhcp6_parser.yy"
+#line 1255 "dhcp6_parser.yy"
                          {
     ctx.unique("mac-sources", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2307,46 +2308,46 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.MAC_SOURCES);
 }
-#line 2311 "dhcp6_parser.cc"
+#line 2312 "dhcp6_parser.cc"
     break;
 
   case 306: // mac_sources: "mac-sources" $@51 ":" "[" mac_sources_list "]"
-#line 1260 "dhcp6_parser.yy"
+#line 1261 "dhcp6_parser.yy"
                                                          {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2320 "dhcp6_parser.cc"
+#line 2321 "dhcp6_parser.cc"
     break;
 
   case 309: // mac_sources_list: mac_sources_list ","
-#line 1267 "dhcp6_parser.yy"
+#line 1268 "dhcp6_parser.yy"
                                          {
                     ctx.warnAboutExtraCommas(yystack_[0].location);
                     }
-#line 2328 "dhcp6_parser.cc"
+#line 2329 "dhcp6_parser.cc"
     break;
 
   case 312: // duid_id: "duid"
-#line 1276 "dhcp6_parser.yy"
+#line 1277 "dhcp6_parser.yy"
               {
     ElementPtr duid(new StringElement("duid", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(duid);
 }
-#line 2337 "dhcp6_parser.cc"
+#line 2338 "dhcp6_parser.cc"
     break;
 
   case 313: // string_id: "constant string"
-#line 1281 "dhcp6_parser.yy"
+#line 1282 "dhcp6_parser.yy"
                   {
     ElementPtr duid(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(duid);
 }
-#line 2346 "dhcp6_parser.cc"
+#line 2347 "dhcp6_parser.cc"
     break;
 
   case 314: // $@52: %empty
-#line 1286 "dhcp6_parser.yy"
+#line 1287 "dhcp6_parser.yy"
                                                            {
     ctx.unique("host-reservation-identifiers", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2354,46 +2355,46 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.HOST_RESERVATION_IDENTIFIERS);
 }
-#line 2358 "dhcp6_parser.cc"
+#line 2359 "dhcp6_parser.cc"
     break;
 
   case 315: // host_reservation_identifiers: "host-reservation-identifiers" $@52 ":" "[" host_reservation_identifiers_list "]"
-#line 1292 "dhcp6_parser.yy"
+#line 1293 "dhcp6_parser.yy"
                                                                           {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2367 "dhcp6_parser.cc"
+#line 2368 "dhcp6_parser.cc"
     break;
 
   case 318: // host_reservation_identifiers_list: host_reservation_identifiers_list ","
-#line 1299 "dhcp6_parser.yy"
+#line 1300 "dhcp6_parser.yy"
                                               {
         ctx.warnAboutExtraCommas(yystack_[0].location);
         }
-#line 2375 "dhcp6_parser.cc"
+#line 2376 "dhcp6_parser.cc"
     break;
 
   case 322: // hw_address_id: "hw-address"
-#line 1309 "dhcp6_parser.yy"
+#line 1310 "dhcp6_parser.yy"
                           {
     ElementPtr hwaddr(new StringElement("hw-address", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(hwaddr);
 }
-#line 2384 "dhcp6_parser.cc"
+#line 2385 "dhcp6_parser.cc"
     break;
 
   case 323: // flex_id: "flex-id"
-#line 1314 "dhcp6_parser.yy"
+#line 1315 "dhcp6_parser.yy"
                  {
     ElementPtr flex_id(new StringElement("flex-id", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(flex_id);
 }
-#line 2393 "dhcp6_parser.cc"
+#line 2394 "dhcp6_parser.cc"
     break;
 
   case 324: // $@53: %empty
-#line 1321 "dhcp6_parser.yy"
+#line 1322 "dhcp6_parser.yy"
                                                {
     ctx.unique("relay-supplied-options", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2401,20 +2402,20 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2405 "dhcp6_parser.cc"
+#line 2406 "dhcp6_parser.cc"
     break;
 
   case 325: // relay_supplied_options: "relay-supplied-options" $@53 ":" "[" list_content "]"
-#line 1327 "dhcp6_parser.yy"
+#line 1328 "dhcp6_parser.yy"
                                                      {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2414 "dhcp6_parser.cc"
+#line 2415 "dhcp6_parser.cc"
     break;
 
   case 326: // $@54: %empty
-#line 1334 "dhcp6_parser.yy"
+#line 1335 "dhcp6_parser.yy"
                                            {
     ctx.unique("multi-threading", ctx.loc2pos(yystack_[0].location));
     ElementPtr mt(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -2422,60 +2423,60 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(mt);
     ctx.enter(ctx.DHCP_MULTI_THREADING);
 }
-#line 2426 "dhcp6_parser.cc"
+#line 2427 "dhcp6_parser.cc"
     break;
 
   case 327: // dhcp_multi_threading: "multi-threading" $@54 ":" "{" multi_threading_params "}"
-#line 1340 "dhcp6_parser.yy"
+#line 1341 "dhcp6_parser.yy"
                                                              {
     // The enable parameter is required.
     ctx.require("enable-multi-threading", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2437 "dhcp6_parser.cc"
+#line 2438 "dhcp6_parser.cc"
     break;
 
   case 330: // multi_threading_params: multi_threading_params ","
-#line 1349 "dhcp6_parser.yy"
+#line 1350 "dhcp6_parser.yy"
                                                      {
                           ctx.warnAboutExtraCommas(yystack_[0].location);
                           }
-#line 2445 "dhcp6_parser.cc"
+#line 2446 "dhcp6_parser.cc"
     break;
 
   case 337: // enable_multi_threading: "enable-multi-threading" ":" "boolean"
-#line 1362 "dhcp6_parser.yy"
+#line 1363 "dhcp6_parser.yy"
                                                              {
     ctx.unique("enable-multi-threading", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("enable-multi-threading", b);
 }
-#line 2455 "dhcp6_parser.cc"
+#line 2456 "dhcp6_parser.cc"
     break;
 
   case 338: // thread_pool_size: "thread-pool-size" ":" "integer"
-#line 1368 "dhcp6_parser.yy"
+#line 1369 "dhcp6_parser.yy"
                                                  {
     ctx.unique("thread-pool-size", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("thread-pool-size", prf);
 }
-#line 2465 "dhcp6_parser.cc"
+#line 2466 "dhcp6_parser.cc"
     break;
 
   case 339: // packet_queue_size: "packet-queue-size" ":" "integer"
-#line 1374 "dhcp6_parser.yy"
+#line 1375 "dhcp6_parser.yy"
                                                    {
     ctx.unique("packet-queue-size", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("packet-queue-size", prf);
 }
-#line 2475 "dhcp6_parser.cc"
+#line 2476 "dhcp6_parser.cc"
     break;
 
   case 340: // $@55: %empty
-#line 1380 "dhcp6_parser.yy"
+#line 1381 "dhcp6_parser.yy"
                                  {
     ctx.unique("hooks-libraries", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2483,113 +2484,113 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.HOOKS_LIBRARIES);
 }
-#line 2487 "dhcp6_parser.cc"
+#line 2488 "dhcp6_parser.cc"
     break;
 
   case 341: // hooks_libraries: "hooks-libraries" $@55 ":" "[" hooks_libraries_list "]"
-#line 1386 "dhcp6_parser.yy"
+#line 1387 "dhcp6_parser.yy"
                                                              {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2496 "dhcp6_parser.cc"
+#line 2497 "dhcp6_parser.cc"
     break;
 
   case 346: // not_empty_hooks_libraries_list: not_empty_hooks_libraries_list ","
-#line 1397 "dhcp6_parser.yy"
+#line 1398 "dhcp6_parser.yy"
                                            {
         ctx.warnAboutExtraCommas(yystack_[0].location);
         }
-#line 2504 "dhcp6_parser.cc"
+#line 2505 "dhcp6_parser.cc"
     break;
 
   case 347: // $@56: %empty
-#line 1402 "dhcp6_parser.yy"
+#line 1403 "dhcp6_parser.yy"
                               {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 2514 "dhcp6_parser.cc"
+#line 2515 "dhcp6_parser.cc"
     break;
 
   case 348: // hooks_library: "{" $@56 hooks_params "}"
-#line 1406 "dhcp6_parser.yy"
+#line 1407 "dhcp6_parser.yy"
                               {
     // The library hooks parameter is required
     ctx.require("library", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 2524 "dhcp6_parser.cc"
+#line 2525 "dhcp6_parser.cc"
     break;
 
   case 349: // $@57: %empty
-#line 1412 "dhcp6_parser.yy"
+#line 1413 "dhcp6_parser.yy"
                                   {
     // Parse the hooks-libraries list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 2534 "dhcp6_parser.cc"
+#line 2535 "dhcp6_parser.cc"
     break;
 
   case 350: // sub_hooks_library: "{" $@57 hooks_params "}"
-#line 1416 "dhcp6_parser.yy"
+#line 1417 "dhcp6_parser.yy"
                               {
     // The library hooks parameter is required
     ctx.require("library", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 2544 "dhcp6_parser.cc"
+#line 2545 "dhcp6_parser.cc"
     break;
 
   case 353: // hooks_params: hooks_params ","
-#line 1424 "dhcp6_parser.yy"
+#line 1425 "dhcp6_parser.yy"
                                  {
                 ctx.warnAboutExtraCommas(yystack_[0].location);
                 }
-#line 2552 "dhcp6_parser.cc"
+#line 2553 "dhcp6_parser.cc"
     break;
 
   case 357: // $@58: %empty
-#line 1434 "dhcp6_parser.yy"
+#line 1435 "dhcp6_parser.yy"
                  {
     ctx.unique("library", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2561 "dhcp6_parser.cc"
+#line 2562 "dhcp6_parser.cc"
     break;
 
   case 358: // library: "library" $@58 ":" "constant string"
-#line 1437 "dhcp6_parser.yy"
+#line 1438 "dhcp6_parser.yy"
                {
     ElementPtr lib(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("library", lib);
     ctx.leave();
 }
-#line 2571 "dhcp6_parser.cc"
+#line 2572 "dhcp6_parser.cc"
     break;
 
   case 359: // $@59: %empty
-#line 1443 "dhcp6_parser.yy"
+#line 1444 "dhcp6_parser.yy"
                        {
     ctx.unique("parameters", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2580 "dhcp6_parser.cc"
+#line 2581 "dhcp6_parser.cc"
     break;
 
   case 360: // parameters: "parameters" $@59 ":" map_value
-#line 1446 "dhcp6_parser.yy"
+#line 1447 "dhcp6_parser.yy"
                   {
     ctx.stack_.back()->set("parameters", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 2589 "dhcp6_parser.cc"
+#line 2590 "dhcp6_parser.cc"
     break;
 
   case 361: // $@60: %empty
-#line 1452 "dhcp6_parser.yy"
+#line 1453 "dhcp6_parser.yy"
                                                      {
     ctx.unique("expired-leases-processing", ctx.loc2pos(yystack_[0].location));
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -2597,89 +2598,89 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(m);
     ctx.enter(ctx.EXPIRED_LEASES_PROCESSING);
 }
-#line 2601 "dhcp6_parser.cc"
+#line 2602 "dhcp6_parser.cc"
     break;
 
   case 362: // expired_leases_processing: "expired-leases-processing" $@60 ":" "{" expired_leases_params "}"
-#line 1458 "dhcp6_parser.yy"
+#line 1459 "dhcp6_parser.yy"
                                                             {
     // No expired lease parameter is required
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2611 "dhcp6_parser.cc"
+#line 2612 "dhcp6_parser.cc"
     break;
 
   case 365: // expired_leases_params: expired_leases_params ","
-#line 1466 "dhcp6_parser.yy"
+#line 1467 "dhcp6_parser.yy"
                                                    {
                          ctx.warnAboutExtraCommas(yystack_[0].location);
                          }
-#line 2619 "dhcp6_parser.cc"
+#line 2620 "dhcp6_parser.cc"
     break;
 
   case 372: // reclaim_timer_wait_time: "reclaim-timer-wait-time" ":" "integer"
-#line 1479 "dhcp6_parser.yy"
+#line 1480 "dhcp6_parser.yy"
                                                                {
     ctx.unique("reclaim-timer-wait-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("reclaim-timer-wait-time", value);
 }
-#line 2629 "dhcp6_parser.cc"
+#line 2630 "dhcp6_parser.cc"
     break;
 
   case 373: // flush_reclaimed_timer_wait_time: "flush-reclaimed-timer-wait-time" ":" "integer"
-#line 1485 "dhcp6_parser.yy"
+#line 1486 "dhcp6_parser.yy"
                                                                                {
     ctx.unique("flush-reclaimed-timer-wait-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("flush-reclaimed-timer-wait-time", value);
 }
-#line 2639 "dhcp6_parser.cc"
+#line 2640 "dhcp6_parser.cc"
     break;
 
   case 374: // hold_reclaimed_time: "hold-reclaimed-time" ":" "integer"
-#line 1491 "dhcp6_parser.yy"
+#line 1492 "dhcp6_parser.yy"
                                                        {
     ctx.unique("hold-reclaimed-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hold-reclaimed-time", value);
 }
-#line 2649 "dhcp6_parser.cc"
+#line 2650 "dhcp6_parser.cc"
     break;
 
   case 375: // max_reclaim_leases: "max-reclaim-leases" ":" "integer"
-#line 1497 "dhcp6_parser.yy"
+#line 1498 "dhcp6_parser.yy"
                                                      {
     ctx.unique("max-reclaim-leases", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-reclaim-leases", value);
 }
-#line 2659 "dhcp6_parser.cc"
+#line 2660 "dhcp6_parser.cc"
     break;
 
   case 376: // max_reclaim_time: "max-reclaim-time" ":" "integer"
-#line 1503 "dhcp6_parser.yy"
+#line 1504 "dhcp6_parser.yy"
                                                  {
     ctx.unique("max-reclaim-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-reclaim-time", value);
 }
-#line 2669 "dhcp6_parser.cc"
+#line 2670 "dhcp6_parser.cc"
     break;
 
   case 377: // unwarned_reclaim_cycles: "unwarned-reclaim-cycles" ":" "integer"
-#line 1509 "dhcp6_parser.yy"
+#line 1510 "dhcp6_parser.yy"
                                                                {
     ctx.unique("unwarned-reclaim-cycles", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("unwarned-reclaim-cycles", value);
 }
-#line 2679 "dhcp6_parser.cc"
+#line 2680 "dhcp6_parser.cc"
     break;
 
   case 378: // $@61: %empty
-#line 1518 "dhcp6_parser.yy"
+#line 1519 "dhcp6_parser.yy"
                       {
     ctx.unique("subnet6", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2687,38 +2688,38 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.SUBNET6);
 }
-#line 2691 "dhcp6_parser.cc"
+#line 2692 "dhcp6_parser.cc"
     break;
 
   case 379: // subnet6_list: "subnet6" $@61 ":" "[" subnet6_list_content "]"
-#line 1524 "dhcp6_parser.yy"
+#line 1525 "dhcp6_parser.yy"
                                                              {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2700 "dhcp6_parser.cc"
+#line 2701 "dhcp6_parser.cc"
     break;
 
   case 384: // not_empty_subnet6_list: not_empty_subnet6_list ","
-#line 1538 "dhcp6_parser.yy"
+#line 1539 "dhcp6_parser.yy"
                                                      {
                           ctx.warnAboutExtraCommas(yystack_[0].location);
                           }
-#line 2708 "dhcp6_parser.cc"
+#line 2709 "dhcp6_parser.cc"
     break;
 
   case 385: // $@62: %empty
-#line 1547 "dhcp6_parser.yy"
+#line 1548 "dhcp6_parser.yy"
                         {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 2718 "dhcp6_parser.cc"
+#line 2719 "dhcp6_parser.cc"
     break;
 
   case 386: // subnet6: "{" $@62 subnet6_params "}"
-#line 1551 "dhcp6_parser.yy"
+#line 1552 "dhcp6_parser.yy"
                                 {
     // Once we reached this place, the subnet parsing is now complete.
     // If we want to, we can implement default values here.
@@ -2740,115 +2741,115 @@ namespace isc { namespace dhcp {
     ctx.require("subnet", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 2744 "dhcp6_parser.cc"
+#line 2745 "dhcp6_parser.cc"
     break;
 
   case 387: // $@63: %empty
-#line 1573 "dhcp6_parser.yy"
+#line 1574 "dhcp6_parser.yy"
                             {
     // Parse the subnet6 list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 2754 "dhcp6_parser.cc"
+#line 2755 "dhcp6_parser.cc"
     break;
 
   case 388: // sub_subnet6: "{" $@63 subnet6_params "}"
-#line 1577 "dhcp6_parser.yy"
+#line 1578 "dhcp6_parser.yy"
                                 {
     // The subnet subnet6 parameter is required
     ctx.require("subnet", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 2764 "dhcp6_parser.cc"
+#line 2765 "dhcp6_parser.cc"
     break;
 
   case 391: // subnet6_params: subnet6_params ","
-#line 1586 "dhcp6_parser.yy"
+#line 1587 "dhcp6_parser.yy"
                                      {
                   ctx.warnAboutExtraCommas(yystack_[0].location);
                   }
-#line 2772 "dhcp6_parser.cc"
+#line 2773 "dhcp6_parser.cc"
     break;
 
   case 438: // $@64: %empty
-#line 1640 "dhcp6_parser.yy"
+#line 1641 "dhcp6_parser.yy"
                {
     ctx.unique("subnet", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2781 "dhcp6_parser.cc"
+#line 2782 "dhcp6_parser.cc"
     break;
 
   case 439: // subnet: "subnet" $@64 ":" "constant string"
-#line 1643 "dhcp6_parser.yy"
+#line 1644 "dhcp6_parser.yy"
                {
     ElementPtr subnet(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("subnet", subnet);
     ctx.leave();
 }
-#line 2791 "dhcp6_parser.cc"
+#line 2792 "dhcp6_parser.cc"
     break;
 
   case 440: // $@65: %empty
-#line 1649 "dhcp6_parser.yy"
+#line 1650 "dhcp6_parser.yy"
                      {
     ctx.unique("interface", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2800 "dhcp6_parser.cc"
+#line 2801 "dhcp6_parser.cc"
     break;
 
   case 441: // interface: "interface" $@65 ":" "constant string"
-#line 1652 "dhcp6_parser.yy"
+#line 1653 "dhcp6_parser.yy"
                {
     ElementPtr iface(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("interface", iface);
     ctx.leave();
 }
-#line 2810 "dhcp6_parser.cc"
+#line 2811 "dhcp6_parser.cc"
     break;
 
   case 442: // $@66: %empty
-#line 1658 "dhcp6_parser.yy"
+#line 1659 "dhcp6_parser.yy"
                            {
     ctx.unique("interface-id", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2819 "dhcp6_parser.cc"
+#line 2820 "dhcp6_parser.cc"
     break;
 
   case 443: // interface_id: "interface-id" $@66 ":" "constant string"
-#line 1661 "dhcp6_parser.yy"
+#line 1662 "dhcp6_parser.yy"
                {
     ElementPtr iface(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("interface-id", iface);
     ctx.leave();
 }
-#line 2829 "dhcp6_parser.cc"
+#line 2830 "dhcp6_parser.cc"
     break;
 
   case 444: // $@67: %empty
-#line 1667 "dhcp6_parser.yy"
+#line 1668 "dhcp6_parser.yy"
                            {
     ctx.unique("client-class", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2838 "dhcp6_parser.cc"
+#line 2839 "dhcp6_parser.cc"
     break;
 
   case 445: // client_class: "client-class" $@67 ":" "constant string"
-#line 1670 "dhcp6_parser.yy"
+#line 1671 "dhcp6_parser.yy"
                {
     ElementPtr cls(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("client-class", cls);
     ctx.leave();
 }
-#line 2848 "dhcp6_parser.cc"
+#line 2849 "dhcp6_parser.cc"
     break;
 
   case 446: // $@68: %empty
-#line 1676 "dhcp6_parser.yy"
+#line 1677 "dhcp6_parser.yy"
                                                {
     ctx.unique("require-client-classes", ctx.loc2pos(yystack_[0].location));
     ElementPtr c(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2856,70 +2857,70 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(c);
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 2860 "dhcp6_parser.cc"
+#line 2861 "dhcp6_parser.cc"
     break;
 
   case 447: // require_client_classes: "require-client-classes" $@68 ":" list_strings
-#line 1682 "dhcp6_parser.yy"
+#line 1683 "dhcp6_parser.yy"
                      {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2869 "dhcp6_parser.cc"
+#line 2870 "dhcp6_parser.cc"
     break;
 
   case 448: // reservations_global: "reservations-global" ":" "boolean"
-#line 1687 "dhcp6_parser.yy"
+#line 1688 "dhcp6_parser.yy"
                                                        {
     ctx.unique("reservations-global", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("reservations-global", b);
 }
-#line 2879 "dhcp6_parser.cc"
+#line 2880 "dhcp6_parser.cc"
     break;
 
   case 449: // reservations_in_subnet: "reservations-in-subnet" ":" "boolean"
-#line 1693 "dhcp6_parser.yy"
+#line 1694 "dhcp6_parser.yy"
                                                              {
     ctx.unique("reservations-in-subnet", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("reservations-in-subnet", b);
 }
-#line 2889 "dhcp6_parser.cc"
+#line 2890 "dhcp6_parser.cc"
     break;
 
   case 450: // reservations_out_of_pool: "reservations-out-of-pool" ":" "boolean"
-#line 1699 "dhcp6_parser.yy"
+#line 1700 "dhcp6_parser.yy"
                                                                  {
     ctx.unique("reservations-out-of-pool", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("reservations-out-of-pool", b);
 }
-#line 2899 "dhcp6_parser.cc"
+#line 2900 "dhcp6_parser.cc"
     break;
 
   case 451: // id: "id" ":" "integer"
-#line 1705 "dhcp6_parser.yy"
+#line 1706 "dhcp6_parser.yy"
                      {
     ctx.unique("id", ctx.loc2pos(yystack_[2].location));
     ElementPtr id(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("id", id);
 }
-#line 2909 "dhcp6_parser.cc"
+#line 2910 "dhcp6_parser.cc"
     break;
 
   case 452: // rapid_commit: "rapid-commit" ":" "boolean"
-#line 1711 "dhcp6_parser.yy"
+#line 1712 "dhcp6_parser.yy"
                                          {
     ctx.unique("rapid-commit", ctx.loc2pos(yystack_[2].location));
     ElementPtr rc(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("rapid-commit", rc);
 }
-#line 2919 "dhcp6_parser.cc"
+#line 2920 "dhcp6_parser.cc"
     break;
 
   case 453: // $@69: %empty
-#line 1719 "dhcp6_parser.yy"
+#line 1720 "dhcp6_parser.yy"
                                  {
     ctx.unique("shared-networks", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2927,54 +2928,54 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.SHARED_NETWORK);
 }
-#line 2931 "dhcp6_parser.cc"
+#line 2932 "dhcp6_parser.cc"
     break;
 
   case 454: // shared_networks: "shared-networks" $@69 ":" "[" shared_networks_content "]"
-#line 1725 "dhcp6_parser.yy"
+#line 1726 "dhcp6_parser.yy"
                                                                 {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2940 "dhcp6_parser.cc"
+#line 2941 "dhcp6_parser.cc"
     break;
 
   case 459: // shared_networks_list: shared_networks_list ","
-#line 1738 "dhcp6_parser.yy"
+#line 1739 "dhcp6_parser.yy"
                                                  {
                         ctx.warnAboutExtraCommas(yystack_[0].location);
                         }
-#line 2948 "dhcp6_parser.cc"
+#line 2949 "dhcp6_parser.cc"
     break;
 
   case 460: // $@70: %empty
-#line 1743 "dhcp6_parser.yy"
+#line 1744 "dhcp6_parser.yy"
                                {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 2958 "dhcp6_parser.cc"
+#line 2959 "dhcp6_parser.cc"
     break;
 
   case 461: // shared_network: "{" $@70 shared_network_params "}"
-#line 1747 "dhcp6_parser.yy"
+#line 1748 "dhcp6_parser.yy"
                                        {
     ctx.stack_.pop_back();
 }
-#line 2966 "dhcp6_parser.cc"
+#line 2967 "dhcp6_parser.cc"
     break;
 
   case 464: // shared_network_params: shared_network_params ","
-#line 1753 "dhcp6_parser.yy"
+#line 1754 "dhcp6_parser.yy"
                                                    {
                          ctx.warnAboutExtraCommas(yystack_[0].location);
                          }
-#line 2974 "dhcp6_parser.cc"
+#line 2975 "dhcp6_parser.cc"
     break;
 
   case 508: // $@71: %empty
-#line 1807 "dhcp6_parser.yy"
+#line 1808 "dhcp6_parser.yy"
                             {
     ctx.unique("option-def", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -2982,55 +2983,55 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.OPTION_DEF);
 }
-#line 2986 "dhcp6_parser.cc"
+#line 2987 "dhcp6_parser.cc"
     break;
 
   case 509: // option_def_list: "option-def" $@71 ":" "[" option_def_list_content "]"
-#line 1813 "dhcp6_parser.yy"
+#line 1814 "dhcp6_parser.yy"
                                                                 {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 2995 "dhcp6_parser.cc"
+#line 2996 "dhcp6_parser.cc"
     break;
 
   case 510: // $@72: %empty
-#line 1821 "dhcp6_parser.yy"
+#line 1822 "dhcp6_parser.yy"
                                     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3004 "dhcp6_parser.cc"
+#line 3005 "dhcp6_parser.cc"
     break;
 
   case 511: // sub_option_def_list: "{" $@72 option_def_list "}"
-#line 1824 "dhcp6_parser.yy"
+#line 1825 "dhcp6_parser.yy"
                                  {
     // parsing completed
 }
-#line 3012 "dhcp6_parser.cc"
+#line 3013 "dhcp6_parser.cc"
     break;
 
   case 516: // not_empty_option_def_list: not_empty_option_def_list ","
-#line 1836 "dhcp6_parser.yy"
+#line 1837 "dhcp6_parser.yy"
                                                            {
                              ctx.warnAboutExtraCommas(yystack_[0].location);
                              }
-#line 3020 "dhcp6_parser.cc"
+#line 3021 "dhcp6_parser.cc"
     break;
 
   case 517: // $@73: %empty
-#line 1843 "dhcp6_parser.yy"
+#line 1844 "dhcp6_parser.yy"
                                  {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3030 "dhcp6_parser.cc"
+#line 3031 "dhcp6_parser.cc"
     break;
 
   case 518: // option_def_entry: "{" $@73 option_def_params "}"
-#line 1847 "dhcp6_parser.yy"
+#line 1848 "dhcp6_parser.yy"
                                    {
     // The name, code and type option def parameters are required.
     ctx.require("name", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
@@ -3038,21 +3039,21 @@ namespace isc { namespace dhcp {
     ctx.require("type", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 3042 "dhcp6_parser.cc"
+#line 3043 "dhcp6_parser.cc"
     break;
 
   case 519: // $@74: %empty
-#line 1858 "dhcp6_parser.yy"
+#line 1859 "dhcp6_parser.yy"
                                {
     // Parse the option-def list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3052 "dhcp6_parser.cc"
+#line 3053 "dhcp6_parser.cc"
     break;
 
   case 520: // sub_option_def: "{" $@74 option_def_params "}"
-#line 1862 "dhcp6_parser.yy"
+#line 1863 "dhcp6_parser.yy"
                                    {
     // The name, code and type option def parameters are required.
     ctx.require("name", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
@@ -3060,115 +3061,115 @@ namespace isc { namespace dhcp {
     ctx.require("type", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 3064 "dhcp6_parser.cc"
+#line 3065 "dhcp6_parser.cc"
     break;
 
   case 525: // not_empty_option_def_params: not_empty_option_def_params ","
-#line 1878 "dhcp6_parser.yy"
+#line 1879 "dhcp6_parser.yy"
                                                                {
                                ctx.warnAboutExtraCommas(yystack_[0].location);
                                }
-#line 3072 "dhcp6_parser.cc"
+#line 3073 "dhcp6_parser.cc"
     break;
 
   case 537: // code: "code" ":" "integer"
-#line 1897 "dhcp6_parser.yy"
+#line 1898 "dhcp6_parser.yy"
                          {
     ctx.unique("code", ctx.loc2pos(yystack_[2].location));
     ElementPtr code(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("code", code);
 }
-#line 3082 "dhcp6_parser.cc"
+#line 3083 "dhcp6_parser.cc"
     break;
 
   case 539: // $@75: %empty
-#line 1905 "dhcp6_parser.yy"
+#line 1906 "dhcp6_parser.yy"
                       {
     ctx.unique("type", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3091 "dhcp6_parser.cc"
+#line 3092 "dhcp6_parser.cc"
     break;
 
   case 540: // option_def_type: "type" $@75 ":" "constant string"
-#line 1908 "dhcp6_parser.yy"
+#line 1909 "dhcp6_parser.yy"
                {
     ElementPtr prf(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("type", prf);
     ctx.leave();
 }
-#line 3101 "dhcp6_parser.cc"
+#line 3102 "dhcp6_parser.cc"
     break;
 
   case 541: // $@76: %empty
-#line 1914 "dhcp6_parser.yy"
+#line 1915 "dhcp6_parser.yy"
                                       {
     ctx.unique("record-types", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3110 "dhcp6_parser.cc"
+#line 3111 "dhcp6_parser.cc"
     break;
 
   case 542: // option_def_record_types: "record-types" $@76 ":" "constant string"
-#line 1917 "dhcp6_parser.yy"
+#line 1918 "dhcp6_parser.yy"
                {
     ElementPtr rtypes(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("record-types", rtypes);
     ctx.leave();
 }
-#line 3120 "dhcp6_parser.cc"
+#line 3121 "dhcp6_parser.cc"
     break;
 
   case 543: // $@77: %empty
-#line 1923 "dhcp6_parser.yy"
+#line 1924 "dhcp6_parser.yy"
              {
     ctx.unique("space", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3129 "dhcp6_parser.cc"
+#line 3130 "dhcp6_parser.cc"
     break;
 
   case 544: // space: "space" $@77 ":" "constant string"
-#line 1926 "dhcp6_parser.yy"
+#line 1927 "dhcp6_parser.yy"
                {
     ElementPtr space(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("space", space);
     ctx.leave();
 }
-#line 3139 "dhcp6_parser.cc"
+#line 3140 "dhcp6_parser.cc"
     break;
 
   case 546: // $@78: %empty
-#line 1934 "dhcp6_parser.yy"
+#line 1935 "dhcp6_parser.yy"
                                     {
     ctx.unique("encapsulate", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3148 "dhcp6_parser.cc"
+#line 3149 "dhcp6_parser.cc"
     break;
 
   case 547: // option_def_encapsulate: "encapsulate" $@78 ":" "constant string"
-#line 1937 "dhcp6_parser.yy"
+#line 1938 "dhcp6_parser.yy"
                {
     ElementPtr encap(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("encapsulate", encap);
     ctx.leave();
 }
-#line 3158 "dhcp6_parser.cc"
+#line 3159 "dhcp6_parser.cc"
     break;
 
   case 548: // option_def_array: "array" ":" "boolean"
-#line 1943 "dhcp6_parser.yy"
+#line 1944 "dhcp6_parser.yy"
                                       {
     ctx.unique("array", ctx.loc2pos(yystack_[2].location));
     ElementPtr array(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("array", array);
 }
-#line 3168 "dhcp6_parser.cc"
+#line 3169 "dhcp6_parser.cc"
     break;
 
   case 549: // $@79: %empty
-#line 1953 "dhcp6_parser.yy"
+#line 1954 "dhcp6_parser.yy"
                               {
     ctx.unique("option-data", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3176,123 +3177,123 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.OPTION_DATA);
 }
-#line 3180 "dhcp6_parser.cc"
+#line 3181 "dhcp6_parser.cc"
     break;
 
   case 550: // option_data_list: "option-data" $@79 ":" "[" option_data_list_content "]"
-#line 1959 "dhcp6_parser.yy"
+#line 1960 "dhcp6_parser.yy"
                                                                  {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3189 "dhcp6_parser.cc"
+#line 3190 "dhcp6_parser.cc"
     break;
 
   case 555: // not_empty_option_data_list: not_empty_option_data_list ","
-#line 1974 "dhcp6_parser.yy"
+#line 1975 "dhcp6_parser.yy"
                                                              {
                               ctx.warnAboutExtraCommas(yystack_[0].location);
                               }
-#line 3197 "dhcp6_parser.cc"
+#line 3198 "dhcp6_parser.cc"
     break;
 
   case 556: // $@80: %empty
-#line 1981 "dhcp6_parser.yy"
+#line 1982 "dhcp6_parser.yy"
                                   {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3207 "dhcp6_parser.cc"
+#line 3208 "dhcp6_parser.cc"
     break;
 
   case 557: // option_data_entry: "{" $@80 option_data_params "}"
-#line 1985 "dhcp6_parser.yy"
+#line 1986 "dhcp6_parser.yy"
                                     {
     /// @todo: the code or name parameters are required.
     ctx.stack_.pop_back();
 }
-#line 3216 "dhcp6_parser.cc"
+#line 3217 "dhcp6_parser.cc"
     break;
 
   case 558: // $@81: %empty
-#line 1993 "dhcp6_parser.yy"
+#line 1994 "dhcp6_parser.yy"
                                 {
     // Parse the option-data list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3226 "dhcp6_parser.cc"
+#line 3227 "dhcp6_parser.cc"
     break;
 
   case 559: // sub_option_data: "{" $@81 option_data_params "}"
-#line 1997 "dhcp6_parser.yy"
+#line 1998 "dhcp6_parser.yy"
                                     {
     /// @todo: the code or name parameters are required.
     // parsing completed
 }
-#line 3235 "dhcp6_parser.cc"
+#line 3236 "dhcp6_parser.cc"
     break;
 
   case 564: // not_empty_option_data_params: not_empty_option_data_params ","
-#line 2013 "dhcp6_parser.yy"
+#line 2014 "dhcp6_parser.yy"
                                          {
         ctx.warnAboutExtraCommas(yystack_[0].location);
         }
-#line 3243 "dhcp6_parser.cc"
+#line 3244 "dhcp6_parser.cc"
     break;
 
   case 576: // $@82: %empty
-#line 2034 "dhcp6_parser.yy"
+#line 2035 "dhcp6_parser.yy"
                        {
     ctx.unique("data", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3252 "dhcp6_parser.cc"
+#line 3253 "dhcp6_parser.cc"
     break;
 
   case 577: // option_data_data: "data" $@82 ":" "constant string"
-#line 2037 "dhcp6_parser.yy"
+#line 2038 "dhcp6_parser.yy"
                {
     ElementPtr data(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("data", data);
     ctx.leave();
 }
-#line 3262 "dhcp6_parser.cc"
+#line 3263 "dhcp6_parser.cc"
     break;
 
   case 580: // option_data_csv_format: "csv-format" ":" "boolean"
-#line 2047 "dhcp6_parser.yy"
+#line 2048 "dhcp6_parser.yy"
                                                  {
     ctx.unique("csv-format", ctx.loc2pos(yystack_[2].location));
     ElementPtr csv(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("csv-format", csv);
 }
-#line 3272 "dhcp6_parser.cc"
+#line 3273 "dhcp6_parser.cc"
     break;
 
   case 581: // option_data_always_send: "always-send" ":" "boolean"
-#line 2053 "dhcp6_parser.yy"
+#line 2054 "dhcp6_parser.yy"
                                                    {
     ctx.unique("always-send", ctx.loc2pos(yystack_[2].location));
     ElementPtr persist(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("always-send", persist);
 }
-#line 3282 "dhcp6_parser.cc"
+#line 3283 "dhcp6_parser.cc"
     break;
 
   case 582: // option_data_never_send: "never-send" ":" "boolean"
-#line 2059 "dhcp6_parser.yy"
+#line 2060 "dhcp6_parser.yy"
                                                  {
     ctx.unique("never-send", ctx.loc2pos(yystack_[2].location));
     ElementPtr cancel(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("never-send", cancel);
 }
-#line 3292 "dhcp6_parser.cc"
+#line 3293 "dhcp6_parser.cc"
     break;
 
   case 583: // $@83: %empty
-#line 2068 "dhcp6_parser.yy"
+#line 2069 "dhcp6_parser.yy"
                   {
     ctx.unique("pools", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3300,113 +3301,113 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.POOLS);
 }
-#line 3304 "dhcp6_parser.cc"
+#line 3305 "dhcp6_parser.cc"
     break;
 
   case 584: // pools_list: "pools" $@83 ":" "[" pools_list_content "]"
-#line 2074 "dhcp6_parser.yy"
+#line 2075 "dhcp6_parser.yy"
                                                            {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3313 "dhcp6_parser.cc"
+#line 3314 "dhcp6_parser.cc"
     break;
 
   case 589: // not_empty_pools_list: not_empty_pools_list ","
-#line 2087 "dhcp6_parser.yy"
+#line 2088 "dhcp6_parser.yy"
                                                  {
                         ctx.warnAboutExtraCommas(yystack_[0].location);
                         }
-#line 3321 "dhcp6_parser.cc"
+#line 3322 "dhcp6_parser.cc"
     break;
 
   case 590: // $@84: %empty
-#line 2092 "dhcp6_parser.yy"
+#line 2093 "dhcp6_parser.yy"
                                 {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3331 "dhcp6_parser.cc"
+#line 3332 "dhcp6_parser.cc"
     break;
 
   case 591: // pool_list_entry: "{" $@84 pool_params "}"
-#line 2096 "dhcp6_parser.yy"
+#line 2097 "dhcp6_parser.yy"
                              {
     // The pool parameter is required.
     ctx.require("pool", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 3341 "dhcp6_parser.cc"
+#line 3342 "dhcp6_parser.cc"
     break;
 
   case 592: // $@85: %empty
-#line 2102 "dhcp6_parser.yy"
+#line 2103 "dhcp6_parser.yy"
                           {
     // Parse the pool list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3351 "dhcp6_parser.cc"
+#line 3352 "dhcp6_parser.cc"
     break;
 
   case 593: // sub_pool6: "{" $@85 pool_params "}"
-#line 2106 "dhcp6_parser.yy"
+#line 2107 "dhcp6_parser.yy"
                              {
     // The pool parameter is required.
     ctx.require("pool", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 3361 "dhcp6_parser.cc"
+#line 3362 "dhcp6_parser.cc"
     break;
 
   case 596: // pool_params: pool_params ","
-#line 2114 "dhcp6_parser.yy"
+#line 2115 "dhcp6_parser.yy"
                                {
                ctx.warnAboutExtraCommas(yystack_[0].location);
                }
-#line 3369 "dhcp6_parser.cc"
+#line 3370 "dhcp6_parser.cc"
     break;
 
   case 605: // $@86: %empty
-#line 2129 "dhcp6_parser.yy"
+#line 2130 "dhcp6_parser.yy"
                  {
     ctx.unique("pool", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3378 "dhcp6_parser.cc"
+#line 3379 "dhcp6_parser.cc"
     break;
 
   case 606: // pool_entry: "pool" $@86 ":" "constant string"
-#line 2132 "dhcp6_parser.yy"
+#line 2133 "dhcp6_parser.yy"
                {
     ElementPtr pool(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("pool", pool);
     ctx.leave();
 }
-#line 3388 "dhcp6_parser.cc"
+#line 3389 "dhcp6_parser.cc"
     break;
 
   case 607: // pool_id: "pool-id" ":" "integer"
-#line 2138 "dhcp6_parser.yy"
+#line 2139 "dhcp6_parser.yy"
                                {
     ctx.unique("pool-id", ctx.loc2pos(yystack_[2].location));
     ElementPtr id(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("pool-id", id);
 }
-#line 3398 "dhcp6_parser.cc"
+#line 3399 "dhcp6_parser.cc"
     break;
 
   case 608: // $@87: %empty
-#line 2144 "dhcp6_parser.yy"
+#line 2145 "dhcp6_parser.yy"
                            {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3406 "dhcp6_parser.cc"
+#line 3407 "dhcp6_parser.cc"
     break;
 
   case 609: // user_context: "user-context" $@87 ":" map_value
-#line 2146 "dhcp6_parser.yy"
+#line 2147 "dhcp6_parser.yy"
                   {
     ElementPtr parent = ctx.stack_.back();
     ElementPtr user_context = yystack_[0].value.as < ElementPtr > ();
@@ -3429,19 +3430,19 @@ namespace isc { namespace dhcp {
     parent->set("user-context", user_context);
     ctx.leave();
 }
-#line 3433 "dhcp6_parser.cc"
+#line 3434 "dhcp6_parser.cc"
     break;
 
   case 610: // $@88: %empty
-#line 2169 "dhcp6_parser.yy"
+#line 2170 "dhcp6_parser.yy"
                  {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3441 "dhcp6_parser.cc"
+#line 3442 "dhcp6_parser.cc"
     break;
 
   case 611: // comment: "comment" $@88 ":" "constant string"
-#line 2171 "dhcp6_parser.yy"
+#line 2172 "dhcp6_parser.yy"
                {
     ElementPtr parent = ctx.stack_.back();
     ElementPtr user_context(new MapElement(ctx.loc2pos(yystack_[3].location)));
@@ -3466,11 +3467,11 @@ namespace isc { namespace dhcp {
     parent->set("user-context", user_context);
     ctx.leave();
 }
-#line 3470 "dhcp6_parser.cc"
+#line 3471 "dhcp6_parser.cc"
     break;
 
   case 612: // $@89: %empty
-#line 2199 "dhcp6_parser.yy"
+#line 2200 "dhcp6_parser.yy"
                         {
     ctx.unique("pd-pools", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3478,38 +3479,38 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.PD_POOLS);
 }
-#line 3482 "dhcp6_parser.cc"
+#line 3483 "dhcp6_parser.cc"
     break;
 
   case 613: // pd_pools_list: "pd-pools" $@89 ":" "[" pd_pools_list_content "]"
-#line 2205 "dhcp6_parser.yy"
+#line 2206 "dhcp6_parser.yy"
                                                               {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3491 "dhcp6_parser.cc"
+#line 3492 "dhcp6_parser.cc"
     break;
 
   case 618: // not_empty_pd_pools_list: not_empty_pd_pools_list ","
-#line 2218 "dhcp6_parser.yy"
+#line 2219 "dhcp6_parser.yy"
                                                        {
                            ctx.warnAboutExtraCommas(yystack_[0].location);
                            }
-#line 3499 "dhcp6_parser.cc"
+#line 3500 "dhcp6_parser.cc"
     break;
 
   case 619: // $@90: %empty
-#line 2223 "dhcp6_parser.yy"
+#line 2224 "dhcp6_parser.yy"
                               {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3509 "dhcp6_parser.cc"
+#line 3510 "dhcp6_parser.cc"
     break;
 
   case 620: // pd_pool_entry: "{" $@90 pd_pool_params "}"
-#line 2227 "dhcp6_parser.yy"
+#line 2228 "dhcp6_parser.yy"
                                 {
     // The prefix, prefix len and delegated len parameters are required.
     ctx.require("prefix", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
@@ -3517,21 +3518,21 @@ namespace isc { namespace dhcp {
     ctx.require("delegated-len", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 3521 "dhcp6_parser.cc"
+#line 3522 "dhcp6_parser.cc"
     break;
 
   case 621: // $@91: %empty
-#line 2235 "dhcp6_parser.yy"
+#line 2236 "dhcp6_parser.yy"
                             {
     // Parse the pd-pool list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3531 "dhcp6_parser.cc"
+#line 3532 "dhcp6_parser.cc"
     break;
 
   case 622: // sub_pd_pool: "{" $@91 pd_pool_params "}"
-#line 2239 "dhcp6_parser.yy"
+#line 2240 "dhcp6_parser.yy"
                                 {
     // The prefix, prefix len and delegated len parameters are required.
     ctx.require("prefix", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
@@ -3539,87 +3540,87 @@ namespace isc { namespace dhcp {
     ctx.require("delegated-len", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 3543 "dhcp6_parser.cc"
+#line 3544 "dhcp6_parser.cc"
     break;
 
   case 625: // pd_pool_params: pd_pool_params ","
-#line 2249 "dhcp6_parser.yy"
+#line 2250 "dhcp6_parser.yy"
                                      {
                   ctx.warnAboutExtraCommas(yystack_[0].location);
                   }
-#line 3551 "dhcp6_parser.cc"
+#line 3552 "dhcp6_parser.cc"
     break;
 
   case 638: // $@92: %empty
-#line 2268 "dhcp6_parser.yy"
+#line 2269 "dhcp6_parser.yy"
                   {
     ctx.unique("prefix", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3560 "dhcp6_parser.cc"
+#line 3561 "dhcp6_parser.cc"
     break;
 
   case 639: // pd_prefix: "prefix" $@92 ":" "constant string"
-#line 2271 "dhcp6_parser.yy"
+#line 2272 "dhcp6_parser.yy"
                {
     ElementPtr prf(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("prefix", prf);
     ctx.leave();
 }
-#line 3570 "dhcp6_parser.cc"
+#line 3571 "dhcp6_parser.cc"
     break;
 
   case 640: // pd_prefix_len: "prefix-len" ":" "integer"
-#line 2277 "dhcp6_parser.yy"
+#line 2278 "dhcp6_parser.yy"
                                         {
     ctx.unique("prefix-len", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("prefix-len", prf);
 }
-#line 3580 "dhcp6_parser.cc"
+#line 3581 "dhcp6_parser.cc"
     break;
 
   case 641: // $@93: %empty
-#line 2283 "dhcp6_parser.yy"
+#line 2284 "dhcp6_parser.yy"
                                  {
     ctx.unique("excluded-prefix", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3589 "dhcp6_parser.cc"
+#line 3590 "dhcp6_parser.cc"
     break;
 
   case 642: // excluded_prefix: "excluded-prefix" $@93 ":" "constant string"
-#line 2286 "dhcp6_parser.yy"
+#line 2287 "dhcp6_parser.yy"
                {
     ElementPtr prf(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("excluded-prefix", prf);
     ctx.leave();
 }
-#line 3599 "dhcp6_parser.cc"
+#line 3600 "dhcp6_parser.cc"
     break;
 
   case 643: // excluded_prefix_len: "excluded-prefix-len" ":" "integer"
-#line 2292 "dhcp6_parser.yy"
+#line 2293 "dhcp6_parser.yy"
                                                        {
     ctx.unique("excluded-prefix-len", ctx.loc2pos(yystack_[2].location));
     ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("excluded-prefix-len", prf);
 }
-#line 3609 "dhcp6_parser.cc"
+#line 3610 "dhcp6_parser.cc"
     break;
 
   case 644: // pd_delegated_len: "delegated-len" ":" "integer"
-#line 2298 "dhcp6_parser.yy"
+#line 2299 "dhcp6_parser.yy"
                                               {
     ctx.unique("delegated-len", ctx.loc2pos(yystack_[2].location));
     ElementPtr deleg(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("delegated-len", deleg);
 }
-#line 3619 "dhcp6_parser.cc"
+#line 3620 "dhcp6_parser.cc"
     break;
 
   case 645: // $@94: %empty
-#line 2307 "dhcp6_parser.yy"
+#line 2308 "dhcp6_parser.yy"
                            {
     ctx.unique("reservations", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3627,74 +3628,74 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.RESERVATIONS);
 }
-#line 3631 "dhcp6_parser.cc"
+#line 3632 "dhcp6_parser.cc"
     break;
 
   case 646: // reservations: "reservations" $@94 ":" "[" reservations_list "]"
-#line 2313 "dhcp6_parser.yy"
+#line 2314 "dhcp6_parser.yy"
                                                           {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3640 "dhcp6_parser.cc"
+#line 3641 "dhcp6_parser.cc"
     break;
 
   case 651: // not_empty_reservations_list: not_empty_reservations_list ","
-#line 2324 "dhcp6_parser.yy"
+#line 2325 "dhcp6_parser.yy"
                                                                {
                                ctx.warnAboutExtraCommas(yystack_[0].location);
                                }
-#line 3648 "dhcp6_parser.cc"
+#line 3649 "dhcp6_parser.cc"
     break;
 
   case 652: // $@95: %empty
-#line 2329 "dhcp6_parser.yy"
+#line 2330 "dhcp6_parser.yy"
                             {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3658 "dhcp6_parser.cc"
+#line 3659 "dhcp6_parser.cc"
     break;
 
   case 653: // reservation: "{" $@95 reservation_params "}"
-#line 2333 "dhcp6_parser.yy"
+#line 2334 "dhcp6_parser.yy"
                                     {
     /// @todo: an identifier parameter is required.
     ctx.stack_.pop_back();
 }
-#line 3667 "dhcp6_parser.cc"
+#line 3668 "dhcp6_parser.cc"
     break;
 
   case 654: // $@96: %empty
-#line 2338 "dhcp6_parser.yy"
+#line 2339 "dhcp6_parser.yy"
                                 {
     // Parse the reservations list entry map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 3677 "dhcp6_parser.cc"
+#line 3678 "dhcp6_parser.cc"
     break;
 
   case 655: // sub_reservation: "{" $@96 reservation_params "}"
-#line 2342 "dhcp6_parser.yy"
+#line 2343 "dhcp6_parser.yy"
                                     {
     /// @todo: an identifier parameter is required.
     // parsing completed
 }
-#line 3686 "dhcp6_parser.cc"
+#line 3687 "dhcp6_parser.cc"
     break;
 
   case 660: // not_empty_reservation_params: not_empty_reservation_params ","
-#line 2353 "dhcp6_parser.yy"
+#line 2354 "dhcp6_parser.yy"
                                          {
         ctx.warnAboutExtraCommas(yystack_[0].location);
         }
-#line 3694 "dhcp6_parser.cc"
+#line 3695 "dhcp6_parser.cc"
     break;
 
   case 672: // $@97: %empty
-#line 2372 "dhcp6_parser.yy"
+#line 2373 "dhcp6_parser.yy"
                            {
     ctx.unique("ip-addresses", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3702,20 +3703,20 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3706 "dhcp6_parser.cc"
+#line 3707 "dhcp6_parser.cc"
     break;
 
   case 673: // ip_addresses: "ip-addresses" $@97 ":" list_strings
-#line 2378 "dhcp6_parser.yy"
+#line 2379 "dhcp6_parser.yy"
                      {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3715 "dhcp6_parser.cc"
+#line 3716 "dhcp6_parser.cc"
     break;
 
   case 674: // $@98: %empty
-#line 2383 "dhcp6_parser.yy"
+#line 2384 "dhcp6_parser.yy"
                    {
     ctx.unique("prefixes", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3723,96 +3724,96 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3727 "dhcp6_parser.cc"
+#line 3728 "dhcp6_parser.cc"
     break;
 
   case 675: // prefixes: "prefixes" $@98 ":" list_strings
-#line 2389 "dhcp6_parser.yy"
+#line 2390 "dhcp6_parser.yy"
                      {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3736 "dhcp6_parser.cc"
+#line 3737 "dhcp6_parser.cc"
     break;
 
   case 676: // $@99: %empty
-#line 2394 "dhcp6_parser.yy"
+#line 2395 "dhcp6_parser.yy"
            {
     ctx.unique("duid", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3745 "dhcp6_parser.cc"
+#line 3746 "dhcp6_parser.cc"
     break;
 
   case 677: // duid: "duid" $@99 ":" "constant string"
-#line 2397 "dhcp6_parser.yy"
+#line 2398 "dhcp6_parser.yy"
                {
     ElementPtr d(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("duid", d);
     ctx.leave();
 }
-#line 3755 "dhcp6_parser.cc"
+#line 3756 "dhcp6_parser.cc"
     break;
 
   case 678: // $@100: %empty
-#line 2403 "dhcp6_parser.yy"
+#line 2404 "dhcp6_parser.yy"
                        {
     ctx.unique("hw-address", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3764 "dhcp6_parser.cc"
+#line 3765 "dhcp6_parser.cc"
     break;
 
   case 679: // hw_address: "hw-address" $@100 ":" "constant string"
-#line 2406 "dhcp6_parser.yy"
+#line 2407 "dhcp6_parser.yy"
                {
     ElementPtr hw(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hw-address", hw);
     ctx.leave();
 }
-#line 3774 "dhcp6_parser.cc"
+#line 3775 "dhcp6_parser.cc"
     break;
 
   case 680: // $@101: %empty
-#line 2412 "dhcp6_parser.yy"
+#line 2413 "dhcp6_parser.yy"
                    {
     ctx.unique("hostname", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3783 "dhcp6_parser.cc"
+#line 3784 "dhcp6_parser.cc"
     break;
 
   case 681: // hostname: "hostname" $@101 ":" "constant string"
-#line 2415 "dhcp6_parser.yy"
+#line 2416 "dhcp6_parser.yy"
                {
     ElementPtr host(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("hostname", host);
     ctx.leave();
 }
-#line 3793 "dhcp6_parser.cc"
+#line 3794 "dhcp6_parser.cc"
     break;
 
   case 682: // $@102: %empty
-#line 2421 "dhcp6_parser.yy"
+#line 2422 "dhcp6_parser.yy"
                        {
     ctx.unique("flex-id", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3802 "dhcp6_parser.cc"
+#line 3803 "dhcp6_parser.cc"
     break;
 
   case 683: // flex_id_value: "flex-id" $@102 ":" "constant string"
-#line 2424 "dhcp6_parser.yy"
+#line 2425 "dhcp6_parser.yy"
                {
     ElementPtr hw(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("flex-id", hw);
     ctx.leave();
 }
-#line 3812 "dhcp6_parser.cc"
+#line 3813 "dhcp6_parser.cc"
     break;
 
   case 684: // $@103: %empty
-#line 2430 "dhcp6_parser.yy"
+#line 2431 "dhcp6_parser.yy"
                                            {
     ctx.unique("client-classes", ctx.loc2pos(yystack_[0].location));
     ElementPtr c(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3820,20 +3821,20 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(c);
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3824 "dhcp6_parser.cc"
+#line 3825 "dhcp6_parser.cc"
     break;
 
   case 685: // reservation_client_classes: "client-classes" $@103 ":" list_strings
-#line 2436 "dhcp6_parser.yy"
+#line 2437 "dhcp6_parser.yy"
                      {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3833 "dhcp6_parser.cc"
+#line 3834 "dhcp6_parser.cc"
     break;
 
   case 686: // $@104: %empty
-#line 2444 "dhcp6_parser.yy"
+#line 2445 "dhcp6_parser.yy"
              {
     ctx.unique("relay", ctx.loc2pos(yystack_[0].location));
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -3841,20 +3842,20 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(m);
     ctx.enter(ctx.RELAY);
 }
-#line 3845 "dhcp6_parser.cc"
+#line 3846 "dhcp6_parser.cc"
     break;
 
   case 687: // relay: "relay" $@104 ":" "{" relay_map "}"
-#line 2450 "dhcp6_parser.yy"
+#line 2451 "dhcp6_parser.yy"
                                                 {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3854 "dhcp6_parser.cc"
+#line 3855 "dhcp6_parser.cc"
     break;
 
   case 689: // $@105: %empty
-#line 2461 "dhcp6_parser.yy"
+#line 2462 "dhcp6_parser.yy"
                                {
     ctx.unique("client-classes", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -3862,104 +3863,104 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.CLIENT_CLASSES);
 }
-#line 3866 "dhcp6_parser.cc"
+#line 3867 "dhcp6_parser.cc"
     break;
 
   case 690: // client_classes: "client-classes" $@105 ":" "[" client_classes_list "]"
-#line 2467 "dhcp6_parser.yy"
+#line 2468 "dhcp6_parser.yy"
                                                             {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3875 "dhcp6_parser.cc"
+#line 3876 "dhcp6_parser.cc"
     break;
 
   case 693: // client_classes_list: client_classes_list ","
-#line 2474 "dhcp6_parser.yy"
+#line 2475 "dhcp6_parser.yy"
                                                {
                        ctx.warnAboutExtraCommas(yystack_[0].location);
                        }
-#line 3883 "dhcp6_parser.cc"
+#line 3884 "dhcp6_parser.cc"
     break;
 
   case 694: // $@106: %empty
-#line 2479 "dhcp6_parser.yy"
+#line 2480 "dhcp6_parser.yy"
                                    {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 3893 "dhcp6_parser.cc"
+#line 3894 "dhcp6_parser.cc"
     break;
 
   case 695: // client_class_entry: "{" $@106 client_class_params "}"
-#line 2483 "dhcp6_parser.yy"
+#line 2484 "dhcp6_parser.yy"
                                      {
     // The name client class parameter is required.
     ctx.require("name", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
 }
-#line 3903 "dhcp6_parser.cc"
+#line 3904 "dhcp6_parser.cc"
     break;
 
   case 700: // not_empty_client_class_params: not_empty_client_class_params ","
-#line 2495 "dhcp6_parser.yy"
+#line 2496 "dhcp6_parser.yy"
                                           {
         ctx.warnAboutExtraCommas(yystack_[0].location);
         }
-#line 3911 "dhcp6_parser.cc"
+#line 3912 "dhcp6_parser.cc"
     break;
 
   case 716: // $@107: %empty
-#line 2518 "dhcp6_parser.yy"
+#line 2519 "dhcp6_parser.yy"
                         {
     ctx.unique("test", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3920 "dhcp6_parser.cc"
+#line 3921 "dhcp6_parser.cc"
     break;
 
   case 717: // client_class_test: "test" $@107 ":" "constant string"
-#line 2521 "dhcp6_parser.yy"
+#line 2522 "dhcp6_parser.yy"
                {
     ElementPtr test(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("test", test);
     ctx.leave();
 }
-#line 3930 "dhcp6_parser.cc"
+#line 3931 "dhcp6_parser.cc"
     break;
 
   case 718: // $@108: %empty
-#line 2527 "dhcp6_parser.yy"
+#line 2528 "dhcp6_parser.yy"
                                           {
     ctx.unique("template-test", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 3939 "dhcp6_parser.cc"
+#line 3940 "dhcp6_parser.cc"
     break;
 
   case 719: // client_class_template_test: "template-test" $@108 ":" "constant string"
-#line 2530 "dhcp6_parser.yy"
+#line 2531 "dhcp6_parser.yy"
                {
     ElementPtr template_test(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("template-test", template_test);
     ctx.leave();
 }
-#line 3949 "dhcp6_parser.cc"
+#line 3950 "dhcp6_parser.cc"
     break;
 
   case 720: // only_if_required: "only-if-required" ":" "boolean"
-#line 2536 "dhcp6_parser.yy"
+#line 2537 "dhcp6_parser.yy"
                                                  {
     ctx.unique("only-if-required", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("only-if-required", b);
 }
-#line 3959 "dhcp6_parser.cc"
+#line 3960 "dhcp6_parser.cc"
     break;
 
   case 721: // $@109: %empty
-#line 2545 "dhcp6_parser.yy"
+#line 2546 "dhcp6_parser.yy"
                      {
     ctx.unique("server-id", ctx.loc2pos(yystack_[0].location));
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -3967,125 +3968,125 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(m);
     ctx.enter(ctx.SERVER_ID);
 }
-#line 3971 "dhcp6_parser.cc"
+#line 3972 "dhcp6_parser.cc"
     break;
 
   case 722: // server_id: "server-id" $@109 ":" "{" server_id_params "}"
-#line 2551 "dhcp6_parser.yy"
+#line 2552 "dhcp6_parser.yy"
                                                        {
     // The type parameter is required.
     ctx.require("type", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 3982 "dhcp6_parser.cc"
+#line 3983 "dhcp6_parser.cc"
     break;
 
   case 725: // server_id_params: server_id_params ","
-#line 2560 "dhcp6_parser.yy"
+#line 2561 "dhcp6_parser.yy"
                                          {
                     ctx.warnAboutExtraCommas(yystack_[0].location);
                     }
-#line 3990 "dhcp6_parser.cc"
+#line 3991 "dhcp6_parser.cc"
     break;
 
   case 735: // $@110: %empty
-#line 2576 "dhcp6_parser.yy"
+#line 2577 "dhcp6_parser.yy"
                      {
     ctx.unique("type", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.DUID_TYPE);
 }
-#line 3999 "dhcp6_parser.cc"
+#line 4000 "dhcp6_parser.cc"
     break;
 
   case 736: // server_id_type: "type" $@110 ":" duid_type
-#line 2579 "dhcp6_parser.yy"
+#line 2580 "dhcp6_parser.yy"
                   {
     ctx.stack_.back()->set("type", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 4008 "dhcp6_parser.cc"
+#line 4009 "dhcp6_parser.cc"
     break;
 
   case 737: // duid_type: "LLT"
-#line 2584 "dhcp6_parser.yy"
+#line 2585 "dhcp6_parser.yy"
                { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("LLT", ctx.loc2pos(yystack_[0].location))); }
-#line 4014 "dhcp6_parser.cc"
+#line 4015 "dhcp6_parser.cc"
     break;
 
   case 738: // duid_type: "EN"
-#line 2585 "dhcp6_parser.yy"
+#line 2586 "dhcp6_parser.yy"
               { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("EN", ctx.loc2pos(yystack_[0].location))); }
-#line 4020 "dhcp6_parser.cc"
+#line 4021 "dhcp6_parser.cc"
     break;
 
   case 739: // duid_type: "LL"
-#line 2586 "dhcp6_parser.yy"
+#line 2587 "dhcp6_parser.yy"
               { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("LL", ctx.loc2pos(yystack_[0].location))); }
-#line 4026 "dhcp6_parser.cc"
+#line 4027 "dhcp6_parser.cc"
     break;
 
   case 740: // htype: "htype" ":" "integer"
-#line 2589 "dhcp6_parser.yy"
+#line 2590 "dhcp6_parser.yy"
                            {
     ctx.unique("htype", ctx.loc2pos(yystack_[2].location));
     ElementPtr htype(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("htype", htype);
 }
-#line 4036 "dhcp6_parser.cc"
+#line 4037 "dhcp6_parser.cc"
     break;
 
   case 741: // $@111: %empty
-#line 2595 "dhcp6_parser.yy"
+#line 2596 "dhcp6_parser.yy"
                        {
     ctx.unique("identifier", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4045 "dhcp6_parser.cc"
+#line 4046 "dhcp6_parser.cc"
     break;
 
   case 742: // identifier: "identifier" $@111 ":" "constant string"
-#line 2598 "dhcp6_parser.yy"
+#line 2599 "dhcp6_parser.yy"
                {
     ElementPtr id(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("identifier", id);
     ctx.leave();
 }
-#line 4055 "dhcp6_parser.cc"
+#line 4056 "dhcp6_parser.cc"
     break;
 
   case 743: // time: "time" ":" "integer"
-#line 2604 "dhcp6_parser.yy"
+#line 2605 "dhcp6_parser.yy"
                          {
     ctx.unique("time", ctx.loc2pos(yystack_[2].location));
     ElementPtr time(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("time", time);
 }
-#line 4065 "dhcp6_parser.cc"
+#line 4066 "dhcp6_parser.cc"
     break;
 
   case 744: // enterprise_id: "enterprise-id" ":" "integer"
-#line 2610 "dhcp6_parser.yy"
+#line 2611 "dhcp6_parser.yy"
                                            {
     ctx.unique("enterprise-id", ctx.loc2pos(yystack_[2].location));
     ElementPtr time(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("enterprise-id", time);
 }
-#line 4075 "dhcp6_parser.cc"
+#line 4076 "dhcp6_parser.cc"
     break;
 
   case 745: // dhcp4o6_port: "dhcp4o6-port" ":" "integer"
-#line 2618 "dhcp6_parser.yy"
+#line 2619 "dhcp6_parser.yy"
                                          {
     ctx.unique("dhcp4o6-port", ctx.loc2pos(yystack_[2].location));
     ElementPtr time(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("dhcp4o6-port", time);
 }
-#line 4085 "dhcp6_parser.cc"
+#line 4086 "dhcp6_parser.cc"
     break;
 
   case 746: // $@112: %empty
-#line 2626 "dhcp6_parser.yy"
+#line 2627 "dhcp6_parser.yy"
                                {
     ctx.unique("control-socket", ctx.loc2pos(yystack_[0].location));
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -4093,66 +4094,66 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(m);
     ctx.enter(ctx.CONTROL_SOCKET);
 }
-#line 4097 "dhcp6_parser.cc"
+#line 4098 "dhcp6_parser.cc"
     break;
 
   case 747: // control_socket: "control-socket" $@112 ":" "{" control_socket_params "}"
-#line 2632 "dhcp6_parser.yy"
+#line 2633 "dhcp6_parser.yy"
                                                             {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4106 "dhcp6_parser.cc"
+#line 4107 "dhcp6_parser.cc"
     break;
 
   case 750: // control_socket_params: control_socket_params ","
-#line 2639 "dhcp6_parser.yy"
+#line 2640 "dhcp6_parser.yy"
                                                    {
                          ctx.warnAboutExtraCommas(yystack_[0].location);
                          }
-#line 4114 "dhcp6_parser.cc"
+#line 4115 "dhcp6_parser.cc"
     break;
 
   case 756: // $@113: %empty
-#line 2651 "dhcp6_parser.yy"
+#line 2652 "dhcp6_parser.yy"
                          {
     ctx.unique("socket-type", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4123 "dhcp6_parser.cc"
+#line 4124 "dhcp6_parser.cc"
     break;
 
   case 757: // socket_type: "socket-type" $@113 ":" "constant string"
-#line 2654 "dhcp6_parser.yy"
+#line 2655 "dhcp6_parser.yy"
                {
     ElementPtr stype(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("socket-type", stype);
     ctx.leave();
 }
-#line 4133 "dhcp6_parser.cc"
+#line 4134 "dhcp6_parser.cc"
     break;
 
   case 758: // $@114: %empty
-#line 2660 "dhcp6_parser.yy"
+#line 2661 "dhcp6_parser.yy"
                          {
     ctx.unique("socket-name", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4142 "dhcp6_parser.cc"
+#line 4143 "dhcp6_parser.cc"
     break;
 
   case 759: // socket_name: "socket-name" $@114 ":" "constant string"
-#line 2663 "dhcp6_parser.yy"
+#line 2664 "dhcp6_parser.yy"
                {
     ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("socket-name", name);
     ctx.leave();
 }
-#line 4152 "dhcp6_parser.cc"
+#line 4153 "dhcp6_parser.cc"
     break;
 
   case 760: // $@115: %empty
-#line 2672 "dhcp6_parser.yy"
+#line 2673 "dhcp6_parser.yy"
                                        {
     ctx.unique("dhcp-queue-control", ctx.loc2pos(yystack_[0].location));
     ElementPtr qc(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -4160,87 +4161,87 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(qc);
     ctx.enter(ctx.DHCP_QUEUE_CONTROL);
 }
-#line 4164 "dhcp6_parser.cc"
+#line 4165 "dhcp6_parser.cc"
     break;
 
   case 761: // dhcp_queue_control: "dhcp-queue-control" $@115 ":" "{" queue_control_params "}"
-#line 2678 "dhcp6_parser.yy"
+#line 2679 "dhcp6_parser.yy"
                                                            {
     // The enable queue parameter is required.
     ctx.require("enable-queue", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4175 "dhcp6_parser.cc"
+#line 4176 "dhcp6_parser.cc"
     break;
 
   case 764: // queue_control_params: queue_control_params ","
-#line 2687 "dhcp6_parser.yy"
+#line 2688 "dhcp6_parser.yy"
                                                  {
                         ctx.warnAboutExtraCommas(yystack_[0].location);
                         }
-#line 4183 "dhcp6_parser.cc"
+#line 4184 "dhcp6_parser.cc"
     break;
 
   case 771: // enable_queue: "enable-queue" ":" "boolean"
-#line 2700 "dhcp6_parser.yy"
+#line 2701 "dhcp6_parser.yy"
                                          {
     ctx.unique("enable-queue", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("enable-queue", b);
 }
-#line 4193 "dhcp6_parser.cc"
+#line 4194 "dhcp6_parser.cc"
     break;
 
   case 772: // $@116: %empty
-#line 2706 "dhcp6_parser.yy"
+#line 2707 "dhcp6_parser.yy"
                        {
     ctx.unique("queue-type", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4202 "dhcp6_parser.cc"
+#line 4203 "dhcp6_parser.cc"
     break;
 
   case 773: // queue_type: "queue-type" $@116 ":" "constant string"
-#line 2709 "dhcp6_parser.yy"
+#line 2710 "dhcp6_parser.yy"
                {
     ElementPtr qt(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("queue-type", qt);
     ctx.leave();
 }
-#line 4212 "dhcp6_parser.cc"
+#line 4213 "dhcp6_parser.cc"
     break;
 
   case 774: // capacity: "capacity" ":" "integer"
-#line 2715 "dhcp6_parser.yy"
+#line 2716 "dhcp6_parser.yy"
                                  {
     ctx.unique("capacity", ctx.loc2pos(yystack_[2].location));
     ElementPtr c(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("capacity", c);
 }
-#line 4222 "dhcp6_parser.cc"
+#line 4223 "dhcp6_parser.cc"
     break;
 
   case 775: // $@117: %empty
-#line 2721 "dhcp6_parser.yy"
+#line 2722 "dhcp6_parser.yy"
                             {
     ctx.unique(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4231 "dhcp6_parser.cc"
+#line 4232 "dhcp6_parser.cc"
     break;
 
   case 776: // arbitrary_map_entry: "constant string" $@117 ":" value
-#line 2724 "dhcp6_parser.yy"
+#line 2725 "dhcp6_parser.yy"
               {
     ctx.stack_.back()->set(yystack_[3].value.as < std::string > (), yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 4240 "dhcp6_parser.cc"
+#line 4241 "dhcp6_parser.cc"
     break;
 
   case 777: // $@118: %empty
-#line 2731 "dhcp6_parser.yy"
+#line 2732 "dhcp6_parser.yy"
                      {
     ctx.unique("dhcp-ddns", ctx.loc2pos(yystack_[0].location));
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -4248,177 +4249,177 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(m);
     ctx.enter(ctx.DHCP_DDNS);
 }
-#line 4252 "dhcp6_parser.cc"
+#line 4253 "dhcp6_parser.cc"
     break;
 
   case 778: // dhcp_ddns: "dhcp-ddns" $@118 ":" "{" dhcp_ddns_params "}"
-#line 2737 "dhcp6_parser.yy"
+#line 2738 "dhcp6_parser.yy"
                                                        {
     // The enable updates DHCP DDNS parameter is required.
     ctx.require("enable-updates", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location));
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4263 "dhcp6_parser.cc"
+#line 4264 "dhcp6_parser.cc"
     break;
 
   case 779: // $@119: %empty
-#line 2744 "dhcp6_parser.yy"
+#line 2745 "dhcp6_parser.yy"
                               {
     // Parse the dhcp-ddns map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 4273 "dhcp6_parser.cc"
+#line 4274 "dhcp6_parser.cc"
     break;
 
   case 780: // sub_dhcp_ddns: "{" $@119 dhcp_ddns_params "}"
-#line 2748 "dhcp6_parser.yy"
+#line 2749 "dhcp6_parser.yy"
                                   {
     // The enable updates DHCP DDNS parameter is required.
     ctx.require("enable-updates", ctx.loc2pos(yystack_[3].location), ctx.loc2pos(yystack_[0].location));
     // parsing completed
 }
-#line 4283 "dhcp6_parser.cc"
+#line 4284 "dhcp6_parser.cc"
     break;
 
   case 783: // dhcp_ddns_params: dhcp_ddns_params ","
-#line 2756 "dhcp6_parser.yy"
+#line 2757 "dhcp6_parser.yy"
                                          {
                     ctx.warnAboutExtraCommas(yystack_[0].location);
                     }
-#line 4291 "dhcp6_parser.cc"
+#line 4292 "dhcp6_parser.cc"
     break;
 
   case 795: // enable_updates: "enable-updates" ":" "boolean"
-#line 2774 "dhcp6_parser.yy"
+#line 2775 "dhcp6_parser.yy"
                                              {
     ctx.unique("enable-updates", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("enable-updates", b);
 }
-#line 4301 "dhcp6_parser.cc"
+#line 4302 "dhcp6_parser.cc"
     break;
 
   case 796: // $@120: %empty
-#line 2780 "dhcp6_parser.yy"
+#line 2781 "dhcp6_parser.yy"
                      {
     ctx.unique("server-ip", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4310 "dhcp6_parser.cc"
+#line 4311 "dhcp6_parser.cc"
     break;
 
   case 797: // server_ip: "server-ip" $@120 ":" "constant string"
-#line 2783 "dhcp6_parser.yy"
+#line 2784 "dhcp6_parser.yy"
                {
     ElementPtr s(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-ip", s);
     ctx.leave();
 }
-#line 4320 "dhcp6_parser.cc"
+#line 4321 "dhcp6_parser.cc"
     break;
 
   case 798: // server_port: "server-port" ":" "integer"
-#line 2789 "dhcp6_parser.yy"
+#line 2790 "dhcp6_parser.yy"
                                        {
     ctx.unique("server-port", ctx.loc2pos(yystack_[2].location));
     ElementPtr i(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("server-port", i);
 }
-#line 4330 "dhcp6_parser.cc"
+#line 4331 "dhcp6_parser.cc"
     break;
 
   case 799: // $@121: %empty
-#line 2795 "dhcp6_parser.yy"
+#line 2796 "dhcp6_parser.yy"
                      {
     ctx.unique("sender-ip", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4339 "dhcp6_parser.cc"
+#line 4340 "dhcp6_parser.cc"
     break;
 
   case 800: // sender_ip: "sender-ip" $@121 ":" "constant string"
-#line 2798 "dhcp6_parser.yy"
+#line 2799 "dhcp6_parser.yy"
                {
     ElementPtr s(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("sender-ip", s);
     ctx.leave();
 }
-#line 4349 "dhcp6_parser.cc"
+#line 4350 "dhcp6_parser.cc"
     break;
 
   case 801: // sender_port: "sender-port" ":" "integer"
-#line 2804 "dhcp6_parser.yy"
+#line 2805 "dhcp6_parser.yy"
                                        {
     ctx.unique("sender-port", ctx.loc2pos(yystack_[2].location));
     ElementPtr i(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("sender-port", i);
 }
-#line 4359 "dhcp6_parser.cc"
+#line 4360 "dhcp6_parser.cc"
     break;
 
   case 802: // max_queue_size: "max-queue-size" ":" "integer"
-#line 2810 "dhcp6_parser.yy"
+#line 2811 "dhcp6_parser.yy"
                                              {
     ctx.unique("max-queue-size", ctx.loc2pos(yystack_[2].location));
     ElementPtr i(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("max-queue-size", i);
 }
-#line 4369 "dhcp6_parser.cc"
+#line 4370 "dhcp6_parser.cc"
     break;
 
   case 803: // $@122: %empty
-#line 2816 "dhcp6_parser.yy"
+#line 2817 "dhcp6_parser.yy"
                            {
     ctx.unique("ncr-protocol", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NCR_PROTOCOL);
 }
-#line 4378 "dhcp6_parser.cc"
+#line 4379 "dhcp6_parser.cc"
     break;
 
   case 804: // ncr_protocol: "ncr-protocol" $@122 ":" ncr_protocol_value
-#line 2819 "dhcp6_parser.yy"
+#line 2820 "dhcp6_parser.yy"
                            {
     ctx.stack_.back()->set("ncr-protocol", yystack_[0].value.as < ElementPtr > ());
     ctx.leave();
 }
-#line 4387 "dhcp6_parser.cc"
+#line 4388 "dhcp6_parser.cc"
     break;
 
   case 805: // ncr_protocol_value: "UDP"
-#line 2825 "dhcp6_parser.yy"
+#line 2826 "dhcp6_parser.yy"
         { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("UDP", ctx.loc2pos(yystack_[0].location))); }
-#line 4393 "dhcp6_parser.cc"
+#line 4394 "dhcp6_parser.cc"
     break;
 
   case 806: // ncr_protocol_value: "TCP"
-#line 2826 "dhcp6_parser.yy"
+#line 2827 "dhcp6_parser.yy"
         { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("TCP", ctx.loc2pos(yystack_[0].location))); }
-#line 4399 "dhcp6_parser.cc"
+#line 4400 "dhcp6_parser.cc"
     break;
 
   case 807: // $@123: %empty
-#line 2829 "dhcp6_parser.yy"
+#line 2830 "dhcp6_parser.yy"
                        {
     ctx.unique("ncr-format", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NCR_FORMAT);
 }
-#line 4408 "dhcp6_parser.cc"
+#line 4409 "dhcp6_parser.cc"
     break;
 
   case 808: // ncr_format: "ncr-format" $@123 ":" "JSON"
-#line 2832 "dhcp6_parser.yy"
+#line 2833 "dhcp6_parser.yy"
              {
     ElementPtr json(new StringElement("JSON", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ncr-format", json);
     ctx.leave();
 }
-#line 4418 "dhcp6_parser.cc"
+#line 4419 "dhcp6_parser.cc"
     break;
 
   case 809: // $@124: %empty
-#line 2840 "dhcp6_parser.yy"
+#line 2841 "dhcp6_parser.yy"
                                {
     ctx.unique("config-control", ctx.loc2pos(yystack_[0].location));
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -4426,48 +4427,48 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(i);
     ctx.enter(ctx.CONFIG_CONTROL);
 }
-#line 4430 "dhcp6_parser.cc"
+#line 4431 "dhcp6_parser.cc"
     break;
 
   case 810: // config_control: "config-control" $@124 ":" "{" config_control_params "}"
-#line 2846 "dhcp6_parser.yy"
+#line 2847 "dhcp6_parser.yy"
                                                             {
     // No config control params are required
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4440 "dhcp6_parser.cc"
+#line 4441 "dhcp6_parser.cc"
     break;
 
   case 811: // $@125: %empty
-#line 2852 "dhcp6_parser.yy"
+#line 2853 "dhcp6_parser.yy"
                                    {
     // Parse the config-control map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(m);
 }
-#line 4450 "dhcp6_parser.cc"
+#line 4451 "dhcp6_parser.cc"
     break;
 
   case 812: // sub_config_control: "{" $@125 config_control_params "}"
-#line 2856 "dhcp6_parser.yy"
+#line 2857 "dhcp6_parser.yy"
                                        {
     // No config_control params are required
     // parsing completed
 }
-#line 4459 "dhcp6_parser.cc"
+#line 4460 "dhcp6_parser.cc"
     break;
 
   case 815: // config_control_params: config_control_params ","
-#line 2864 "dhcp6_parser.yy"
+#line 2865 "dhcp6_parser.yy"
                                                    {
                          ctx.warnAboutExtraCommas(yystack_[0].location);
                          }
-#line 4467 "dhcp6_parser.cc"
+#line 4468 "dhcp6_parser.cc"
     break;
 
   case 818: // $@126: %empty
-#line 2874 "dhcp6_parser.yy"
+#line 2875 "dhcp6_parser.yy"
                                    {
     ctx.unique("config-databases", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -4475,30 +4476,30 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.CONFIG_DATABASE);
 }
-#line 4479 "dhcp6_parser.cc"
+#line 4480 "dhcp6_parser.cc"
     break;
 
   case 819: // config_databases: "config-databases" $@126 ":" "[" database_list "]"
-#line 2880 "dhcp6_parser.yy"
+#line 2881 "dhcp6_parser.yy"
                                                       {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4488 "dhcp6_parser.cc"
+#line 4489 "dhcp6_parser.cc"
     break;
 
   case 820: // config_fetch_wait_time: "config-fetch-wait-time" ":" "integer"
-#line 2885 "dhcp6_parser.yy"
+#line 2886 "dhcp6_parser.yy"
                                                              {
     ctx.unique("config-fetch-wait-time", ctx.loc2pos(yystack_[2].location));
     ElementPtr value(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("config-fetch-wait-time", value);
 }
-#line 4498 "dhcp6_parser.cc"
+#line 4499 "dhcp6_parser.cc"
     break;
 
   case 821: // $@127: %empty
-#line 2893 "dhcp6_parser.yy"
+#line 2894 "dhcp6_parser.yy"
                  {
     ctx.unique("loggers", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -4506,83 +4507,83 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.LOGGERS);
 }
-#line 4510 "dhcp6_parser.cc"
+#line 4511 "dhcp6_parser.cc"
     break;
 
   case 822: // loggers: "loggers" $@127 ":" "[" loggers_entries "]"
-#line 2899 "dhcp6_parser.yy"
+#line 2900 "dhcp6_parser.yy"
                                                          {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4519 "dhcp6_parser.cc"
+#line 4520 "dhcp6_parser.cc"
     break;
 
   case 825: // loggers_entries: loggers_entries ","
-#line 2908 "dhcp6_parser.yy"
+#line 2909 "dhcp6_parser.yy"
                                        {
                    ctx.warnAboutExtraCommas(yystack_[0].location);
                    }
-#line 4527 "dhcp6_parser.cc"
+#line 4528 "dhcp6_parser.cc"
     break;
 
   case 826: // $@128: %empty
-#line 2914 "dhcp6_parser.yy"
+#line 2915 "dhcp6_parser.yy"
                              {
     ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(l);
     ctx.stack_.push_back(l);
 }
-#line 4537 "dhcp6_parser.cc"
+#line 4538 "dhcp6_parser.cc"
     break;
 
   case 827: // logger_entry: "{" $@128 logger_params "}"
-#line 2918 "dhcp6_parser.yy"
+#line 2919 "dhcp6_parser.yy"
                                {
     ctx.stack_.pop_back();
 }
-#line 4545 "dhcp6_parser.cc"
+#line 4546 "dhcp6_parser.cc"
     break;
 
   case 830: // logger_params: logger_params ","
-#line 2924 "dhcp6_parser.yy"
+#line 2925 "dhcp6_parser.yy"
                                    {
                  ctx.warnAboutExtraCommas(yystack_[0].location);
                  }
-#line 4553 "dhcp6_parser.cc"
+#line 4554 "dhcp6_parser.cc"
     break;
 
   case 838: // debuglevel: "debuglevel" ":" "integer"
-#line 2938 "dhcp6_parser.yy"
+#line 2939 "dhcp6_parser.yy"
                                      {
     ctx.unique("debuglevel", ctx.loc2pos(yystack_[2].location));
     ElementPtr dl(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("debuglevel", dl);
 }
-#line 4563 "dhcp6_parser.cc"
+#line 4564 "dhcp6_parser.cc"
     break;
 
   case 839: // $@129: %empty
-#line 2944 "dhcp6_parser.yy"
+#line 2945 "dhcp6_parser.yy"
                    {
     ctx.unique("severity", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4572 "dhcp6_parser.cc"
+#line 4573 "dhcp6_parser.cc"
     break;
 
   case 840: // severity: "severity" $@129 ":" "constant string"
-#line 2947 "dhcp6_parser.yy"
+#line 2948 "dhcp6_parser.yy"
                {
     ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("severity", sev);
     ctx.leave();
 }
-#line 4582 "dhcp6_parser.cc"
+#line 4583 "dhcp6_parser.cc"
     break;
 
   case 841: // $@130: %empty
-#line 2953 "dhcp6_parser.yy"
+#line 2954 "dhcp6_parser.yy"
                                     {
     ctx.unique("output-options", ctx.loc2pos(yystack_[0].location));
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
@@ -4590,122 +4591,122 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(l);
     ctx.enter(ctx.OUTPUT_OPTIONS);
 }
-#line 4594 "dhcp6_parser.cc"
+#line 4595 "dhcp6_parser.cc"
     break;
 
   case 842: // output_options_list: "output-options" $@130 ":" "[" output_options_list_content "]"
-#line 2959 "dhcp6_parser.yy"
+#line 2960 "dhcp6_parser.yy"
                                                                     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4603 "dhcp6_parser.cc"
+#line 4604 "dhcp6_parser.cc"
     break;
 
   case 845: // output_options_list_content: output_options_list_content ","
-#line 2966 "dhcp6_parser.yy"
+#line 2967 "dhcp6_parser.yy"
                                                                {
                                ctx.warnAboutExtraCommas(yystack_[0].location);
                                }
-#line 4611 "dhcp6_parser.cc"
+#line 4612 "dhcp6_parser.cc"
     break;
 
   case 846: // $@131: %empty
-#line 2971 "dhcp6_parser.yy"
+#line 2972 "dhcp6_parser.yy"
                              {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 4621 "dhcp6_parser.cc"
+#line 4622 "dhcp6_parser.cc"
     break;
 
   case 847: // output_entry: "{" $@131 output_params_list "}"
-#line 2975 "dhcp6_parser.yy"
+#line 2976 "dhcp6_parser.yy"
                                     {
     ctx.stack_.pop_back();
 }
-#line 4629 "dhcp6_parser.cc"
+#line 4630 "dhcp6_parser.cc"
     break;
 
   case 850: // output_params_list: output_params_list ","
-#line 2981 "dhcp6_parser.yy"
+#line 2982 "dhcp6_parser.yy"
                                              {
                       ctx.warnAboutExtraCommas(yystack_[0].location);
                       }
-#line 4637 "dhcp6_parser.cc"
+#line 4638 "dhcp6_parser.cc"
     break;
 
   case 856: // $@132: %empty
-#line 2993 "dhcp6_parser.yy"
+#line 2994 "dhcp6_parser.yy"
                {
     ctx.unique("output", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4646 "dhcp6_parser.cc"
+#line 4647 "dhcp6_parser.cc"
     break;
 
   case 857: // output: "output" $@132 ":" "constant string"
-#line 2996 "dhcp6_parser.yy"
+#line 2997 "dhcp6_parser.yy"
                {
     ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output", sev);
     ctx.leave();
 }
-#line 4656 "dhcp6_parser.cc"
+#line 4657 "dhcp6_parser.cc"
     break;
 
   case 858: // flush: "flush" ":" "boolean"
-#line 3002 "dhcp6_parser.yy"
+#line 3003 "dhcp6_parser.yy"
                            {
     ctx.unique("flush", ctx.loc2pos(yystack_[2].location));
     ElementPtr flush(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("flush", flush);
 }
-#line 4666 "dhcp6_parser.cc"
+#line 4667 "dhcp6_parser.cc"
     break;
 
   case 859: // maxsize: "maxsize" ":" "integer"
-#line 3008 "dhcp6_parser.yy"
+#line 3009 "dhcp6_parser.yy"
                                {
     ctx.unique("maxsize", ctx.loc2pos(yystack_[2].location));
     ElementPtr maxsize(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("maxsize", maxsize);
 }
-#line 4676 "dhcp6_parser.cc"
+#line 4677 "dhcp6_parser.cc"
     break;
 
   case 860: // maxver: "maxver" ":" "integer"
-#line 3014 "dhcp6_parser.yy"
+#line 3015 "dhcp6_parser.yy"
                              {
     ctx.unique("maxver", ctx.loc2pos(yystack_[2].location));
     ElementPtr maxver(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("maxver", maxver);
 }
-#line 4686 "dhcp6_parser.cc"
+#line 4687 "dhcp6_parser.cc"
     break;
 
   case 861: // $@133: %empty
-#line 3020 "dhcp6_parser.yy"
+#line 3021 "dhcp6_parser.yy"
                  {
     ctx.unique("pattern", ctx.loc2pos(yystack_[0].location));
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 4695 "dhcp6_parser.cc"
+#line 4696 "dhcp6_parser.cc"
     break;
 
   case 862: // pattern: "pattern" $@133 ":" "constant string"
-#line 3023 "dhcp6_parser.yy"
+#line 3024 "dhcp6_parser.yy"
                {
     ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("pattern", sev);
     ctx.leave();
 }
-#line 4705 "dhcp6_parser.cc"
+#line 4706 "dhcp6_parser.cc"
     break;
 
   case 863: // $@134: %empty
-#line 3029 "dhcp6_parser.yy"
+#line 3030 "dhcp6_parser.yy"
                              {
     ctx.unique("compatibility", ctx.loc2pos(yystack_[0].location));
     ElementPtr i(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -4713,38 +4714,38 @@ namespace isc { namespace dhcp {
     ctx.stack_.push_back(i);
     ctx.enter(ctx.COMPATIBILITY);
 }
-#line 4717 "dhcp6_parser.cc"
+#line 4718 "dhcp6_parser.cc"
     break;
 
   case 864: // compatibility: "compatibility" $@134 ":" "{" compatibility_params "}"
-#line 3035 "dhcp6_parser.yy"
+#line 3036 "dhcp6_parser.yy"
                                                            {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 4726 "dhcp6_parser.cc"
+#line 4727 "dhcp6_parser.cc"
     break;
 
   case 867: // compatibility_params: compatibility_params ","
-#line 3042 "dhcp6_parser.yy"
+#line 3043 "dhcp6_parser.yy"
                                                  {
                         ctx.warnAboutExtraCommas(yystack_[0].location);
                         }
-#line 4734 "dhcp6_parser.cc"
+#line 4735 "dhcp6_parser.cc"
     break;
 
   case 870: // lenient_option_parsing: "lenient-option-parsing" ":" "boolean"
-#line 3051 "dhcp6_parser.yy"
+#line 3052 "dhcp6_parser.yy"
                                                              {
     ctx.unique("lenient-option-parsing", ctx.loc2pos(yystack_[2].location));
     ElementPtr b(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("lenient-option-parsing", b);
 }
-#line 4744 "dhcp6_parser.cc"
+#line 4745 "dhcp6_parser.cc"
     break;
 
 
-#line 4748 "dhcp6_parser.cc"
+#line 4749 "dhcp6_parser.cc"
 
             default:
               break;
@@ -6298,80 +6299,80 @@ namespace isc { namespace dhcp {
      538,   539,   540,   541,   542,   543,   544,   545,   546,   547,
      548,   549,   550,   551,   552,   553,   554,   555,   556,   557,
      558,   559,   560,   561,   562,   563,   564,   565,   566,   567,
-     570,   570,   579,   585,   591,   597,   603,   609,   615,   621,
-     627,   633,   639,   645,   651,   657,   663,   669,   675,   681,
-     681,   690,   693,   696,   699,   702,   708,   708,   717,   717,
-     726,   735,   745,   745,   754,   757,   760,   763,   768,   774,
-     774,   783,   783,   792,   798,   804,   810,   810,   819,   825,
-     825,   834,   834,   843,   849,   855,   861,   861,   873,   873,
-     882,   883,   884,   889,   890,   891,   892,   893,   894,   895,
-     896,   899,   899,   910,   916,   922,   928,   934,   934,   947,
-     947,   960,   960,   971,   972,   975,   976,   977,   982,   982,
-     992,   993,   994,   999,  1000,  1001,  1002,  1003,  1004,  1005,
-    1006,  1007,  1008,  1009,  1010,  1011,  1012,  1013,  1014,  1015,
-    1016,  1017,  1018,  1019,  1020,  1021,  1024,  1024,  1032,  1033,
-    1034,  1037,  1037,  1046,  1046,  1055,  1055,  1064,  1070,  1070,
-    1079,  1085,  1091,  1097,  1103,  1109,  1115,  1122,  1128,  1128,
-    1136,  1137,  1138,  1141,  1147,  1153,  1159,  1159,  1168,  1168,
-    1177,  1177,  1186,  1186,  1195,  1195,  1206,  1207,  1208,  1213,
-    1214,  1217,  1217,  1236,  1236,  1254,  1254,  1265,  1266,  1267,
-    1272,  1273,  1276,  1281,  1286,  1286,  1297,  1298,  1299,  1304,
-    1305,  1306,  1309,  1314,  1321,  1321,  1334,  1334,  1347,  1348,
-    1349,  1354,  1355,  1356,  1357,  1358,  1359,  1362,  1368,  1374,
-    1380,  1380,  1391,  1392,  1395,  1396,  1397,  1402,  1402,  1412,
-    1412,  1422,  1423,  1424,  1427,  1430,  1431,  1434,  1434,  1443,
-    1443,  1452,  1452,  1464,  1465,  1466,  1471,  1472,  1473,  1474,
-    1475,  1476,  1479,  1485,  1491,  1497,  1503,  1509,  1518,  1518,
-    1532,  1533,  1536,  1537,  1538,  1547,  1547,  1573,  1573,  1584,
-    1585,  1586,  1592,  1593,  1594,  1595,  1596,  1597,  1598,  1599,
-    1600,  1601,  1602,  1603,  1604,  1605,  1606,  1607,  1608,  1609,
-    1610,  1611,  1612,  1613,  1614,  1615,  1616,  1617,  1618,  1619,
-    1620,  1621,  1622,  1623,  1624,  1625,  1626,  1627,  1628,  1629,
-    1630,  1631,  1632,  1633,  1634,  1635,  1636,  1637,  1640,  1640,
-    1649,  1649,  1658,  1658,  1667,  1667,  1676,  1676,  1687,  1693,
-    1699,  1705,  1711,  1719,  1719,  1731,  1732,  1736,  1737,  1738,
-    1743,  1743,  1751,  1752,  1753,  1758,  1759,  1760,  1761,  1762,
-    1763,  1764,  1765,  1766,  1767,  1768,  1769,  1770,  1771,  1772,
-    1773,  1774,  1775,  1776,  1777,  1778,  1779,  1780,  1781,  1782,
-    1783,  1784,  1785,  1786,  1787,  1788,  1789,  1790,  1791,  1792,
-    1793,  1794,  1795,  1796,  1797,  1798,  1799,  1800,  1807,  1807,
-    1821,  1821,  1830,  1831,  1834,  1835,  1836,  1843,  1843,  1858,
-    1858,  1872,  1873,  1876,  1877,  1878,  1883,  1884,  1885,  1886,
-    1887,  1888,  1889,  1890,  1891,  1892,  1895,  1897,  1903,  1905,
-    1905,  1914,  1914,  1923,  1923,  1932,  1934,  1934,  1943,  1953,
-    1953,  1966,  1967,  1972,  1973,  1974,  1981,  1981,  1993,  1993,
-    2005,  2006,  2011,  2012,  2013,  2020,  2021,  2022,  2023,  2024,
-    2025,  2026,  2027,  2028,  2029,  2032,  2034,  2034,  2043,  2045,
-    2047,  2053,  2059,  2068,  2068,  2081,  2082,  2085,  2086,  2087,
-    2092,  2092,  2102,  2102,  2112,  2113,  2114,  2119,  2120,  2121,
-    2122,  2123,  2124,  2125,  2126,  2129,  2129,  2138,  2144,  2144,
-    2169,  2169,  2199,  2199,  2212,  2213,  2216,  2217,  2218,  2223,
-    2223,  2235,  2235,  2247,  2248,  2249,  2254,  2255,  2256,  2257,
-    2258,  2259,  2260,  2261,  2262,  2263,  2264,  2265,  2268,  2268,
-    2277,  2283,  2283,  2292,  2298,  2307,  2307,  2318,  2319,  2322,
-    2323,  2324,  2329,  2329,  2338,  2338,  2347,  2348,  2351,  2352,
-    2353,  2359,  2360,  2361,  2362,  2363,  2364,  2365,  2366,  2367,
-    2368,  2369,  2372,  2372,  2383,  2383,  2394,  2394,  2403,  2403,
-    2412,  2412,  2421,  2421,  2430,  2430,  2444,  2444,  2455,  2461,
-    2461,  2472,  2473,  2474,  2479,  2479,  2489,  2490,  2493,  2494,
-    2495,  2500,  2501,  2502,  2503,  2504,  2505,  2506,  2507,  2508,
-    2509,  2510,  2511,  2512,  2513,  2516,  2518,  2518,  2527,  2527,
-    2536,  2545,  2545,  2558,  2559,  2560,  2565,  2566,  2567,  2568,
-    2569,  2570,  2571,  2572,  2573,  2576,  2576,  2584,  2585,  2586,
-    2589,  2595,  2595,  2604,  2610,  2618,  2626,  2626,  2637,  2638,
-    2639,  2644,  2645,  2646,  2647,  2648,  2651,  2651,  2660,  2660,
-    2672,  2672,  2685,  2686,  2687,  2692,  2693,  2694,  2695,  2696,
-    2697,  2700,  2706,  2706,  2715,  2721,  2721,  2731,  2731,  2744,
-    2744,  2754,  2755,  2756,  2761,  2762,  2763,  2764,  2765,  2766,
-    2767,  2768,  2769,  2770,  2771,  2774,  2780,  2780,  2789,  2795,
-    2795,  2804,  2810,  2816,  2816,  2825,  2826,  2829,  2829,  2840,
-    2840,  2852,  2852,  2862,  2863,  2864,  2870,  2871,  2874,  2874,
-    2885,  2893,  2893,  2906,  2907,  2908,  2914,  2914,  2922,  2923,
-    2924,  2929,  2930,  2931,  2932,  2933,  2934,  2935,  2938,  2944,
-    2944,  2953,  2953,  2964,  2965,  2966,  2971,  2971,  2979,  2980,
-    2981,  2986,  2987,  2988,  2989,  2990,  2993,  2993,  3002,  3008,
-    3014,  3020,  3020,  3029,  3029,  3040,  3041,  3042,  3047,  3048,
-    3051
+     570,   570,   580,   586,   592,   598,   604,   610,   616,   622,
+     628,   634,   640,   646,   652,   658,   664,   670,   676,   682,
+     682,   691,   694,   697,   700,   703,   709,   709,   718,   718,
+     727,   736,   746,   746,   755,   758,   761,   764,   769,   775,
+     775,   784,   784,   793,   799,   805,   811,   811,   820,   826,
+     826,   835,   835,   844,   850,   856,   862,   862,   874,   874,
+     883,   884,   885,   890,   891,   892,   893,   894,   895,   896,
+     897,   900,   900,   911,   917,   923,   929,   935,   935,   948,
+     948,   961,   961,   972,   973,   976,   977,   978,   983,   983,
+     993,   994,   995,  1000,  1001,  1002,  1003,  1004,  1005,  1006,
+    1007,  1008,  1009,  1010,  1011,  1012,  1013,  1014,  1015,  1016,
+    1017,  1018,  1019,  1020,  1021,  1022,  1025,  1025,  1033,  1034,
+    1035,  1038,  1038,  1047,  1047,  1056,  1056,  1065,  1071,  1071,
+    1080,  1086,  1092,  1098,  1104,  1110,  1116,  1123,  1129,  1129,
+    1137,  1138,  1139,  1142,  1148,  1154,  1160,  1160,  1169,  1169,
+    1178,  1178,  1187,  1187,  1196,  1196,  1207,  1208,  1209,  1214,
+    1215,  1218,  1218,  1237,  1237,  1255,  1255,  1266,  1267,  1268,
+    1273,  1274,  1277,  1282,  1287,  1287,  1298,  1299,  1300,  1305,
+    1306,  1307,  1310,  1315,  1322,  1322,  1335,  1335,  1348,  1349,
+    1350,  1355,  1356,  1357,  1358,  1359,  1360,  1363,  1369,  1375,
+    1381,  1381,  1392,  1393,  1396,  1397,  1398,  1403,  1403,  1413,
+    1413,  1423,  1424,  1425,  1428,  1431,  1432,  1435,  1435,  1444,
+    1444,  1453,  1453,  1465,  1466,  1467,  1472,  1473,  1474,  1475,
+    1476,  1477,  1480,  1486,  1492,  1498,  1504,  1510,  1519,  1519,
+    1533,  1534,  1537,  1538,  1539,  1548,  1548,  1574,  1574,  1585,
+    1586,  1587,  1593,  1594,  1595,  1596,  1597,  1598,  1599,  1600,
+    1601,  1602,  1603,  1604,  1605,  1606,  1607,  1608,  1609,  1610,
+    1611,  1612,  1613,  1614,  1615,  1616,  1617,  1618,  1619,  1620,
+    1621,  1622,  1623,  1624,  1625,  1626,  1627,  1628,  1629,  1630,
+    1631,  1632,  1633,  1634,  1635,  1636,  1637,  1638,  1641,  1641,
+    1650,  1650,  1659,  1659,  1668,  1668,  1677,  1677,  1688,  1694,
+    1700,  1706,  1712,  1720,  1720,  1732,  1733,  1737,  1738,  1739,
+    1744,  1744,  1752,  1753,  1754,  1759,  1760,  1761,  1762,  1763,
+    1764,  1765,  1766,  1767,  1768,  1769,  1770,  1771,  1772,  1773,
+    1774,  1775,  1776,  1777,  1778,  1779,  1780,  1781,  1782,  1783,
+    1784,  1785,  1786,  1787,  1788,  1789,  1790,  1791,  1792,  1793,
+    1794,  1795,  1796,  1797,  1798,  1799,  1800,  1801,  1808,  1808,
+    1822,  1822,  1831,  1832,  1835,  1836,  1837,  1844,  1844,  1859,
+    1859,  1873,  1874,  1877,  1878,  1879,  1884,  1885,  1886,  1887,
+    1888,  1889,  1890,  1891,  1892,  1893,  1896,  1898,  1904,  1906,
+    1906,  1915,  1915,  1924,  1924,  1933,  1935,  1935,  1944,  1954,
+    1954,  1967,  1968,  1973,  1974,  1975,  1982,  1982,  1994,  1994,
+    2006,  2007,  2012,  2013,  2014,  2021,  2022,  2023,  2024,  2025,
+    2026,  2027,  2028,  2029,  2030,  2033,  2035,  2035,  2044,  2046,
+    2048,  2054,  2060,  2069,  2069,  2082,  2083,  2086,  2087,  2088,
+    2093,  2093,  2103,  2103,  2113,  2114,  2115,  2120,  2121,  2122,
+    2123,  2124,  2125,  2126,  2127,  2130,  2130,  2139,  2145,  2145,
+    2170,  2170,  2200,  2200,  2213,  2214,  2217,  2218,  2219,  2224,
+    2224,  2236,  2236,  2248,  2249,  2250,  2255,  2256,  2257,  2258,
+    2259,  2260,  2261,  2262,  2263,  2264,  2265,  2266,  2269,  2269,
+    2278,  2284,  2284,  2293,  2299,  2308,  2308,  2319,  2320,  2323,
+    2324,  2325,  2330,  2330,  2339,  2339,  2348,  2349,  2352,  2353,
+    2354,  2360,  2361,  2362,  2363,  2364,  2365,  2366,  2367,  2368,
+    2369,  2370,  2373,  2373,  2384,  2384,  2395,  2395,  2404,  2404,
+    2413,  2413,  2422,  2422,  2431,  2431,  2445,  2445,  2456,  2462,
+    2462,  2473,  2474,  2475,  2480,  2480,  2490,  2491,  2494,  2495,
+    2496,  2501,  2502,  2503,  2504,  2505,  2506,  2507,  2508,  2509,
+    2510,  2511,  2512,  2513,  2514,  2517,  2519,  2519,  2528,  2528,
+    2537,  2546,  2546,  2559,  2560,  2561,  2566,  2567,  2568,  2569,
+    2570,  2571,  2572,  2573,  2574,  2577,  2577,  2585,  2586,  2587,
+    2590,  2596,  2596,  2605,  2611,  2619,  2627,  2627,  2638,  2639,
+    2640,  2645,  2646,  2647,  2648,  2649,  2652,  2652,  2661,  2661,
+    2673,  2673,  2686,  2687,  2688,  2693,  2694,  2695,  2696,  2697,
+    2698,  2701,  2707,  2707,  2716,  2722,  2722,  2732,  2732,  2745,
+    2745,  2755,  2756,  2757,  2762,  2763,  2764,  2765,  2766,  2767,
+    2768,  2769,  2770,  2771,  2772,  2775,  2781,  2781,  2790,  2796,
+    2796,  2805,  2811,  2817,  2817,  2826,  2827,  2830,  2830,  2841,
+    2841,  2853,  2853,  2863,  2864,  2865,  2871,  2872,  2875,  2875,
+    2886,  2894,  2894,  2907,  2908,  2909,  2915,  2915,  2923,  2924,
+    2925,  2930,  2931,  2932,  2933,  2934,  2935,  2936,  2939,  2945,
+    2945,  2954,  2954,  2965,  2966,  2967,  2972,  2972,  2980,  2981,
+    2982,  2987,  2988,  2989,  2990,  2991,  2994,  2994,  3003,  3009,
+    3015,  3021,  3021,  3030,  3030,  3041,  3042,  3043,  3048,  3049,
+    3052
   };
 
   void
@@ -6404,9 +6405,9 @@ namespace isc { namespace dhcp {
 
 #line 14 "dhcp6_parser.yy"
 } } // isc::dhcp
-#line 6408 "dhcp6_parser.cc"
+#line 6409 "dhcp6_parser.cc"
 
-#line 3057 "dhcp6_parser.yy"
+#line 3058 "dhcp6_parser.yy"
 
 
 void
index 834dfbca25c5767990aac909b510a322a4c94e36..7eccc51d1d95e5869f3872766bfd4293440066b8 100644 (file)
@@ -572,6 +572,7 @@ data_directory: DATA_DIRECTORY {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     ElementPtr datadir(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.warning(@2, "data-directory is deprecated and will be ignored");
     ctx.stack_.back()->set("data-directory", datadir);
     ctx.leave();
 };
index 671d69a802ebbb3180e16894fa2c5a40b14abe73..ffa6b5735b5203bc840a429c5b68a4d9d5a0086a 100644 (file)
@@ -73,21 +73,6 @@ using namespace isc::util;
 
 namespace {
 
-/// @brief Checks if specified directory exists.
-///
-/// @param dir_path Path to a directory.
-/// @throw BadValue If the directory does not exist or is not a directory.
-void dirExists(const string& dir_path) {
-    struct stat statbuf;
-    if (stat(dir_path.c_str(), &statbuf) < 0) {
-        isc_throw(BadValue, "Bad directory '" << dir_path
-                  << "': " << strerror(errno));
-    }
-    if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
-        isc_throw(BadValue, "'" << dir_path << "' is not a directory");
-    }
-}
-
 /// @brief Parser for list of RSOO options
 ///
 /// This parser handles a Dhcp6/relay-supplied-options entry. It contains a
@@ -182,8 +167,15 @@ public:
 
         // Set the data directory for server id file.
         if (global->contains("data-directory")) {
-            CfgMgr::instance().setDataDir(getString(global, "data-directory"),
-                                          false);
+            auto dd = getString(global, "data-directory");
+            if (dd != CfgMgr::instance().getDataDir()) {
+                isc_throw(DhcpConfigError,
+                          "'data-directory' of '" << dd << "' is invalid,"
+                          << " supported path is '"
+                          << CfgMgr::instance().getDataDir() << "'");
+            }
+
+            LOG_WARN(dhcp6_logger, DHCP6_DATA_DIRECTORY_DEPRECATED);
         }
 
         // Set the probation period for decline handling.
@@ -472,13 +464,6 @@ processDhcp6Config(isc::data::ConstElementPtr config_set) {
         // Apply global options in the staging config, e.g. ip-reservations-unique
         global_parser.parseEarly(srv_config, mutable_cfg);
 
-        // Specific check for this global parameter.
-        ConstElementPtr data_directory = mutable_cfg->get("data-directory");
-        if (data_directory) {
-            parameter_name = "data-directory";
-            dirExists(data_directory->stringValue());
-        }
-
         // We need definitions first
         ConstElementPtr option_defs = mutable_cfg->get("option-def");
         if (option_defs) {
index 12f4fc222598d172f0918966003a2c13f491be1f..fc89031260fb06fd4864bfd2eca24397bb001b53 100644 (file)
@@ -15,6 +15,7 @@ DISTCLEANFILES += marker_file.h
 DISTCLEANFILES += test_data_files_config.h
 DISTCLEANFILES += test_libraries.h
 
+dhcp_data_dir = @localstatedir@/lib/@PACKAGE@
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 AM_CPPFLAGS += -I$(top_srcdir)/src -I$(top_builddir)/src
@@ -25,6 +26,7 @@ AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
 AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/kea6\"
 AM_CPPFLAGS += -DSYNTAX_FILE=\"$(abs_srcdir)/../dhcp6_parser.yy\"
 AM_CPPFLAGS += -DKEA_LFC_EXECUTABLE=\"$(abs_top_builddir)/src/bin/lfc/kea-lfc\"
+AM_CPPFLAGS += -DDHCP_DATA_DIR="\"$(dhcp_data_dir)\""
 
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
 
index dfbe6175cf8edec389b3694eaabd116addeaad55..ab95e57e1ed9fcc0135c66896baedefe6f2ec672 100644 (file)
@@ -365,7 +365,7 @@ const char* PARSER_CONFIGS[] = {
     "}"
 };
 
-class Dhcp6ParserTest : public LogContentTest {
+class Dhcp6ParserTest : public BaseServerTest {
 protected:
     // Check that no hooks libraries are loaded.  This is a pre-condition for
     // a number of tests, so is checked in one place.  As this uses an
@@ -6408,31 +6408,9 @@ TEST_F(Dhcp6ParserTest, rsooBogusName) {
     EXPECT_TRUE(errorContainsPosition(status, "<string>"));
 }
 
-/// Check that not existent data directory returns an error.
-TEST_F(Dhcp6ParserTest, notExistDataDir) {
-
-    string config_txt = "{\n"
-        "\"data-directory\": \"/does-not-exist--\"\n"
-        "}";
-    ConstElementPtr config;
-    ASSERT_NO_THROW(config = parseDHCP6(config_txt));
-
-    ConstElementPtr status;
-    EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, config));
-
-    // returned value should be 1 (error)
-    int rcode;
-    ConstElementPtr comment = parseAnswerText(rcode, status);
-    EXPECT_EQ(1, rcode);
-    string text;
-    ASSERT_NO_THROW(text = comment->stringValue());
-    EXPECT_EQ("Bad directory '/does-not-exist--': No such file or directory",
-              text);
-}
-
-/// Check that not a directory data directory returns an error.
-TEST_F(Dhcp6ParserTest, notDirDataDir) {
-
+/// Checks that an invalid data-directory path returns an error.
+TEST_F(Dhcp6ParserTest, invalidDataDir) {
+    CfgMgr::instance().getDataDir(true, TEST_DATA_BUILDDIR);
     string config_txt = "{\n"
         "\"data-directory\": \"/dev/null\"\n"
         "}";
@@ -6448,32 +6426,27 @@ TEST_F(Dhcp6ParserTest, notDirDataDir) {
     EXPECT_EQ(1, rcode);
     string text;
     ASSERT_NO_THROW(text = comment->stringValue());
-    EXPECT_EQ("'/dev/null' is not a directory", text);
+    std::ostringstream os;
+    os << "'data-directory' of '/dev/null' is invalid, supported path is '"
+       << CfgMgr::instance().getDataDir() << "'";
+
+    EXPECT_EQ(os.str(), text);
 }
 
 /// Check that a valid data directory is accepted.
-TEST_F(Dhcp6ParserTest, testDataDir) {
+TEST_F(Dhcp6ParserTest, validDataDir) {
+    std::ostringstream os;
+    os << "{\"data-directory\": \""
+       << CfgMgr::instance().getDataDir() << "\"}";
 
-    EXPECT_TRUE(CfgMgr::instance().getDataDir().unspecified());
-    string original_datadir(CfgMgr::instance().getDataDir());
-    string datadir(TEST_DATA_BUILDDIR);
-    string config_txt = "{\n"
-        "\"data-directory\": \"" + datadir + "\"\n"
-        "}";
     ConstElementPtr config;
-    ASSERT_NO_THROW(config = parseDHCP6(config_txt));
-    // Do not export it as it will keep the current TEST_DATA_BUILDDIR...
+    ASSERT_NO_THROW(config = parseDHCP6(os.str()));
 
     ConstElementPtr status;
     EXPECT_NO_THROW(status = Dhcpv6SrvTest::configure(srv_, config));
 
     // returned value should be 0 (success);
     checkResult(status, 0);
-
-    // The value of data-directory was updated.
-    EXPECT_FALSE(CfgMgr::instance().getDataDir().unspecified());
-    EXPECT_EQ(datadir, string(CfgMgr::instance().getDataDir()));
-    EXPECT_NE(original_datadir, string(CfgMgr::instance().getDataDir()));
 }
 
 /// Check that the dhcp4o6-port default value has a default value if not
index 41dfef633268c2ff90f554530081a2335711483c..85b0c927d177ae20fc67eb57c25245461f624902 100644 (file)
@@ -15,6 +15,7 @@ CFG_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_config.json"
 # Path to the Kea log file.
 LOG_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test.log"
 # Path to the Kea lease file.
+export KEA_DHCP_DATA_DIR="@abs_top_builddir@/src/bin/dhcp6/tests"
 LEASE_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_leases.csv"
 # Path to the Kea LFC application
 export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
index 8d3baded461971f2304e8e098cda114a159cecac..ac050770409cab82d8795020d1479bdc9ae144a0 100644 (file)
@@ -32,9 +32,11 @@ namespace test {
 
 const char* BaseServerTest::DUID_FILE = "kea-dhcp6-serverid";
 
-BaseServerTest::BaseServerTest()
-    : original_datadir_(CfgMgr::instance().getDataDir()) {
-    CfgMgr::instance().setDataDir(TEST_DATA_BUILDDIR);
+BaseServerTest::BaseServerTest() {
+    isc::dhcp::CfgMgr::instance().clear();
+    CfgMgr::instance().setFamily(AF_INET6);
+    original_datadir_ = CfgMgr::instance().getDataDir();
+    CfgMgr::instance().getDataDir(true, TEST_DATA_BUILDDIR);
 }
 
 BaseServerTest::~BaseServerTest() {
@@ -48,10 +50,14 @@ BaseServerTest::~BaseServerTest() {
     s2 << CfgMgr::instance().getDataDir() << "/kea-leases6.csv";
     static_cast<void>(::remove(s2.str().c_str()));
 
+    std::ostringstream s3;
+    s3 << CfgMgr::instance().getDataDir() << "/kea-dhcp6.csv";
+    static_cast<void>(::remove(s3.str().c_str()));
+
     // Revert to original data directory.
-    CfgMgr::instance().setDataDir(original_datadir_);
+    CfgMgr::instance().getDataDir(true, original_datadir_);
 
-    // Revert to unit test logging in case the test reconfigured logging.
+    // Revert to unit test logging, in case the test reconfigured it.
     isc::log::initLogger();
 }
 
index b67a36d6b1dcd337479795bdbe2c8904a6922af4..fd7a11f474d5b0bd41c342fc8372dafc5ea4455d 100644 (file)
@@ -32,6 +32,7 @@
 #include <hooks/hooks_manager.h>
 #include <config/command_mgr.h>
 #include <util/multi_threading_mgr.h>
+#include <testutils/log_utils.h>
 
 #include <list>
 
@@ -112,7 +113,7 @@ struct StrictIAIDChecking : public SpecializedTypeWrapper<bool> {
 /// Currently it configures the test data path directory in
 /// the @c CfgMgr. When the object is destroyed, the original
 /// path is reverted.
-class BaseServerTest : public ::testing::Test {
+class BaseServerTest : public LogContentTest {
 public:
 
     /// @brief Location of a test DUID file
index b262409140bcdd3118123859249c2d27b0d8e99e..f86ac241eee43f5e64a0d927bea0f3c1cd875f50 100644 (file)
@@ -1093,12 +1093,12 @@ bool HooksDhcpv6SrvTest::callback_rev_update_;
 DdnsParamsPtr HooksDhcpv6SrvTest::callback_ddns_params_;
 
 /// @brief Fixture class used to do basic library load/unload tests
-class LoadUnloadDhcpv6SrvTest : public Dhcpv6SrvTest {
+class LoadUnloadDhcpv6SrvTest : public BaseServerTest {
 public:
     /// @brief Pointer to the tested server object
     boost::shared_ptr<NakedDhcpv6Srv> server_;
 
-    LoadUnloadDhcpv6SrvTest() : Dhcpv6SrvTest() {
+    LoadUnloadDhcpv6SrvTest() {
         reset();
         MultiThreadingMgr::instance().setMode(false);
         resetHooksPath();
index 1ba44e123606678016e821348e914fa9a102be62..0fd9a117de8972d70cd3502a08ae87b25f602c8c 100644 (file)
@@ -780,6 +780,7 @@ TEST(ParserTest, mapEntries) {
     loadFile(sample_dir + "reservations.json", sample_json);
     loadFile(sample_dir + "all-keys-netconf.json", sample_json);
     KeywordSet sample_keys = {
+        "data-directory",
         "hosts-database"
     };
     // Recursively extract keywords.
index 9a1300d4893af0024c2da1308e197e111aa64f6a..e1937f70765eadc2c9b256ceca300fcc1dc488a7 100644 (file)
@@ -20,7 +20,8 @@ namespace isc {
 namespace dhcp {
 
 CfgMgr::CfgMgr()
-    : datadir_(DHCP_DATA_DIR, true), d2_client_mgr_(new D2ClientMgr()),
+    : data_dir_checker_(new file::PathChecker(DHCP_DATA_DIR, "KEA_DHCP_DATA_DIR")),
+      d2_client_mgr_(new D2ClientMgr()),
       configuration_(new SrvConfig()), family_(AF_INET) {
 }
 
@@ -30,14 +31,14 @@ CfgMgr::instance() {
     return (cfg_mgr);
 }
 
-Optional<std::string>
-CfgMgr::getDataDir() const {
-    return (datadir_);
+std::string
+CfgMgr::getDataDir(bool reset /* = false */, const std::string explicit_path /* = "" */) {
+    return (data_dir_checker_->getPath(reset, explicit_path));
 }
 
-void
-CfgMgr::setDataDir(const std::string& datadir, bool unspecified) {
-    datadir_ = Optional<std::string>(datadir, unspecified);
+std::string
+CfgMgr::validatePath(const std::string data_path, bool enforce_path /* = true */) const {
+    return (data_dir_checker_->validatePath(data_path, enforce_path));
 }
 
 void
index 553e3a4c8a2f75f32a5b1a795c4f93be20fc981c..56e71f4129294071dd68301a00572fbe4ba0ee1b 100644 (file)
@@ -15,6 +15,7 @@
 #include <dhcpsrv/pool.h>
 #include <dhcpsrv/srv_config.h>
 #include <util/buffer.h>
+#include <util/filesystem.h>
 #include <util/optional.h>
 
 #include <boost/shared_ptr.hpp>
@@ -75,18 +76,31 @@ public:
     /// accessing it.
     static CfgMgr& instance();
 
-    /// @brief returns path do the data directory
+    /// @brief Fetches the supported DHCP data directory.
     ///
-    /// This method returns a path to writable directory that DHCP servers
-    /// can store data in.
-    /// @return data directory
-    util::Optional<std::string> getDataDir() const;
+    /// The first call to this function with no arguments will set the default
+    /// hooks path to either the value of DHCP_DATA_DIR or the environment
+    /// variable KEA_DHCP_DATA_DIR if it is defined.  Subsequent calls with no
+    /// arguments will simply return this value.
+    ///
+    /// @param reset recalculate when true, defaults to false. This is for
+    /// testing purposes only.
+    /// @param explicit_path set default hooks path to this value. This is
+    /// for testing purposes only.
+    ///
+    /// @return String containing the default data directory.
+    std::string getDataDir(bool reset = false,
+                           const std::string explicit_path = "");
 
-    /// @brief Sets new data directory.
+    /// @brief Validates a file path against the supported directory for DHDP data.
+    ///
+    /// @param data_path data path to validate.
+    /// @param enforce_path enables validation against the supported path.
+    /// If false verifies only that the path contains a file name.
     ///
-    /// @param datadir New data directory.
-    /// @param unspecified Initial state. Default is "unspecified".
-    void setDataDir(const std::string& datadir, bool unspecified = true);
+    /// @return validated path
+    std::string validatePath(const std::string data_path,
+                             bool enforce_path = true) const;
 
     /// @brief Updates the DHCP-DDNS client configuration to the given value.
     ///
@@ -260,8 +274,9 @@ private:
     /// @param seq Source configuration sequence number.
     void mergeIntoCfg(const SrvConfigPtr& taget_config, const uint32_t seq);
 
-    /// @brief directory where data files (e.g. server-id) are stored
-    util::Optional<std::string> datadir_;
+    /// @brief PathChecker that provides the supported DHCP data directory
+    /// where data files (e.g. lease files and server-id) are stored.
+    util::file::PathCheckerPtr data_dir_checker_;
 
     /// @brief Manages the DHCP-DDNS client and its configuration.
     D2ClientMgrPtr d2_client_mgr_;
index 992f4d82adc9b3db2f4c38cc189d3e1f4383c464..f10f2340f403b8451b395f5361f3c23453e76ef7 100644 (file)
@@ -97,6 +97,7 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6 = "DH
 extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START = "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START";
 extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4 = "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4";
 extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR = "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR";
+extern const isc::log::MessageID DHCPSRV_MEMFILE_FAILED_TO_OPEN = "DHCPSRV_MEMFILE_FAILED_TO_OPEN";
 extern const isc::log::MessageID DHCPSRV_MEMFILE_GET4 = "DHCPSRV_MEMFILE_GET4";
 extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6 = "DHCPSRV_MEMFILE_GET6";
 extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID = "DHCPSRV_MEMFILE_GET6_DUID";
@@ -381,6 +382,7 @@ const char* values[] = {
     "DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START", "starting deletion of %1 expired-reclaimed leases",
     "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4", "extracting extended info saw %1 leases, extended info sanity checks modified %2 / updated %3 leases and %4 leases have relay or remote id",
     "DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR", "extracting extended info got an exception on the lease for %1: %2",
+    "DHCPSRV_MEMFILE_FAILED_TO_OPEN", "Could not open lease file: %1",
     "DHCPSRV_MEMFILE_GET4", "obtaining all IPv4 leases",
     "DHCPSRV_MEMFILE_GET6", "obtaining all IPv6 leases",
     "DHCPSRV_MEMFILE_GET6_DUID", "obtaining IPv6 leases for DUID %1",
index 9013e7e2d528587045481e03dc4cbca79516c926..4399d6b1152fbdb16fa2ed4082846b73ccfda6a4 100644 (file)
@@ -98,6 +98,7 @@ extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED6;
 extern const isc::log::MessageID DHCPSRV_MEMFILE_DELETE_EXPIRED_RECLAIMED_START;
 extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4;
 extern const isc::log::MessageID DHCPSRV_MEMFILE_EXTRACT_EXTENDED_INFO4_ERROR;
+extern const isc::log::MessageID DHCPSRV_MEMFILE_FAILED_TO_OPEN;
 extern const isc::log::MessageID DHCPSRV_MEMFILE_GET4;
 extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6;
 extern const isc::log::MessageID DHCPSRV_MEMFILE_GET6_DUID;
index a132b414f6629096aa21030069e990a3947e5c95..0964765092d95e679d27d1d264866da79188c3b2 100644 (file)
@@ -1417,3 +1417,11 @@ indicate an error in the source code, please submit a bug report.
 % DHCPSRV_UNKNOWN_DB unknown database type: %1
 The database access string specified a database type (given in the
 message) that is unknown to the software. This is a configuration error.
+
+% DHCPSRV_MEMFILE_FAILED_TO_OPEN Could not open lease file: %1
+This error is issued when the lease file could not be opened. The
+argument contains the details. The most likely cause is that the `name`
+parameter for memfile back end contains a path other than the supported
+path. The argument will contain the details. The path component may
+simply be omitted. To override the default supported path, set the
+environment variable KEA_DHCP_DATA_DIR prior to starting the server.
index 0cb9d019ad33fa4ebba217d33ddf29549a6790ac..5fe1ac7a0392642acff1579d0965a33635ed891e 100644 (file)
@@ -77,9 +77,15 @@ LeaseMgrFactory::create(const std::string& dbaccess) {
 #endif
     }
     if (parameters[type] == string("memfile")) {
-        LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_DB).arg(redacted);
-        getLeaseMgrPtr().reset(new Memfile_LeaseMgr(parameters));
-        return;
+        try {
+            LOG_INFO(dhcpsrv_logger, DHCPSRV_MEMFILE_DB).arg(redacted);
+            getLeaseMgrPtr().reset(new Memfile_LeaseMgr(parameters));
+            return;
+        } catch (const std::exception& ex) {
+            LOG_ERROR(dhcpsrv_logger, DHCPSRV_MEMFILE_FAILED_TO_OPEN)
+                .arg(ex.what());
+            throw;
+        }
     }
 
     // Get here on no match
index 70d8d31b74adb1e742ef26f50a6f1cbe34d2096d..fb385415128958ffbcdc2c13dfc67c0974ab7e02 100644 (file)
@@ -2222,11 +2222,18 @@ Memfile_LeaseMgr::appendSuffix(const std::string& file_name,
 }
 
 std::string
-Memfile_LeaseMgr::getDefaultLeaseFilePath(Universe u) const {
-    std::ostringstream s;
-    s << CfgMgr::instance().getDataDir() << "/kea-leases";
-    s << (u == V4 ? "4" : "6");
-    s << ".csv";
+Memfile_LeaseMgr::getDefaultLeaseFilePath(Universe u,
+                                          std::string filename /* = "" */) const {
+    std::ostringstream s;;
+    s << CfgMgr::instance().getDataDir();
+    if (filename.empty()) {
+        s << "/kea-leases";
+        s << (u == V4 ? "4" : "6");
+        s << ".csv";
+    } else {
+        s << "/" << filename;
+    }
+
     return (s.str());
 }
 
@@ -2275,8 +2282,12 @@ Memfile_LeaseMgr::initLeaseFilePath(Universe u) {
     try {
         lease_file = conn_.getParameter("name");
     } catch (const Exception&) {
-        lease_file = getDefaultLeaseFilePath(u);
+        // Not specified, use the default.
+        return (getDefaultLeaseFilePath(u));
     }
+
+    // If path is invalid this will throw.
+    lease_file = CfgMgr::instance().validatePath(lease_file);
     return (lease_file);
 }
 
index aca9aaf9752d8429bfd390d9bf3356c8e06480e5..9118d7bff7d61797a3dfd2ef96f4d3512e7ba452 100644 (file)
@@ -990,7 +990,9 @@ public:
     /// @brief Returns default path to the lease file.
     ///
     /// @param u Universe (V4 or V6).
-    std::string getDefaultLeaseFilePath(Universe u) const;
+    /// @param filename optional filename to use.
+    std::string getDefaultLeaseFilePath(Universe u,
+                                        const std::string filename = "") const;
 
     /// @brief Returns an absolute path to the lease file.
     ///
index 41bf7ec18b1e46fd5561679e11d4018b9adca8e9..ea26133f15c4b14a3a86ec4cdc7364c17ac6011f 100644 (file)
@@ -726,15 +726,6 @@ SrvConfig::toElement() const {
     // Set user-context
     contextToElement(dhcp);
 
-    // Set data directory if DHCPv6 and specified.
-    if (family == AF_INET6) {
-        const util::Optional<std::string>& datadir =
-            CfgMgr::instance().getDataDir();
-        if (!datadir.unspecified()) {
-            dhcp->set("data-directory", Element::create(datadir));
-        }
-    }
-
     // Set compatibility flags.
     ElementPtr compatibility = Element::createMap();
     if (getLenientOptionParsing()) {
index eb2cd2630f433fdfa20448f010f5838aeab6531a..7799aacde9c1bc6f350ffc5c7c8ec37c60e56338 100644 (file)
@@ -1,9 +1,10 @@
 SUBDIRS = .
 
+dhcp_data_dir = @localstatedir@/lib/@PACKAGE@
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/dhcpsrv/tests\"
-AM_CPPFLAGS += -DDHCP_DATA_DIR=\"$(abs_top_builddir)/src/lib/dhcpsrv/tests\"
+AM_CPPFLAGS += -DDHCP_DATA_DIR="\"$(dhcp_data_dir)\""
 AM_CPPFLAGS += -DKEA_LFC_BUILD_DIR=\"$(abs_top_builddir)/src/bin/lfc\"
 AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
 
index 933b2c8f775bad7ed75cb503ebc3e35179733c72..12c31e70433cdbbf60be67d4b23c6fa663c1e411 100644 (file)
@@ -62,7 +62,7 @@ public:
 std::string
 CfgDUIDTest::absolutePath(const std::string& filename) const {
     std::ostringstream s;
-    s << DHCP_DATA_DIR << "/" << filename;
+    s << TEST_DATA_BUILDDIR << "/" << filename;
     return (s.str());
 }
 
index b57f00dc9474688be86863501bd934aa2e95e6c7..860196ccef66824553d84f5c3c428fd761c3d98e 100644 (file)
@@ -17,6 +17,7 @@
 #include <process/logging_info.h>
 #include <stats/stats_mgr.h>
 #include <util/chrono_time_utils.h>
+#include <testutils/env_var_wrapper.h>
 
 #include <gtest/gtest.h>
 
@@ -33,6 +34,7 @@ using namespace isc::dhcp::test;
 using namespace isc::util;
 using namespace isc::stats;
 using namespace isc::process;
+using namespace isc::test;
 using namespace isc;
 
 namespace {
@@ -256,9 +258,8 @@ TEST(ValueStorageTest, StringTesting) {
 
 class CfgMgrTest : public ::testing::Test {
 public:
-    CfgMgrTest() {
+    CfgMgrTest() : data_dir_env_var_("KEA_DHCP_DATA_DIR") {
         // make sure we start with a clean configuration
-        original_datadir_ = CfgMgr::instance().getDataDir();
         clear();
     }
 
@@ -279,11 +280,24 @@ public:
 
     void clear() {
         CfgMgr::instance().setFamily(AF_INET);
-        CfgMgr::instance().setDataDir(original_datadir_);
+        resetDataDir();
         CfgMgr::instance().clear();
         LeaseMgrFactory::destroy();
     }
 
+    /// @brief Sets the DHCP data path for server data files.
+    /// @param custom_path path to use.
+    void setDataDir(const std::string explicit_path = "") {
+        CfgMgr::instance().getDataDir(true,
+                                      (!explicit_path.empty() ?
+                                      explicit_path : std::string(DHCP_DATA_DIR)));
+    }
+
+    /// @brief Resets the DHCP data path to DHCP_DATA_DIR.
+    void resetDataDir() {
+        CfgMgr::instance().getDataDir(true);
+    }
+
     /// @brief Creates instance of the backend.
     ///
     /// @param family AF_INET for v4, AF_INET6 for v6
@@ -301,18 +315,16 @@ public:
         CfgMgr::instance().setFamily(family);
     }
 
+    /// @brief RAII wrapper for KEA_DHCP_DATA_DIR env variable.
+    EnvVarWrapper data_dir_env_var_;
+
     /// used in client classification (or just empty container for other tests)
     isc::dhcp::ClientClasses classify_;
-
-private:
-    /// to restore it in destructor.
-    string original_datadir_;
 };
 
 // Checks that there is a configuration structure available and that
 // it is empty by default.
 TEST_F(CfgMgrTest, configuration) {
-
     ConstSrvConfigPtr configuration = CfgMgr::instance().getCurrentCfg();
     ASSERT_TRUE(configuration);
     EXPECT_TRUE(configuration->getLoggingInfo().empty());
@@ -322,62 +334,18 @@ TEST_F(CfgMgrTest, configuration) {
     EXPECT_TRUE(configuration->getLoggingInfo().empty());
 }
 
-// This test checks the data directory handling.
-TEST_F(CfgMgrTest, dataDir) {
-    // It is only in DHCPv6 syntax so switch to IPv6.
-    CfgMgr::instance().setFamily(AF_INET6);
+TEST_F(CfgMgrTest, getDataDir) {
+    // No environment variable or explicit path should
+    // return the default path after construction.
+    ASSERT_FALSE(getenv("KEA_DHCP_DATA_DIR"));
+    ASSERT_EQ(CfgMgr::instance().getDataDir(), std::string(DHCP_DATA_DIR));
 
-    // Default.
-    EXPECT_TRUE(CfgMgr::instance().getDataDir().unspecified());
-    ConstElementPtr json = CfgMgr::instance().getCurrentCfg()->toElement();
-    ASSERT_TRUE(json);
-    ASSERT_EQ(Element::map, json->getType());
-    ConstElementPtr dhcp = json->get("Dhcp6");
-    ASSERT_TRUE(dhcp);
-    ASSERT_EQ(Element::map, dhcp->getType());
-    ConstElementPtr datadir = dhcp->get("data-directory");
-    EXPECT_FALSE(datadir);
-
-    // Set but not specified.
-    CfgMgr::instance().setDataDir("/tmp");
-    EXPECT_TRUE(CfgMgr::instance().getDataDir().unspecified());
-    EXPECT_EQ("/tmp", string(CfgMgr::instance().getDataDir()));
-    json = CfgMgr::instance().getCurrentCfg()->toElement();
-    ASSERT_TRUE(json);
-    ASSERT_EQ(Element::map, json->getType());
-    dhcp = json->get("Dhcp6");
-    ASSERT_TRUE(dhcp);
-    ASSERT_EQ(Element::map, dhcp->getType());
-    datadir = dhcp->get("data-directory");
-    EXPECT_FALSE(datadir);
-
-    // Set and specified.
-    CfgMgr::instance().setDataDir("/tmp", false);
-    EXPECT_FALSE(CfgMgr::instance().getDataDir().unspecified());
-    EXPECT_EQ("/tmp", string(CfgMgr::instance().getDataDir()));
-    json = CfgMgr::instance().getCurrentCfg()->toElement();
-    ASSERT_TRUE(json);
-    ASSERT_EQ(Element::map, json->getType());
-    dhcp = json->get("Dhcp6");
-    ASSERT_TRUE(dhcp);
-    ASSERT_EQ(Element::map, dhcp->getType());
-    datadir = dhcp->get("data-directory");
-    ASSERT_TRUE(datadir);
-    ASSERT_EQ(Element::string, datadir->getType());
-    EXPECT_EQ("/tmp", datadir->stringValue());
-
-    // Still IPv6 only.
-    CfgMgr::instance().setFamily(AF_INET);
-    EXPECT_FALSE(CfgMgr::instance().getDataDir().unspecified());
-    EXPECT_EQ("/tmp", string(CfgMgr::instance().getDataDir()));
-    json = CfgMgr::instance().getCurrentCfg()->toElement();
-    ASSERT_TRUE(json);
-    ASSERT_EQ(Element::map, json->getType());
-    dhcp = json->get("Dhcp4");
-    ASSERT_TRUE(dhcp);
-    ASSERT_EQ(Element::map, dhcp->getType());
-    datadir = dhcp->get("data-directory");
-    EXPECT_FALSE(datadir);
+    setenv("KEA_DHCP_DATA_DIR", "/tmp/envpath", 1);
+    ASSERT_EQ(CfgMgr::instance().getDataDir(true), "/tmp/envpath");
+    ASSERT_EQ(CfgMgr::instance().getDataDir(), "/tmp/envpath");
+
+    ASSERT_EQ(CfgMgr::instance().getDataDir(true, "/tmp/explicit"), "/tmp/explicit");
+    ASSERT_EQ(CfgMgr::instance().getDataDir(), "/tmp/explicit");
 }
 
 // This test checks the D2ClientMgr wrapper methods.
index fcc59b85dcefe26f2f2680517cb731cf37b8def2..a0b7ceaead6563b2f51cb78f582a60547a383761 100644 (file)
@@ -95,7 +95,7 @@ CSVLeaseFile4Test::CSVLeaseFile4Test()
 std::string
 CSVLeaseFile4Test::absolutePath(const std::string& filename) {
     std::ostringstream s;
-    s << DHCP_DATA_DIR << "/" << filename;
+    s << TEST_DATA_BUILDDIR << "/" << filename;
     return (s.str());
 }
 
index 227f960c1b838b4bfc341a08e8e748f301a5f58c..7ecfb8542b5ee3d9f2a01573ed697e75c4743796 100644 (file)
@@ -94,7 +94,7 @@ CSVLeaseFile6Test::CSVLeaseFile6Test()
 std::string
 CSVLeaseFile6Test::absolutePath(const std::string& filename) {
     std::ostringstream s;
-    s << DHCP_DATA_DIR << "/" << filename;
+    s << TEST_DATA_BUILDDIR << "/" << filename;
     return (s.str());
 }
 
index e6067bc35ea1f23c3e48e24a38e5d397d5fc8a46..a151ac2dcba392bac04c09543cd6bae043eb3262 100644 (file)
@@ -324,7 +324,7 @@ LeaseFileLoaderTest::~LeaseFileLoaderTest() {
 std::string
 LeaseFileLoaderTest::absolutePath(const std::string& filename) {
     std::ostringstream s;
-    s << DHCP_DATA_DIR << "/" << filename;
+    s << TEST_DATA_BUILDDIR << "/" << filename;
     return (s.str());
 }
 
index 034f1f55bd262dd1c347337f851c2bcf3af97e2d..8bc79f370c7758ecb1b42e0e1cc936de9658aa82 100644 (file)
@@ -26,6 +26,7 @@
 #include <util/pid_file.h>
 #include <util/range_utilities.h>
 #include <util/stopwatch.h>
+#include <testutils/env_var_wrapper.h>
 
 #include <gtest/gtest.h>
 
@@ -45,6 +46,7 @@ using namespace isc::db;
 using namespace isc::dhcp;
 using namespace isc::dhcp::test;
 using namespace isc::util;
+using namespace isc::test;
 
 namespace {
 
@@ -105,16 +107,19 @@ public:
 /// @brief Test fixture class for @c Memfile_LeaseMgr
 class MemfileLeaseMgrTest : public GenericLeaseMgrTest {
 public:
-
     /// @brief memfile lease mgr test constructor
     ///
     /// Creates memfile and stores it in lmptr_ pointer
     MemfileLeaseMgrTest() :
-        io4_(getLeaseFilePath("leasefile4_0.csv")),
-        io6_(getLeaseFilePath("leasefile6_0.csv")),
         io_service_(getIOService()),
         timer_mgr_(TimerMgr::instance()),
-        extra_files_() {
+        extra_files_(),
+        data_dir_env_var_("KEA_DHCP_DATA_DIR") {
+
+        // Save the pre-test data dir and set it to the test directory.
+        CfgMgr::instance().clear();
+        original_datadir_ = CfgMgr::instance().getDataDir();
+        CfgMgr::instance().getDataDir(true, TEST_DATA_BUILDDIR);
 
         timer_mgr_->setIOService(io_service_);
         DatabaseConnection::setIOService(io_service_);
@@ -167,6 +172,9 @@ public:
         MultiThreadingMgr::instance().setMode(false);
 
         getIOService()->stopAndPoll();
+
+        // Revert to original data directory.
+        CfgMgr::instance().getDataDir(true, original_datadir_);
     }
 
     /// @brief Remove files being products of Lease File Cleanup.
@@ -204,7 +212,7 @@ public:
     /// @return Full path to the lease file.
     static std::string getLeaseFilePath(const std::string& filename) {
         std::ostringstream s;
-        s << TEST_DATA_BUILDDIR << "/" << filename;
+        s << CfgMgr::instance().getDataDir() << "/" << filename;
         return (s.str());
     }
 
@@ -388,12 +396,6 @@ public:
         return (lease);
     }
 
-    /// @brief Object providing access to v4 lease IO.
-    LeaseFileIO io4_;
-
-    /// @brief Object providing access to v6 lease IO.
-    LeaseFileIO io6_;
-
     /// @brief Pointer to the IO service used by the tests.
     IOServicePtr io_service_;
 
@@ -402,6 +404,12 @@ public:
 
     /// @brief List of names of other files to removed.
     vector<string> extra_files_;
+
+    /// @brief RAII wrapper for KEA_DHCP_DATA_DIR env variable.
+    EnvVarWrapper data_dir_env_var_;
+
+    /// @brief Stores the pre-test DHCP data directory.
+    std::string original_datadir_;
 };
 
 /// @brief This test checks if the LeaseMgr can be instantiated and that it
@@ -448,6 +456,68 @@ TEST_F(MemfileLeaseMgrTest, constructor) {
     EXPECT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
 }
 
+/// @brief Verifies that the supported path is the enforced.
+TEST_F(MemfileLeaseMgrTest, defaultDataDir) {
+    ASSERT_TRUE(data_dir_env_var_.getValue().empty());
+    DatabaseConnection::ParameterMap pmap;
+    pmap["universe"] = "6";
+    pmap["persist"] = "true";
+    pmap["lfc-interval"] = "0";
+    pmap["name"] = "leasefile6_1.csv";
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
+
+    ASSERT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
+    EXPECT_EQ(lease_mgr->getLeaseFilePath(Memfile_LeaseMgr::V6),
+              CfgMgr::instance().validatePath("leasefile6_1.csv"));
+
+    pmap["name"] = "/tmp/leasefile6_1.csv";
+    std::ostringstream os;
+    os << "invalid path specified: '/tmp', supported path is '"
+       << CfgMgr::instance().getDataDir() << "'";
+
+    ASSERT_THROW_MSG(lease_mgr.reset(new Memfile_LeaseMgr(pmap)),
+                     BadValue, os.str());
+}
+
+/// @brief Verifies that the supported path may be overridden with
+/// the environment variable KEA_DHCP_DATA_DIR.
+TEST_F(MemfileLeaseMgrTest, dataDirEnvVarOverride) {
+    ASSERT_TRUE(data_dir_env_var_.getValue().empty());
+    data_dir_env_var_.setValue("/tmp");
+    auto valid_path = CfgMgr::instance().getDataDir(true);
+    ASSERT_EQ(valid_path, "/tmp");
+
+    DatabaseConnection::ParameterMap pmap;
+    pmap["universe"] = "6";
+    pmap["persist"] = "true";
+    pmap["lfc-interval"] = "0";
+    pmap["name"] = "leasefile6_1.csv";
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
+
+    ASSERT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
+    EXPECT_EQ(lease_mgr->getLeaseFilePath(Memfile_LeaseMgr::V6),
+              "/tmp/leasefile6_1.csv");
+}
+
+/// @brief Verifies that the supported path may be overridden with
+/// an explicit path even though its really only for UT testing.
+TEST_F(MemfileLeaseMgrTest, dataDirExplicitOveride) {
+    ASSERT_TRUE(data_dir_env_var_.getValue().empty());
+    auto valid_path = CfgMgr::instance().getDataDir(true, "/tmp");
+    ASSERT_EQ(valid_path, "/tmp");
+
+    DatabaseConnection::ParameterMap pmap;
+    pmap["universe"] = "6";
+    pmap["persist"] = "true";
+    pmap["lfc-interval"] = "0";
+    pmap["name"] = "leasefile6_1.csv";
+    boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr;
+
+    ASSERT_NO_THROW(lease_mgr.reset(new Memfile_LeaseMgr(pmap)));
+    EXPECT_EQ(lease_mgr->getLeaseFilePath(Memfile_LeaseMgr::V6),
+              "/tmp/leasefile6_1.csv");
+}
+
 /// @brief Checks if there is no lease manager NoLeaseManager is thrown.
 TEST_F(MemfileLeaseMgrTest, noLeaseManager) {
     LeaseMgrFactory::destroy();
index 2a65ce45e942b9ac48e10286e064c4ba89407340..9ad63dd1c5954fd2cadb1b49369395a450114ecf 100644 (file)
@@ -23,20 +23,31 @@ using namespace isc::util::file;
 namespace isc {
 namespace hooks {
 
+namespace {
+    // Singleton PathChecker to set and hold valid hooks library path.
+    PathCheckerPtr hooks_path_checker_;
+};
+
 std::string
 HooksLibrariesParser::getHooksPath(bool reset /* = false */, const std::string explicit_path /* = "" */) {
-    static std::string default_hooks_path = "";
-    if (default_hooks_path.empty() || reset) {
-        if (explicit_path.empty()) {
-            default_hooks_path = std::string(std::getenv("KEA_HOOKS_PATH") ?
-                                             std::getenv("KEA_HOOKS_PATH")
-                                             : DEFAULT_HOOKS_PATH);
-        } else {
-            default_hooks_path = explicit_path;
+    if (!hooks_path_checker_ || reset) {
+        hooks_path_checker_.reset(new PathChecker(DEFAULT_HOOKS_PATH, "KEA_HOOKS_PATH"));
+        if (!explicit_path.empty()) {
+            hooks_path_checker_->getPath(true, explicit_path);
         }
     }
 
-    return (default_hooks_path);
+    return (hooks_path_checker_->getPath());
+}
+
+std::string
+HooksLibrariesParser::validatePath(const std::string libpath,
+                                   bool enforce_path /* = true */) {
+    if (!hooks_path_checker_) {
+        getHooksPath();
+    }
+
+    return (hooks_path_checker_->validatePath(libpath, enforce_path));
 }
 
 // @todo use the flat style, split into list and item
@@ -118,12 +129,5 @@ HooksLibrariesParser::parse(HooksConfig& libraries, ConstElementPtr value) {
     }
 }
 
-std::string
-HooksLibrariesParser::validatePath(const std::string libpath,
-                                   bool enforce_path /* = true */) {
-    return (FileManager::validatePath(HooksLibrariesParser::getHooksPath(),
-                                      libpath, enforce_path));
-}
-
 }
 }
index 6ea0173bf2b1947a547ec9d4bb5562b669e8fd28..bc997d119a27e245dd4f30a33d8bad1b067925fa 100644 (file)
@@ -10,6 +10,7 @@
 #include <cc/data.h>
 #include <cc/simple_parser.h>
 #include <hooks/hooks_config.h>
+#include <util/filesystem.h>
 
 namespace isc {
 namespace hooks {
index b391b854155467555a5a6d8126308a7f40eb4091..21e9e37120f688bee739b8609aa95c770899a73e 100644 (file)
@@ -1166,6 +1166,14 @@ TEST_F(HooksParserTest, validatePathEnforcePath) {
         def_path + "/mylib.so",
         def_path + "/mylib.so",
         ""
+    },
+    {
+        // Invalid relative path.
+        __LINE__,
+        "../kea/mylib.so",
+        "",
+        string("invalid path specified: '../kea', supported path is '" +
+               def_path + "'")
     }
     };
 
index 30332da54810bd7c83ec99291ba48c83605d7f9b..266fa86a8c4bf256fd1f2db5562cd6522247e484 100644 (file)
@@ -16,9 +16,13 @@ libkea_testutils_la_SOURCES += unix_control_client.cc unix_control_client.h
 libkea_testutils_la_SOURCES += user_context_utils.cc user_context_utils.h
 libkea_testutils_la_SOURCES += gtest_utils.h
 libkea_testutils_la_SOURCES += multi_threading_utils.h
+libkea_testutils_la_SOURCES += env_var_wrapper.cc env_var_wrapper.h
 libkea_testutils_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+libkea_testutils_la_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+
 libkea_testutils_la_LIBADD  = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
 libkea_testutils_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
+libkea_testutils_la_LIBADD += $(GTEST_LDADD)
 endif
 
 # Include common libraries being used by shell-based tests.
diff --git a/src/lib/testutils/env_var_wrapper.cc b/src/lib/testutils/env_var_wrapper.cc
new file mode 100644 (file)
index 0000000..4b3b3dd
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <testutils/env_var_wrapper.h>
+
+namespace isc {
+namespace test {
+
+EnvVarWrapper::EnvVarWrapper(const std::string& name) : name_(name) {
+    original_value_ = getValue();
+}
+
+EnvVarWrapper::~EnvVarWrapper() {
+    setValue(original_value_);
+}
+
+std::string
+EnvVarWrapper::getOriginalValue() const {
+    return (original_value_);
+}
+
+std::string
+EnvVarWrapper::getValue() const {
+    auto value = getenv(name_.c_str());
+    return (value ? std::string(value) : std::string(""));
+}
+
+void
+EnvVarWrapper::setValue(const std::string value /* = "" */) {
+    if (value.empty()) {
+        unsetenv(name_.c_str());
+    } else {
+        setenv(name_.c_str(), value.c_str(), 1);
+    }
+}
+
+}  // end of isc::test namespace
+}  // end of isc namespace
diff --git a/src/lib/testutils/env_var_wrapper.h b/src/lib/testutils/env_var_wrapper.h
new file mode 100644 (file)
index 0000000..e1d284f
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2025 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef ENV_VAR_WRAPPER_H
+#define ENV_VAR_WRAPPER_H
+
+#include <string>
+
+namespace isc {
+namespace test {
+
+/// @brief Wrapper for environment variable that restores the
+/// variable to its original value.
+class EnvVarWrapper {
+public:
+    /// @brief Constructor
+    ///
+    /// Fetchs and retains the variable's current value as
+    /// the "original" value.
+    EnvVarWrapper(const std::string& name);
+
+    /// @brief Destructor.
+    ///
+    /// Restores the original value (if one), otherwise it
+    /// unsets it.
+    ~EnvVarWrapper();
+
+    /// @brief Fetches the original value of the env variable.
+    std::string getOriginalValue() const;
+
+    /// @brief Fetches the current value of the env variable.
+    std::string getValue() const;
+
+    /// @brief Sets the current value of the env variable.
+    ///
+    /// @param value new value of the variable. If empty the
+    /// variable is unset.
+    void setValue(const std::string value = "");
+
+private:
+    /// @brief Name of the variable.
+    std::string name_;
+
+    /// @brief Value of the env variable at the time the wrapper
+    /// was constructed.
+    std::string original_value_;
+};
+
+}  // end of isc::test namespace
+}  // end of isc namespace
+
+#endif // ENV_VAR_WRAPPER_H
index f807db18e1e491de5a22a5443e4e40c8657441e5..d8e1cffd1871b4d5833aa0668b34d60a94bb1d38 100644 (file)
@@ -212,16 +212,38 @@ string TemporaryDirectory::dirName() {
     return dir_name_;
 }
 
+PathChecker::PathChecker(const std::string default_path,
+                             const std::string env_name /* = "" */)
+    : default_path_(default_path), env_name_(env_name) {
+    getPath(true);
+}
+
 std::string
-FileManager::validatePath(const std::string supported_path_str, const std::string input_path_str,
-                          bool enforce_path /* = true */) {
-    // Remove the trailing "/" if it present so comparison to
-    // input's parent path functions.
-    auto supported_path_copy(supported_path_str);
-    if (supported_path_copy.back() == '/') {
-        supported_path_copy.pop_back();
+PathChecker::getPath(bool reset /* = false */,
+                     const std::string explicit_path /* = "" */) {
+    if (reset) {
+        if (!explicit_path.empty()) {
+            path_ = explicit_path;
+        } else if (!env_name_.empty()) {
+            path_ = std::string(std::getenv(env_name_.c_str()) ?
+                                std::getenv(env_name_.c_str()) : default_path_);
+        } else {
+            path_ = default_path_;
+        }
+
+        // Remove the trailing "/" if it is present so comparison to
+        // other Path::parentPath() works.
+        while (!path_.empty() && path_.back() == '/') {
+            path_.pop_back();
+        }
     }
 
+    return (path_);
+}
+
+std::string
+PathChecker::validatePath(const std::string input_path_str,
+                          bool enforce_path /* = true */) const {
     Path input_path(trim(input_path_str));
     auto filename = input_path.filename();
     if (filename.empty()) {
@@ -230,20 +252,21 @@ FileManager::validatePath(const std::string supported_path_str, const std::strin
 
     auto parent_path = input_path.parentPath();
     if (!parent_path.empty()) {
-         if (!enforce_path) {
-             // Security set to lax, let it fly.
-             return (input_path_str);
-         }
-
-         // We only allow absolute path equal to default. Catch an invalid path.
-        if (parent_path != supported_path_copy) {
-             isc_throw(BadValue, "invalid path specified: '"
+        if (!enforce_path) {
+            // Security set to lax, let it fly.
+            return (input_path_str);
+        }
+
+
+        // We only allow absolute path equal to default. Catch an invalid path.
+        if (parent_path != path_) {
+            isc_throw(BadValue, "invalid path specified: '"
                       << parent_path << "', supported path is '"
-                      << supported_path_copy << "'");
-         }
-     }
+                      << path_ << "'");
+        }
+    }
 
-    std::string valid_path(supported_path_copy + "/" +  filename);
+    std::string valid_path(path_ + "/" +  filename);
     return (valid_path);
 }
 
index 34e7aad24b5605e10f2b4c59897bc6cdbf1fcf7d..eaf2701b08b5fa0dbf92d0559bc67b2724b05b3e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <sys/stat.h>
 #include <string>
+#include <boost/shared_ptr.hpp>
 
 namespace isc {
 namespace util {
@@ -138,9 +139,39 @@ private:
     std::string dir_name_;
 };
 
-/// @brief Class that provides basic file related tasks.
-class FileManager {
+/// @brief Embodies a supported path against which file paths can be validated.
+class PathChecker {
 public:
+    /// @brief Constructor.
+    ///
+    /// Makes a call to getPath(true) to initialize the supported path.
+    ///
+    /// @param default_path path to use unless overridden by explicitly or via
+    /// environment variable.
+    /// @param env_name name of environment variable (if one), that can override
+    /// the default path.
+    PathChecker(const std::string default_path, const std::string env_name = "");
+
+    /// @brief Destructor.
+    virtual ~PathChecker() {};
+
+    /// @brief Fetches the supported path.
+    ///
+    /// When called with reset=true it will calculate the supported path as
+    /// follows:
+    ///
+    /// 1. Use the value of explicit_path parameter if not blank
+    /// 2. Use the value of the environment variable, if one is provided and it
+    /// is defined in the environment
+    /// 3. Use the value of default path.
+    ///
+    /// @param reset recalculate when true, defaults to false.
+    /// @param explicit_path set the default path to this value. This is
+    /// for testing purposes only.
+    ///
+    /// @return String containing the default path.
+    std::string getPath(bool reset = false, const std::string explicit_path = "");
+
     /// @brief Validates a file path against a supported path.
     ///
     /// If the input path specifies a parent path and file name, the parent path
@@ -148,8 +179,6 @@ public:
     /// the validated path. If the input path contains only a file name the function
     /// returns valid path using the supported path and the input path name.
     ///
-    /// @param supported_path_str absolute path specifying the  supported path
-    /// of the file against which the input path is validated.
     /// @param input_path_str file path to validate.
     /// @param enforce_path enables validation against the supported path.  If false
     /// verifies only that the path contains a file name.
@@ -158,11 +187,33 @@ public:
     ///
     /// @throw BadValue if the input path does not include a file name or if the
     /// it the parent path does not path the supported path.
-    static std::string validatePath(const std::string supported_path_str,
-                                    const std::string input_path_str,
-                                    bool enforce_path = true);
+    std::string validatePath(const std::string input_path_str,
+                             bool enforce_path = true) const;
+
+    /// @brief Fetches the default path.
+    std::string getDefaultPath() const {
+        return (default_path_);
+    }
+
+    /// @brief Fetches the environment variable name.
+    std::string getEnvName() const {
+        return (env_name_);
+    }
+
+private:
+    /// @brief Default supported path.
+    std::string default_path_;
+
+    /// @brief Name of environment variable (if one) that can override the default.
+    std::string env_name_;
+
+    /// @brief The supported path currently in effect.
+    std::string path_;
 };
 
+/// @brief Defines a pointer to a PathChecker.
+typedef boost::shared_ptr<PathChecker> PathCheckerPtr;
+
 }  // namespace file
 }  // namespace util
 }  // namespace isc
index bd309ca19525e7bae111402d008e9b3afe9a8d4a..b246f5bdb3e24066b3481eb6a5cd4612f87ee6b2 100644 (file)
@@ -158,10 +158,79 @@ TEST(PathTest, replaceParentPath) {
     EXPECT_EQ("/just/some/dir/a.b", fname.str());
 }
 
+/// @brief Test fixture for testing PathChecker.
+class PathCheckerTest : public ::testing::Test {
+public:
+    /// @brief Constructor
+    PathCheckerTest() {
+        env_name_ = "KEA_PATCHECKER_TEST_PATH";
+        // Save current value of the environment path.
+        char* env_path = std::getenv(env_name_.c_str());
+        if (env_path) {
+            original_path_ = std::string(env_name_.c_str());
+        }
+
+        // Clear the environment path.
+        unsetenv(env_name_.c_str());
+    }
+
+    /// @brief Destructor
+    ~PathCheckerTest() {
+        // Restore the original environment path.
+        if (!original_path_.empty()) {
+            setenv(env_name_.c_str(), original_path_.c_str(), 1);
+        } else {
+            unsetenv(env_name_.c_str());
+        }
+    }
+
+    /// @brief Name of env variable for overriding default path.
+    std::string env_name_;
+
+    /// @brief Retains the environment variable's original value.
+    std::string original_path_;
+
+};
+
+TEST_F(PathCheckerTest, getPathDefault) {
+    // No environment variable or explicit path should
+    // return the default path after construction.
+    ASSERT_FALSE(std::getenv(env_name_.c_str()));
+    PathChecker checker("/tmp/def_path", env_name_.c_str());
+    ASSERT_EQ(checker.getPath(), checker.getDefaultPath());
 
+    // A subsequent call with reset=true should do the same.
+    EXPECT_EQ(checker.getPath(true), checker.getDefaultPath());
+}
+
+TEST_F(PathCheckerTest, getPathEnvVariable) {
+    // Override default with an env variable upon construction.
+    setenv(env_name_.c_str(), "/tmp/override", 1);
+    ASSERT_TRUE(std::getenv(env_name_.c_str()));
+    PathChecker checker("/tmp/def_path", env_name_.c_str());
+    ASSERT_EQ(checker.getPath(), "/tmp/override");
+
+    // A subsequent call with reset=true should do the same.
+    EXPECT_EQ(checker.getPath(true), "/tmp/override");
+}
+
+TEST_F(PathCheckerTest, getPathExplicit) {
+    // Default construction with no env variable.
+    ASSERT_FALSE(std::getenv(env_name_.c_str()));
+    PathChecker checker("/tmp/def_path", env_name_.c_str());
+    ASSERT_EQ(checker.getPath(), checker.getDefaultPath());
+
+    // A subsequent call with reset=true and an explicit path
+    // should return the explicit path.
+    ASSERT_EQ(checker.getPath(true, "/tmp/explicit"),
+              "/tmp/explicit");
 
-// Verifies FileManager::validatePath() when enforce_path is true.
-TEST(FileManager, validatePathEnforcePath) {
+    // A subsequent call with no arguments should do the same.
+    EXPECT_EQ(checker.getPath(), "/tmp/explicit");
+}
+
+// Verifies PathChecker::validatePath() when enforce_path is true.
+TEST(PathChecker, validatePathEnforcePath) {
     std::string def_path(TEST_DATA_BUILDDIR);
     struct Scenario {
         int line_;
@@ -205,9 +274,19 @@ TEST(FileManager, validatePathEnforcePath) {
         "      ",
         "",
         string("path: '' has no filename")
+    },
+    {
+        // Invalid relative path.
+        __LINE__,
+        "../kea/mylib.so",
+        "",
+        string("invalid path specified: '../kea', supported path is '" +
+               def_path + "'")
     }
     };
 
+    // Create a PathChecker with a supported path of def_path.
+    PathChecker checker(def_path);
     for (auto scenario : scenarios) {
         std::ostringstream oss;
         oss << " Scenario at line: " << scenario.line_;
@@ -215,18 +294,18 @@ TEST(FileManager, validatePathEnforcePath) {
         std::string validated_path;
         if (scenario.exp_error_.empty()) {
             ASSERT_NO_THROW_LOG(validated_path =
-                                FileManager::validatePath(def_path, scenario.lib_path_));
+                                checker.validatePath(scenario.lib_path_));
             EXPECT_EQ(validated_path, scenario.exp_path_);
         } else {
             ASSERT_THROW_MSG(validated_path =
-                             FileManager::validatePath(def_path, scenario.lib_path_),
+                             checker.validatePath(scenario.lib_path_),
                              BadValue, scenario.exp_error_);
         }
     }
 }
 
-// Verifies FileManager::validatePath() when enforce_path is false.
-TEST(FileManager, validatePathEnforcePathFalse) {
+// Verifies PathChecker::validatePath() when enforce_path is false.
+TEST(PathChecker, validatePathEnforcePathFalse) {
     std::string def_path(TEST_DATA_BUILDDIR);
     struct Scenario {
         int line_;
@@ -273,6 +352,8 @@ TEST(FileManager, validatePathEnforcePathFalse) {
     }
     };
 
+    // Create a PathChecker with a supported path of def_path.
+    PathChecker checker(def_path);
     for (auto scenario : scenarios) {
         std::ostringstream oss;
         oss << " Scenario at line: " << scenario.line_;
@@ -280,11 +361,11 @@ TEST(FileManager, validatePathEnforcePathFalse) {
         std::string validated_path;
         if (scenario.exp_error_.empty()) {
             ASSERT_NO_THROW_LOG(validated_path =
-                                FileManager::validatePath(def_path, scenario.lib_path_, false));
+                                checker.validatePath(scenario.lib_path_, false));
             EXPECT_EQ(validated_path, scenario.exp_path_);
         } else {
             ASSERT_THROW_MSG(validated_path =
-                             FileManager::validatePath(def_path, scenario.lib_path_, false),
+                             checker.validatePath(scenario.lib_path_, false),
                              BadValue, scenario.exp_error_);
         }
     }