]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[master] Merge branch 'trac3464' (pool definitions are now structures)
authorTomek Mrugalski <tomasz@isc.org>
Fri, 8 Aug 2014 17:13:38 +0000 (19:13 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Fri, 8 Aug 2014 17:13:38 +0000 (19:13 +0200)
Conflicts:
ChangeLog
doc/examples/kea4/several-subnets.json
doc/examples/kea4/single-subnet.json
doc/examples/kea6/several-subnets.json
doc/guide/dhcp4-srv.xml

16 files changed:
1  2 
ChangeLog
doc/examples/kea4/several-subnets.json
doc/examples/kea4/single-subnet.json
doc/examples/kea6/several-subnets.json
doc/guide/dhcp4-srv.xml
doc/guide/dhcp6-srv.xml
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp4/tests/dhcp4_process_tests.sh.in
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dora_unittest.cc
src/bin/dhcp4/tests/inform_unittest.cc
src/bin/dhcp4/tests/kea_controller_unittest.cc
src/bin/dhcp6/tests/confirm_unittest.cc
src/bin/dhcp6/tests/dhcp6_process_tests.sh.in
src/bin/dhcp6/tests/rebind_unittest.cc
src/bin/keactrl/tests/keactrl_tests.sh.in

diff --cc ChangeLog
index 11b02f05d8a76b0a6894b7e90c4069ae9a8441e1,149e028a22a814ac3bcbe8d23ed03f9cf30f0ba5..178d9b295cc83e541fcc963a40bebd769e720c96
+++ b/ChangeLog
@@@ -1,53 -1,8 +1,59 @@@
 -8xx.  [func]          tomek
++815.  [func]          tomek
+       Pool definitions in DHCPv4 and DHCPv6 are now lists of
+       structures. This makes adding new per-pool parameters easier in
+       the future.
 -      (Trac #3464, git tbd)
++      (Trac #3464, git 4bd0c0eda9d86608f8802d28bd360239fe88e905)
++
 +814.  [func,doc]      tomek
 +      It is now possible to specify logging parameters in a
 +      configuration file for DHCPv4, DHCPv6 and DHCP-DDNS components.
 +      (Trac #3427, git 23285903645c36fc35c6866a74c50c74089cd255)
 +
 +813.  [func]          tomek
 +      Functions, methods and variables referring to BIND10 were renamed
 +      to Kea. In particular, system variables (B10_LOGGER_ROOT,
 +      B10_LOCKFILE_DIR_FROM_BUILD etc.) were renamed. B10_ prefix was
 +      replaced with KEA_.
 +      (Trac #3417, git 1db8988de6af435fa388dc9c7f909c4a004a01d0)
 +
 +812.  [doc]           tomek
 +      DHCPv6 and DDNS sections in Kea Administrator Reference Manual
 +      has been updated. Usage of keactl has been documented.
 +      (Trac #3468, git 3945fc6211bcadb9bece7147039a6b50ebcf936b)
 +      (Trac #3466, git fa9570d19c73cbe7effc75589b7eb855c411f6a3)
 +
 +811.  [doc]           tmark
 +      Added documentation of message protocol between DHCP servers and the
 +      DHCP-DDNS process.
 +      (Trac #3505, git 6d9aed2f8fe181714e8260493c6cc06e13d0edd0)
 +
 +810.  [func]          stephen
 +      perfdhcp is now installed in sbin as it requires root privilege to run.
 +      The perfdhcp source has been moved to the directory src/bin/perfdhcp.
 +      (Trac #3481, git d101aed6156a993476fa1164f0b0ec8395f5886c)
 +
 +809.  [func]          stephen
 +      sockcreator is no longer built or installed.  The code is being retained
 +      in the repository for the moment, but may be deleted at some point in the
 +      future.
 +      (Trac #3480, git 2a55a469dde8fcc053b49e287c30d0906baa91b4)
 +
 +808.  [func]          stephen
 +      Reduced number of startup and shutdown messages in the
 +      DHCP-DDNS process by making some of them debug messages.
 +      (Trac #3479, git bca0bae285de9ce904c0afd21af777dac2edb4e6)
 +
 +807.  [func]          marcin
 +      DHCPv6 server responds to Confirm messages from clients.
 +      (Trac #3269, git 4f43c309a994e30c07f5aa27057552fb195ec284)
 +
 +806.  [func]          marcin
 +      DHCPv4 server processes Requested IP Address option (50).
 +      (Trac #3320, git ad411a177a32bbe6a93f4baf813d985558c99e2f)
 +
 +805.  [func]          stephen
 +      Changed all occurrences of "BIND 10" in message files to "Kea".
 +      (Trac #3416, git e88090b57a75424920d9b96efbf50e3554048828)
  
  804.  [func]          marcin
        DHCPv4 server supports DHCPINFORM messages from the clients.
index ce8cb984ebd46a2eb35f903ff092f03807919c65,62dc42ea6556e5bbc926b41bf92eca4ace55178b..aff824b64027196edf46c9dfa5884173cd25f784
  
  # The following list defines subnets. Each subnet consists of at
  # least subnet and pool entries.
-   "subnet4": [
-   {    "pool": [ "192.0.2.1 - 192.0.2.200" ],
+   "subnet4": [ 
+   {    "pools": [ { "pool":  "192.0.2.1 - 192.0.2.200" } ],
         "subnet": "192.0.2.0/24"  },
-   {    "pool": [ "192.0.3.100 - 192.0.3.200" ],
+   {    "pools": [ { "pool": "192.0.3.100 - 192.0.3.200" } ],
         "subnet": "192.0.3.0/24"  },
-   {    "pool": [ "192.0.4.1 - 192.0.4.254" ],
+   {    "pools": [ { "pool": "192.0.4.1 - 192.0.4.254" } ],
         "subnet": "192.0.4.0/24"  } ]
 +},
 +
 +# The following configures logging. Kea will log all debug messages
 +# to /var/log/kea-debug.log file.
 +"Logging": {
 +    "loggers": [
 +        {
 +            "name": "kea-dhcp4",
 +            "output_options": [
 +                {
 +                    "output": "/var/log/kea-debug.log"
 +                }
 +            ],
 +            "debuglevel": 99,
 +            "severity": "DEBUG"
 +        }
 +    ]
  }
  
  }
index 6bb92ba27a994d00d950f5d0eec804113c90e66d,a7b7024c9571a758da9113424140f1b158f425f9..0c2e10ca07c720b5c41487f50ab46b432e06c8b6
  #  "rebind-timer": 2000,
  
  # The following list defines subnets. We have only one subnet
 -# here.
 +# here. We tell Kea that it is directly available over local interface.
    "subnet4": [
-   {    "pool": [ "192.0.2.1 - 192.0.2.200" ],
+     {
 -      "pools": [ { "pool":  "192.0.2.1 - 192.0.2.200" } ],
 -      "subnet": "192.0.2.0/24"
 -    }
++       "pools": [ { "pool":  "192.0.2.1 - 192.0.2.200" } ],
 +       "subnet": "192.0.2.0/24",
-        "interface": "eth0"  } ]
++       "interface": "eth0"
++    } 
+   ]
 +},
 +
 +# The following configures logging. It assumes that messages with at least
 +# informational level (info, warn, error) will will be logged to stdout.
 +"Logging": {
 +    "loggers": [
 +        {
 +            "name": "kea-dhcp4",
 +            "output_options": [
 +                {
 +                    "output": "stdout"
 +                }
 +            ],
 +            "severity": "INFO"
 +        }
 +    ]
  }
  
  }
index 420596da9f91e7644b6c003b5b687356345f0edf,2cf012feba69b63f9733fba77534fc79a73de474..f138c059eaa3713be0e56b15d86f4a733f6930b1
  
  # The following list defines subnets. Each subnet consists of at
  # least subnet and pool entries.
-   "subnet6": [
-   {    "pool": [ "2001:db8:1::/80" ],
+   "subnet6": [ 
+   {    "pools": [ { "pool": "2001:db8:1::/80" } ],
         "subnet": "2001:db8:1::/64"  },
-   {    "pool": [ "2001:db8:2::/80" ],
-        "subnet": "2001:db8:2::/64"  },
-   {    "pool": [ "2001:db8:3::/80" ],
+   {    "pools": [ { "pool": "2001:db8:2::/80" } ],
+        "subnet": "2001:db8:2::/64"  }, 
+   {    "pools": [ { "pool": "2001:db8:3::/80" } ],
         "subnet": "2001:db8:3::/64"  },
-   {    "pool": [ "2001:db8:4::/80" ],
+   {    "pools": [ { "pool": "2001:db8:4::/80" } ],
         "subnet": "2001:db8:4::/64"  } ]
 -}
 +},
  
 +# The following configures logging. It assumes that warning messages
 +# will be logged to stdout.
 +"Logging": {
 +    "loggers": [
 +        {
 +            "name": "kea-dhcp6",
 +            "output_options": [
 +                {
 +                    "output": "stdout"
 +                }
 +            ],
 +            "severity": "WARN"
 +        }
 +    ]
  }
  
 +}
Simple merge
index 630afdaddf779ac693434cc97ccbbdc4d91210e7,7f3acd3d97bfde494b397f50b216b21393fe927d..bd4443c7f74a63b89dab4577cdf6394ac3a65249
@@@ -456,6 -351,6 +456,13 @@@ temporarily override a list of interfac
          is actually a list of pools: for this reason, the pool definition is
          enclosed in square brackets, even though only one range of addresses
          is specified.</para>
++
++        <para>Each <command>pool</command> is a structure that contains the
++        parameters th describe a single pool. Currently there is only one
++        parameter, <command>pool</command>, which gives the range of addresses
++        in the pool. Additional parameters will be added in future releases of
++        Kea.</para>
++
          <para>It is possible to define more than one pool in a
          subnet: continuing the previous example, further assume that
          2001:db8:1:0:5::/80 should be also be managed by the server. It could be written as
index 81704554cb59778ff2ae963fd57a5dc33cecb5b7,afbd8b2ff804f37e7adf031199ff16f0d9e77a96..40967bf7ff9f2ceccaf58cdf304bbf30f76eb41a
@@@ -32,23 -32,8 +32,23 @@@ CONFIG="
          \"subnet4\": [
          {
              \"subnet\": \"10.0.0.0/8\",
-             \"pool\": [ \"10.0.0.10-10.0.0.100\" ]
+             \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
          } ]
 +    },
 +
 +    \"Logging\":
 +    {
 +        \"loggers\": [
 +        {
 +            \"name\": \"kea-dhcp4\",
 +            \"output_options\": [
 +                {
 +                    \"output\": \"$LOG_FILE\"
 +                }
 +            ],
 +            \"severity\": \"INFO\"
 +        }
 +        ]
      }
  }"
  # Invalid configuration (negative valid-lifetime) to check that Kea
@@@ -68,23 -53,8 +68,23 @@@ CONFIG_INVALID="
          \"subnet4\": [
          {
              \"subnet\": \"10.0.0.0/8\",
-             \"pool\": [ \"10.0.0.10-10.0.0.100\" ]
+             \"pool\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
          } ]
 +    },
 +
 +    \"Logging\":
 +    {
 +        \"loggers\": [
 +        {
 +            \"name\": \"kea-dhcp4\",
 +            \"output_options\": [
 +                {
 +                    \"output\": \"$LOG_FILE\"
 +                }
 +            ],
 +            \"severity\": \"INFO\"
 +        }
 +        ]
      }
  }"
  
index 07e785545af39919e82e624b88db1be3449c2b63,0000000000000000000000000000000000000000..8b44619ee41ff1f8787a5c0fa0003c2c74f7dce0
mode 100644,000000..100644
--- /dev/null
@@@ -1,352 -1,0 +1,352 @@@
-         "    \"pool\": [ \"10.0.0.10-10.0.0.100\" ],"
 +// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
 +//
 +// Permission to use, copy, modify, and/or distribute this software for any
 +// purpose with or without fee is hereby granted, provided that the above
 +// copyright notice and this permission notice appear in all copies.
 +//
 +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 +// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 +// PERFORMANCE OF THIS SOFTWARE.
 +
 +#include <config.h>
 +#include <asiolink/io_address.h>
 +#include <cc/data.h>
 +#include <dhcp/dhcp4.h>
 +#include <dhcp/tests/iface_mgr_test_config.h>
 +#include <dhcp4/tests/dhcp4_test_utils.h>
 +#include <dhcp4/tests/dhcp4_client.h>
 +#include <boost/shared_ptr.hpp>
 +
 +using namespace isc;
 +using namespace isc::asiolink;
 +using namespace isc::data;
 +using namespace isc::dhcp;
 +using namespace isc::dhcp::test;
 +
 +namespace {
 +
 +/// @brief Set of JSON configurations used throughout the DORA tests.
 +///
 +/// - Configuration 0:
 +///   - Used for testing direct traffic
 +///   - 1 subnet: 10.0.0.0/24
 +///   - 1 pool: 10.0.0.10-10.0.0.100
 +///   - Router option present: 10.0.0.200 and 10.0.0.201
 +///   - Domain Name Server option present: 10.0.0.202, 10.0.0.203.
 +///   - Log Servers option present: 192.0.2.200 and 192.0.2.201
 +///   - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
 +///
 +/// - Configuration 1:
 +///   - Use for testing relayed messages
 +///   - 1 subnet: 192.0.2.0/24
 +///   - Router option present: 192.0.2.200 and 192.0.2.201
 +///   - Domain Name Server option present: 192.0.2.202, 192.0.2.203.
 +///   - Log Servers option present: 192.0.2.200 and 192.0.2.201
 +///   - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
 +const char* DORA_CONFIGS[] = {
 +// Configuration 0
 +    "{ \"interfaces\": [ \"all\" ],"
 +        "\"valid-lifetime\": 600,"
 +        "\"subnet4\": [ { "
 +        "    \"subnet\": \"10.0.0.0/24\", "
++        "    \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
 +        "    \"option-data\": [ {"
 +        "        \"name\": \"routers\","
 +        "        \"code\": 3,"
 +        "        \"data\": \"10.0.0.200,10.0.0.201\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    },"
 +        "    {"
 +        "        \"name\": \"domain-name-servers\","
 +        "        \"code\": 6,"
 +        "        \"data\": \"10.0.0.202,10.0.0.203\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    },"
 +        "    {"
 +        "        \"name\": \"log-servers\","
 +        "        \"code\": 7,"
 +        "        \"data\": \"10.0.0.200,10.0.0.201\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    },"
 +        "    {"
 +        "        \"name\": \"cookie-servers\","
 +        "        \"code\": 8,"
 +        "        \"data\": \"10.0.0.202,10.0.0.203\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    } ]"
 +        " } ]"
 +    "}",
 +
 +// Configuration 1
 +    "{ \"interfaces\": [ \"all\" ],"
 +        "\"valid-lifetime\": 600,"
 +        "\"subnet4\": [ { "
 +        "    \"subnet\": \"192.0.2.0/24\", "
 +        "    \"option-data\": [ {"
 +        "        \"name\": \"routers\","
 +        "        \"code\": 3,"
 +        "        \"data\": \"192.0.2.200,192.0.2.201\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    },"
 +        "    {"
 +        "        \"name\": \"domain-name-servers\","
 +        "        \"code\": 6,"
 +        "        \"data\": \"192.0.2.202,192.0.2.203\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    },"
 +        "    {"
 +        "        \"name\": \"log-servers\","
 +        "        \"code\": 7,"
 +        "        \"data\": \"10.0.0.200,10.0.0.201\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    },"
 +        "    {"
 +        "        \"name\": \"cookie-servers\","
 +        "        \"code\": 8,"
 +        "        \"data\": \"10.0.0.202,10.0.0.203\","
 +        "        \"csv-format\": true,"
 +        "        \"space\": \"dhcp4\""
 +        "    } ]"
 +        " } ]"
 +    "}"
 +};
 +
 +/// @brief Test fixture class for testing 4-way (DORA) exchanges.
 +///
 +/// @todo Currently there is a limit number of test cases covered here.
 +/// In the future it is planned that the tests from the
 +/// dhcp4_srv_unittest.cc will be migrated here and will use the
 +/// @c Dhcp4Client class.
 +class DORATest : public Dhcpv4SrvTest {
 +public:
 +
 +    /// @brief Constructor.
 +    ///
 +    /// Sets up fake interfaces.
 +    DORATest()
 +        : Dhcpv4SrvTest(),
 +          iface_mgr_test_config_(true) {
 +        IfaceMgr::instance().openSockets4();
 +    }
 +
 +    /// @brief Interface Manager's fake configuration control.
 +    IfaceMgrTestConfig iface_mgr_test_config_;
 +
 +};
 +
 +/// This test verifies that the client in the SELECTING state can get
 +/// an address when it doesn't request any specific address in the
 +/// DHCPDISCOVER message.
 +TEST_F(DORATest, selectingDoNotRequestAddress) {
 +    Dhcp4Client client(Dhcp4Client::SELECTING);
 +    // Configure DHCP server.
 +    configure(DORA_CONFIGS[0], *client.getServer());
 +
 +    // Perform 4-way exchange with the server but to not request any
 +    // specific address in the DHCPDISCOVER message.
 +    ASSERT_NO_THROW(client.doDORA());
 +
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    Pkt4Ptr resp = client.getContext().response_;
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got the lease with the requested address.
 +    ASSERT_NE(client.config_.lease_.addr_.toText(), "0.0.0.0");
 +}
 +
 +/// This test verifies that multiple clients may use the DHCPv4 server
 +/// and obtain unique leases.
 +TEST_F(DORATest, selectingMultipleClients) {
 +    Dhcp4Client client(Dhcp4Client::SELECTING);
 +    // Configure DHCP server.
 +    configure(DORA_CONFIGS[0], *client.getServer());
 +
 +    // Get the first lease.
 +    ASSERT_NO_THROW(client.doDORA());
 +
 +    // Make sure that the server responded.
 +    Pkt4Ptr resp = client.getContext().response_;
 +    ASSERT_TRUE(resp);
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Store the lease.
 +    Lease4 lease1 = client.config_.lease_;
 +
 +    // Get the lease for a different client.
 +    client.modifyHWAddr();
 +    ASSERT_NO_THROW(client.doDORA());
 +    // Make sure that the server responded.
 +    resp = client.getContext().response_;
 +    ASSERT_TRUE(resp);
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Store the lease.
 +    Lease4 lease2 = client.config_.lease_;
 +
 +    // Get the lease for a different client.
 +    client.modifyHWAddr();
 +    ASSERT_NO_THROW(client.doDORA());
 +    // Make sure that the server responded.
 +    resp = client.getContext().response_;
 +    ASSERT_TRUE(resp);
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Store the lease.
 +    Lease4 lease3 = client.config_.lease_;
 +
 +    // Make sure that unique addresses have been assigned.
 +    EXPECT_NE(lease1.addr_, lease2.addr_);
 +    EXPECT_NE(lease2.addr_, lease3.addr_);
 +    EXPECT_NE(lease1.addr_, lease3.addr_);
 +}
 +
 +// This test verifies that the client in a SELECTING state can request
 +// a specific address and that this address will be assigned when
 +// available. It also tests that if the client requests an address which
 +// is in use the client will get a different address.
 +TEST_F(DORATest, selectingRequestAddress) {
 +    Dhcp4Client client(Dhcp4Client::SELECTING);
 +    // Configure DHCP server.
 +    configure(DORA_CONFIGS[0], *client.getServer());
 +
 +    // Perform 4-way exchange with the server.
 +    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
 +                                  IOAddress>(new IOAddress("10.0.0.50"))));
 +
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    Pkt4Ptr resp = client.getContext().response_;
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got the lease with the requested address.
 +    ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
 +
 +    // Simulate different client requesting the same address.
 +    client.modifyHWAddr();
 +    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
 +                                  IOAddress>(new IOAddress("10.0.0.50"))));
 +    resp = client.getContext().response_;
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(resp);
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got some address.
 +    EXPECT_NE(client.config_.lease_.addr_.toText(), "0.0.0.0");
 +    // Make sure that the client has got a different address than requested
 +    // as the requested one is already in use.
 +    EXPECT_NE(client.config_.lease_.addr_.toText(), "10.0.0.50");
 +}
 +
 +// This test verifies that the client will get the address that it has
 +// been allocated when the client requests a different address.
 +TEST_F(DORATest, selectingRequestNonMatchingAddress) {
 +    Dhcp4Client client(Dhcp4Client::SELECTING);
 +    // Configure DHCP server.
 +    configure(DORA_CONFIGS[0], *client.getServer());
 +
 +    // Perform 4-way exchange with the server.
 +    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
 +                                  IOAddress>(new IOAddress("10.0.0.50"))));
 +
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    Pkt4Ptr resp = client.getContext().response_;
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got the lease with the requested address.
 +    ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
 +
 +    // Let's request a different address. The server should respond with
 +    // the one that the client already has allocated.
 +    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
 +                                  IOAddress>(new IOAddress("10.0.0.80"))));
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    resp = client.getContext().response_;
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got the lease with the address that
 +    // the client has recorded in the lease database.
 +    EXPECT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
 +}
 +
 +// Test that the client in the INIT-REBOOT state can request the IP
 +// address it has and the address is returned. Also, check that if
 +// if the client requests in valid address the server sends a DHCPNAK.
 +TEST_F(DORATest, InitRebootRequest) {
 +    Dhcp4Client client(Dhcp4Client::SELECTING);
 +    // Configure DHCP server.
 +    configure(DORA_CONFIGS[0], *client.getServer());
 +    // Obtain a lease from the server using the 4-way exchange.
 +    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<
 +                                  IOAddress>(new IOAddress("10.0.0.50"))));
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    Pkt4Ptr resp = client.getContext().response_;
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got the lease with the requested address.
 +    ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
 +
 +    // Client has a lease in the database. Let's transition the client
 +    // to the INIT_REBOOT state so as the client can request the cached
 +    // lease using the DHCPREQUEST message.
 +    client.setState(Dhcp4Client::INIT_REBOOT);
 +    ASSERT_NO_THROW(client.doRequest());
 +
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    resp = client.getContext().response_;
 +    // Make sure that the server has responded with DHCPACK.
 +    ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
 +    // Response must not be relayed.
 +    EXPECT_FALSE(resp->isRelayed());
 +    // Make sure that the server id is present.
 +    EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
 +    // Make sure that the client has got the lease with the requested address.
 +    ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
 +
 +    // Try to request a different address than the client has. The server
 +    // should respond with DHCPNAK.
 +    client.config_.lease_.addr_ = IOAddress("10.0.0.30");
 +    ASSERT_NO_THROW(client.doRequest());
 +    // Make sure that the server responded.
 +    ASSERT_TRUE(client.getContext().response_);
 +    resp = client.getContext().response_;
 +    EXPECT_EQ(DHCPNAK, static_cast<int>(resp->getType()));
 +}
 +
 +} // end of anonymous namespace
index b436144bff154fbb98ded30302c9110d51342e59,0000000000000000000000000000000000000000..26bfe1e927564f9da93aafd2bd9d0204ea09d3f9
mode 100644,000000..100644
--- /dev/null
@@@ -1,329 -1,0 +1,329 @@@
-         "    \"pool\": [ \"2001:db8:1::/64\" ],"
 +// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
 +//
 +// Permission to use, copy, modify, and/or distribute this software for any
 +// purpose with or without fee is hereby granted, provided that the above
 +// copyright notice and this permission notice appear in all copies.
 +//
 +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 +// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 +// PERFORMANCE OF THIS SOFTWARE.
 +
 +#include <config.h>
 +#include <asiolink/io_address.h>
 +#include <cc/data.h>
 +#include <dhcp/tests/iface_mgr_test_config.h>
 +#include <dhcp6/json_config_parser.h>
 +#include <dhcp6/tests/dhcp6_message_test.h>
 +
 +using namespace isc;
 +using namespace isc::asiolink;
 +using namespace isc::data;
 +using namespace isc::dhcp;
 +using namespace isc::dhcp::test;
 +using namespace isc::test;
 +
 +namespace {
 +
 +/// @brief Set of JSON configurations used throughout the Confirm tests.
 +///
 +/// - Configuration 0:
 +///   - only addresses (no prefixes)
 +///   - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::/64
 +///   - 1 subnet for eth0 and 1 subnet for eth1
 +///
 +/// - Configuration 1:
 +///   - similar to Configuration 0
 +///   - pools configured: 3000:1::/64 and 3000:2::/64
 +///   - this specific configuration is used by tests using relays
 +///
 +const char* CONFIRM_CONFIGS[] = {
 +// Configuration 0
 +    "{ \"interfaces\": [ \"all\" ],"
 +        "\"preferred-lifetime\": 3000,"
 +        "\"rebind-timer\": 2000, "
 +        "\"renew-timer\": 1000, "
 +        "\"subnet6\": [ { "
-         "    \"pool\": [ \"2001:db8:2::/64\" ],"
++        "    \"pools\": [  { \"pool\": \"2001:db8:1::/64\" } ],"
 +        "    \"subnet\": \"2001:db8:1::/48\", "
 +        "    \"interface-id\": \"\","
 +        "    \"interface\": \"eth0\""
 +        " },"
 +        " {"
-         "    \"pool\": [ \"3000:1::/64\" ],"
++        "    \"pools\": [  { \"pool\": \"2001:db8:2::/64\" } ],"
 +        "    \"subnet\": \"2001:db8:2::/48\", "
 +        "    \"interface-id\": \"\","
 +        "    \"interface\": \"eth1\""
 +        " } ],"
 +        "\"valid-lifetime\": 4000 }",
 +
 +// Configuration 1
 +    "{ \"interfaces\": [ \"all\" ],"
 +        "\"preferred-lifetime\": 3000,"
 +        "\"rebind-timer\": 2000, "
 +        "\"renew-timer\": 1000, "
 +        "\"subnet6\": [ { "
-         "    \"pool\": [ \"3000:2::/64\" ],"
++        "    \"pools\": [  { \"pool\": \"3000:1::/64\" } ],"
 +        "    \"subnet\": \"3000:1::/48\", "
 +        "    \"interface-id\": \"\","
 +        "    \"interface\": \"eth0\""
 +        " },"
 +        " {"
++        "    \"pools\": [  { \"pool\": \"3000:2::/64\" } ],"
 +        "    \"subnet\": \"3000:2::/48\", "
 +        "    \"interface-id\": \"\","
 +        "    \"interface\": \"eth1\""
 +        " } ],"
 +        "\"valid-lifetime\": 4000 }"
 +};
 +
 +/// @brief Test fixture class for testing Confirm..
 +class ConfirmTest : public isc::dhcp::test::Dhcpv6MessageTest {
 +public:
 +
 +    /// @brief Constructor.
 +    ///
 +    /// Sets up fake interfaces.
 +    ConfirmTest()
 +        : Dhcpv6MessageTest() {
 +    }
 +
 +};
 +
 +
 +// Test that directly connected client's Confirm message is processed and Reply
 +// message is sent back. In this test case, the client sends Confirm for two
 +// addresses that belong to the same IAID and are sent within the same IA_NA
 +// option (RFC3315, section 18.2.2).
 +TEST_F(ConfirmTest, directClientSameIAID) {
 +    Dhcp6Client client;
 +    // Configure client to request IA_NA.
 +    client.useNA();
 +    // Make 4-way exchange to get the lease.
 +    ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[0], 2, client));
 +    // Keep the client's lease for future reference.
 +    Lease6 lease_client1 = client.getLease(0);
 +    // Clone the lease and modify its address so as it is still in the range
 +    // of the subnet to which the first lease belongs. When the client sends
 +    // the Confirm it should include both addresses and the server should
 +    // send Success because both of these addresses are on-link, regardless
 +    // what the server has in the lease database.
 +    Lease6 lease_client2 = lease_client1;
 +    lease_client2.addr_ = bumpAddress(lease_client2.addr_);
 +    client.createLease(lease_client2);
 +    ASSERT_EQ(2, client.getLeaseNum());
 +    // Send Confirm message to the server.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    // Client should have received a status code option and this option should
 +    // indicate the success.
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_Success, client.getStatusCode());
 +
 +    ASSERT_EQ(2, client.getLeaseNum());
 +    lease_client2 = client.getLease(1);
 +    lease_client2.addr_ = bumpSubnet(lease_client2.addr_);
 +    client.createLease(lease_client2);
 +    // Send confirm to the server. This time, one of the leases contains the
 +    // address which doesn't belong to the configured subnet and the server
 +    // should respond with STATUS_NotOnLink.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
 +    // Make sure that the server id has been included.
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
 +}
 +
 +// Test that directly connected client's Confirm message is processed and Reply
 +// message is sent back. In this test case, the client sends Confirm for two
 +// addresses that belong to different IAIDs and are sent within the different
 +// IA_NA options (RFC3315, section 18.2.2).
 +TEST_F(ConfirmTest, directClientDifferentIAID) {
 +    Dhcp6Client client;
 +    // Configure client to request IA_NA.
 +    client.useNA();
 +    // Make 4-way exchange to get the lease.
 +    ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[0], 2, client));
 +    // Keep the client's lease for future reference.
 +    Lease6 lease_client1 = client.getLease(0);
 +    // Clone the lease and modify its address so as it is still in the range
 +    // of the subnet to which the first lease belongs. When the client sends
 +    // the Confirm it should include both addresses and the server should
 +    // send Success because both of these addresses are on-link, regardless
 +    // what the server has in the lease database.
 +    Lease6 lease_client2 = lease_client1;
 +    ++lease_client2.iaid_;
 +    lease_client2.addr_ = bumpAddress(lease_client2.addr_);
 +    client.createLease(lease_client2);
 +    ASSERT_EQ(2, client.getLeaseNum());
 +    // Send Confirm message to the server.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    // Client should have received a status code option and this option should
 +    // indicate the success.
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_Success, client.getStatusCode());
 +    // Make sure that the server id and client id have been included.
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
 +
 +    ASSERT_EQ(2, client.getLeaseNum());
 +    lease_client2 = client.getLease(1);
 +    lease_client2.addr_ = bumpSubnet(lease_client2.addr_);
 +    client.createLease(lease_client2);
 +    // Send confirm to the server. This time, one of the leases contains the
 +    // address which doesn't belong to the configured subnet and the server
 +    // should respond with STATUS_NotOnLink.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
 +    // Make sure that the server id have been included.
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
 +}
 +
 +
 +// Test that relayed client's Confirm message is processed and Reply message
 +// is sent back (RFC3315, section 18.2.2).
 +TEST_F(ConfirmTest, relayedClient) {
 +    Dhcp6Client client;
 +    // Client to send relayed message.
 +    client.useRelay();
 +    // Configure client to request IA_NA.
 +    client.useNA();
 +    // Make 4-way exchange to get the lease.
 +    ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client));
 +    // Keep the client's lease for future reference.
 +    Lease6 lease_client1 = client.getLease(0);
 +    // Clone the lease and modify its address so as it is still in the range
 +    // of the subnet to which the first lease belongs. When the client sends
 +    // the Confirm it should include both addresses and the server should
 +    // send Success because both of these addresses are on-link, regardless
 +    // what the server has in the lease database.
 +    Lease6 lease_client2 = lease_client1;
 +    lease_client2.addr_ = bumpAddress(lease_client2.addr_);
 +    ++lease_client2.iaid_;
 +    client.createLease(lease_client2);
 +    // Send Confirm message to the server.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    // Client should have received a status code option and this option should
 +    // indicate the success.
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_Success, client.getStatusCode());
 +
 +    lease_client2 = client.getLease(1);
 +    lease_client2.addr_ = bumpSubnet(lease_client2.addr_);
 +    client.createLease(lease_client2);
 +    // Send confirm to the server. This time, one of the leases contains the
 +    // address which doesn't belong to the configured subnet and the server
 +    // should respond with STATUS_NotOnLink.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
 +    // Make sure that the server id and client id have been included.
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
 +}
 +
 +// Test that the Confirm message without any addresses is discarded
 +// (RFC3315, section 18.2.2).
 +TEST_F(ConfirmTest, relayedClientNoAddress) {
 +    Dhcp6Client client;
 +    // Configure the server.
 +    configure(CONFIRM_CONFIGS[1], *client.getServer());
 +    // Make sure we ended-up having expected number of subnets configured.
 +    const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
 +    ASSERT_EQ(2, subnets->size());
 +    // Client to send relayed message.
 +    client.useRelay();
 +    // Send Confirm message to the server. This message will contain no
 +    // addresses because client has no leases.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    EXPECT_FALSE(client.getContext().response_);
 +}
 +
 +// This test checks that the server processes Confirm message correctly if
 +// the subnet can't be selected for the client (RFC3315, section 18.2.2).
 +TEST_F(ConfirmTest, relayedClientNoSubnet) {
 +    Dhcp6Client client;
 +    // Client to send relayed message.
 +    client.useRelay();
 +    // Configure client to request IA_NA.
 +    client.useNA();
 +    // Make 4-way exchange to get the lease.
 +    ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client));
 +    // Now that the client has a lease, let's remove any subnets to check
 +    // how the server would respond to the Confirm.
 +    ASSERT_NO_THROW(CfgMgr::instance().deleteSubnets6());
 +    // Send Confirm message to the server.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    // Client should have received a status code option and this option should
 +    // indicate that the client is NotOnLink becuase subnet could not be
 +    // selected.
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_NotOnLink, client.getStatusCode());
 +
 +    // Let's test another case that the client sends no addresses in the Confirm
 +    // message. The subnet can't be selected for that client as in the previous
 +    // case but this time the server must discard the client's message because
 +    // it contains no addresses (is invalid).
 +
 +    // Set lifetimes to 0 so as the Confirm will ignore the specific address
 +    // and send an empty IA_NA.
 +    client.config_.leases_[0].lease_.preferred_lft_ = 0;
 +    client.config_.leases_[0].lease_.valid_lft_ = 0;
 +    ASSERT_NO_THROW(client.doConfirm());
 +    EXPECT_FALSE(client.getContext().response_);
 +
 +    // Do similar test but this time remove the lease so as no IA_NA option
 +    // is sent.
 +    client.config_.clear();
 +    ASSERT_NO_THROW(client.doConfirm());
 +    EXPECT_FALSE(client.getContext().response_);
 +}
 +
 +// This test checks that the relayed Confirm messsage is processed by the server
 +// when sent to unicast address RFC3315, section 18.2.8).
 +TEST_F(ConfirmTest, relayedUnicast) {
 +    Dhcp6Client client;
 +    // Client to send relayed message.
 +    client.useRelay();
 +    // Configure client to request IA_NA.
 +    client.useNA();
 +    // Make 4-way exchange to get the lease.
 +    ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client));
 +    // Make sure we have got the lease.
 +    ASSERT_GT(client.getLeaseNum(), 0);
 +    client.setDestAddress(IOAddress("2001:db8:1::1"));
 +    // Send Confirm message to the server.
 +    ASSERT_NO_THROW(client.doConfirm());
 +    // Client should have received a response.
 +    ASSERT_TRUE(client.getContext().response_);
 +    // Client should have received a status code option and this option should
 +    // indicate the success.
 +    ASSERT_TRUE(client.receivedStatusCode());
 +    ASSERT_EQ(STATUS_Success, client.getStatusCode());
 +    // Make sure that the server id and client id have been included.
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_SERVERID));
 +    EXPECT_TRUE(client.getContext().response_->getOption(D6O_CLIENTID));
 +}
 +
 +// This test checks that the Confirm message is discarded by the server if it
 +// has been sent to unicast address (RFC3315, section 15).
 +TEST_F(ConfirmTest, unicast) {
 +    Dhcp6Client client;
 +    // Configure client to request IA_NA.
 +    client.useNA();
 +    // Make 4-way exchange to get the lease.
 +    ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[0], 2, client));
 +    // Make sure the client has got the lease.
 +    ASSERT_GT(client.getLeaseNum(), 0);
 +    // Send Confirm message to the server to the unicast address.
 +    client.setDestAddress(IOAddress("2001:db8:1::1"));
 +    ASSERT_NO_THROW(client.doConfirm());
 +    // Mak sure that the server discarded client's Confirm message.
 +    EXPECT_FALSE(client.getContext().response_);
 +}
 +
 +} // end of anonymous namespace
index 75e9d0a62ac4ee67a496f0c64a1f190e8ec5aa37,6f185a9630418cd6ff994479ba519387a29159b8..54ee7e709a7ce0bb50fe01548beaa6a9c60f3f95
@@@ -33,23 -33,8 +33,23 @@@ CONFIG="
          \"subnet6\": [
          {
              \"subnet\": \"2001:db8:1::/64\",
-             \"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
+             \"pools\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
          } ]
 +    },
 +
 +    \"Logging\":
 +    {
 +        \"loggers\": [
 +        {
 +            \"name\": \"kea-dhcp6\",
 +            \"output_options\": [
 +                {
 +                    \"output\": \"$LOG_FILE\"
 +                }
 +            ],
 +            \"severity\": \"INFO\"
 +        }
 +        ]
      }
  }"
  # Invalid configuration (negative preferred-lifetime) to check that Kea
@@@ -70,23 -55,8 +70,23 @@@ CONFIG_INVALID="
          \"subnet6\": [
          {
              \"subnet\": \"2001:db8:1::/64\",
-             \"pool\": [ \"2001:db8:1::10-2001:db8:1::100\" ]
+             \"pool\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
          } ]
 +    },
 +
 +    \"Logging\":
 +    {
 +        \"loggers\": [
 +        {
 +            \"name\": \"kea-dhcp6\",
 +            \"output_options\": [
 +                {
 +                    \"output\": \"$LOG_FILE\"
 +                }
 +            ],
 +            \"severity\": \"INFO\"
 +        }
 +        ]
      }
  }"