diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index 39baed3e22..b851b064ba 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -252,7 +252,7 @@ recommended. A debug message issued when the server is about to add an IPv4 lease with the specified address to the MySQL backend database. -% DHCPSRV_MYSQL_ADD_ADDR6 adding IPv6 lease with address %1 +% DHCPSRV_MYSQL_ADD_ADDR6 adding IPv6 lease with address %1, lease type %2 A debug message issued when the server is about to add an IPv6 lease with the specified address to the MySQL backend database. @@ -275,7 +275,7 @@ the specified address from the MySQL database for the specified address. A debug message issued when the server is attempting to obtain an IPv4 lease from the MySQL database for the specified address. -% DHCPSRV_MYSQL_GET_ADDR6 obtaining IPv6 lease for address %1 +% DHCPSRV_MYSQL_GET_ADDR6 obtaining IPv6 lease for address %1, lease type %2 A debug message issued when the server is attempting to obtain an IPv6 lease from the MySQL database for the specified address. @@ -289,12 +289,12 @@ A debug message issued when the server is attempting to obtain a set of IPv4 leases from the MySQL database for a client with the specified hardware address. -% DHCPSRV_MYSQL_GET_IAID_DUID obtaining IPv4 leases for IAID %1 and DUID %2 +% DHCPSRV_MYSQL_GET_IAID_DUID obtaining IPv6 leases for IAID %1, DUID %2, and lease type %3 A debug message issued when the server is attempting to obtain a set of IPv6 lease from the MySQL database for a client with the specified IAID (Identity Association ID) and DUID (DHCP Unique Identifier). -% DHCPSRV_MYSQL_GET_IAID_SUBID_DUID obtaining IPv4 leases for IAID %1, Subnet ID %2 and DUID %3 +% DHCPSRV_MYSQL_GET_IAID_SUBID_DUID obtaining IPv6 leases for IAID %1, Subnet ID %2, DUID %3, and lease type %4 A debug message issued when the server is attempting to obtain an IPv6 lease from the MySQL database for a client with the specified IAID (Identity Association ID), Subnet ID and DUID (DHCP Unique Identifier). @@ -321,7 +321,7 @@ be rolled back and not committed to the database. A debug message issued when the server is attempting to update IPv4 lease from the MySQL database for the specified address. -% DHCPSRV_MYSQL_UPDATE_ADDR6 updating IPv6 lease for address %1 +% DHCPSRV_MYSQL_UPDATE_ADDR6 updating IPv6 lease for address %1, lease type %2 A debug message issued when the server is attempting to update IPv6 lease from the MySQL database for the specified address. diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index 18e37b4132..731f90e771 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -163,21 +163,22 @@ TaggedStatement tagged_statements[] = { "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname " "FROM lease6 " - "WHERE address = ?"}, + "WHERE address = ? and lease_type = ?"}, {MySqlLeaseMgr::GET_LEASE6_DUID_IAID, "SELECT address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname " "FROM lease6 " - "WHERE duid = ? AND iaid = ?"}, + "WHERE duid = ? AND iaid = ? AND lease_type = ?"}, {MySqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID, "SELECT address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " "lease_type, iaid, prefix_len, " "fqdn_fwd, fqdn_rev, hostname " "FROM lease6 " - "WHERE duid = ? AND iaid = ? AND subnet_id = ?"}, + "WHERE duid = ? AND iaid = ? AND subnet_id = ? " + "AND lease_type = ?"}, {MySqlLeaseMgr::GET_VERSION, "SELECT version, minor FROM schema_version"}, {MySqlLeaseMgr::INSERT_LEASE4, @@ -1374,7 +1375,8 @@ MySqlLeaseMgr::addLease(const Lease4Ptr& lease) { bool MySqlLeaseMgr::addLease(const Lease6Ptr& lease) { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_MYSQL_ADD_ADDR6).arg(lease->addr_.toText()); + DHCPSRV_MYSQL_ADD_ADDR6).arg(lease->addr_.toText()) + .arg(lease->type_); // Create the MYSQL_BIND array for the lease std::vector bind = exchange6_->createBindForSend(lease); @@ -1651,13 +1653,14 @@ MySqlLeaseMgr::getLease4(const ClientId& clientid, SubnetID subnet_id) const { Lease6Ptr -MySqlLeaseMgr::getLease6(Lease6::LeaseType /* type - not used yet */, +MySqlLeaseMgr::getLease6(Lease6::LeaseType lease_type, const isc::asiolink::IOAddress& addr) const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_MYSQL_GET_ADDR6).arg(addr.toText()); + DHCPSRV_MYSQL_GET_ADDR6).arg(addr.toText()) + .arg(lease_type); // Set up the WHERE clause value - MYSQL_BIND inbind[1]; + MYSQL_BIND inbind[2]; memset(inbind, 0, sizeof(inbind)); std::string addr6 = addr.toText(); @@ -1670,6 +1673,11 @@ MySqlLeaseMgr::getLease6(Lease6::LeaseType /* type - not used yet */, inbind[0].buffer_length = addr6_length; inbind[0].length = &addr6_length; + // LEASE_TYPE + inbind[1].buffer_type = MYSQL_TYPE_TINY; + inbind[1].buffer = reinterpret_cast(&lease_type); + inbind[1].is_unsigned = MLM_TRUE; + Lease6Ptr result; getLease(GET_LEASE6_ADDR, inbind, result); @@ -1678,13 +1686,14 @@ MySqlLeaseMgr::getLease6(Lease6::LeaseType /* type - not used yet */, Lease6Collection -MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */, +MySqlLeaseMgr::getLeases6(Lease6::LeaseType lease_type, const DUID& duid, uint32_t iaid) const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_MYSQL_GET_IAID_DUID).arg(iaid).arg(duid.toText()); + DHCPSRV_MYSQL_GET_IAID_DUID).arg(iaid).arg(duid.toText()) + .arg(lease_type); // Set up the WHERE clause value - MYSQL_BIND inbind[2]; + MYSQL_BIND inbind[3]; memset(inbind, 0, sizeof(inbind)); // In the following statement, the DUID is being read. However, the @@ -1712,6 +1721,11 @@ MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */, inbind[1].buffer = reinterpret_cast(&iaid); inbind[1].is_unsigned = MLM_TRUE; + // LEASE_TYPE + inbind[2].buffer_type = MYSQL_TYPE_TINY; + inbind[2].buffer = reinterpret_cast(&lease_type); + inbind[2].is_unsigned = MLM_TRUE; + // ... and get the data Lease6Collection result; getLeaseCollection(GET_LEASE6_DUID_IAID, inbind, result); @@ -1720,15 +1734,16 @@ MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */, } Lease6Collection -MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */, +MySqlLeaseMgr::getLeases6(Lease6::LeaseType lease_type, const DUID& duid, uint32_t iaid, SubnetID subnet_id) const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_GET_IAID_SUBID_DUID) - .arg(iaid).arg(subnet_id).arg(duid.toText()); + .arg(iaid).arg(subnet_id).arg(duid.toText()) + .arg(lease_type); // Set up the WHERE clause value - MYSQL_BIND inbind[3]; + MYSQL_BIND inbind[4]; memset(inbind, 0, sizeof(inbind)); // See the earlier description of the use of "const_cast" when accessing @@ -1751,14 +1766,16 @@ MySqlLeaseMgr::getLeases6(Lease6::LeaseType /* type - not used yet */, inbind[2].buffer = reinterpret_cast(&subnet_id); inbind[2].is_unsigned = MLM_TRUE; - Lease6Ptr result; - getLease(GET_LEASE6_DUID_IAID_SUBID, inbind, result); + // LEASE_TYPE + inbind[3].buffer_type = MYSQL_TYPE_TINY; + inbind[3].buffer = reinterpret_cast(&lease_type); + inbind[3].is_unsigned = MLM_TRUE; - /// @todo: Implement getting one than more lease at the time - Lease6Collection collection; - collection.push_back(result); + // ... and get the data + Lease6Collection result; + getLeaseCollection(GET_LEASE6_DUID_IAID_SUBID, inbind, result); - return (collection); + return (result); } // Update lease methods. These comprise common code that handles the actual @@ -1823,7 +1840,8 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) { const StatementIndex stindex = UPDATE_LEASE6; LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, - DHCPSRV_MYSQL_UPDATE_ADDR6).arg(lease->addr_.toText()); + DHCPSRV_MYSQL_UPDATE_ADDR6).arg(lease->addr_.toText()) + .arg(lease->type_); // Create the MYSQL_BIND array for the data being updated std::vector bind = exchange6_->createBindForSend(lease); diff --git a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc index 52a39e9a7a..5096015b52 100644 --- a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc @@ -824,8 +824,7 @@ TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSubnetId) { /// /// Adds leases to the database and checks that they can be accessed via /// a combination of DIUID and IAID. -/// @todo: update this test once type checking/filtering is implemented -TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) { +TEST_F(MySqlLeaseMgrTest, getLeases6DuidIaid) { // Get the leases to be used for the test. vector leases = createLeases6(); ASSERT_LE(6, leases.size()); // Expect to access leases 0 through 5 @@ -840,8 +839,8 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) { *leases[1]->duid_, leases[1]->iaid_); - // Should be three leases, matching leases[1], [4] and [5]. - ASSERT_EQ(3, returned.size()); + // Should be two leases, matching leases[1] and [4]. + ASSERT_EQ(2, returned.size()); // Easiest way to check is to look at the addresses. vector addresses; @@ -852,7 +851,6 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) { sort(addresses.begin(), addresses.end()); EXPECT_EQ(straddress6_[1], addresses[0]); EXPECT_EQ(straddress6_[4], addresses[1]); - EXPECT_EQ(straddress6_[5], addresses[2]); // Check that nothing is returned when either the IAID or DUID match // nothing. @@ -871,8 +869,7 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaid) { // @brief Get Lease4 by DUID and IAID (2) // // Check that the system can cope with a DUID of any size. -/// @todo: update this test once type checking/filtering is implemented -TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSize) { +TEST_F(MySqlLeaseMgrTest, getLeases6DuidIaidSize) { // Create leases, although we need only one. vector leases = createLeases6(); @@ -902,6 +899,99 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSize) { // tests. } +/// @brief Check that getLease6 methods discriminate by lease type. +/// +/// Adds six leases, two per lease type all with the same duid and iad but +/// with alternating subnet_ids. +/// It then verifies that all of getLeases6() method variants correctly +/// discriminate between the leases based on lease type alone. +TEST_F(MySqlLeaseMgrTest, lease6LeaseTypeCheck) { + + Lease6Ptr empty_lease(new Lease6()); + + DuidPtr duid(new DUID(vector(8, 0x77))); + + // Initialize unused fields. + empty_lease->t1_ = 0; // Not saved + empty_lease->t2_ = 0; // Not saved + empty_lease->fixed_ = false; // Unused + empty_lease->comments_ = std::string(""); // Unused + empty_lease->iaid_ = 142; + empty_lease->duid_ = DuidPtr(new DUID(*duid)); + empty_lease->subnet_id_ = 23; + empty_lease->preferred_lft_ = 100; + empty_lease->valid_lft_ = 100; + empty_lease->cltt_ = 100; + empty_lease->fqdn_fwd_ = true; + empty_lease->fqdn_rev_ = true; + empty_lease->hostname_ = "myhost.example.com."; + empty_lease->prefixlen_ = 4; + + // Make Two leases per lease type, all with the same duid, iad but + // alternate the subnet_ids. + vector leases; + int tick = 0; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 2; j++) { + Lease6Ptr lease(new Lease6(*empty_lease)); + lease->type_ = leasetype6_[i]; + lease->addr_ = IOAddress(straddress6_[tick++]); + lease->subnet_id_ += j; + std::cout << "ok, subnet is: " << lease->subnet_id_ + << " tick is:" << tick << std::endl; + leases.push_back(lease); + EXPECT_TRUE(lmptr_->addLease(lease)); + } + } + + // Verify getting a single lease by type and address. + for (int i = 0; i < 3; i++) { + // Look for exact match for each lease type. + Lease6Ptr returned = lmptr_->getLease6(leasetype6_[i], + leases[i*2]->addr_); + // We should match one per lease type. + ASSERT_TRUE(returned); + EXPECT_TRUE(*returned == *leases[i*2]); + + // Same address but wrong lease type, should not match. + returned = lmptr_->getLease6(leasetype6_[i+1], leases[i*2]->addr_); + ASSERT_FALSE(returned); + } + + // Verify getting a collection of leases by type, duid, and iad. + // Iterate over the lease types, asking for leases based on + // lease type, duid, and iad. + tick = 0; + for (int i = 0; i < 3; i++) { + Lease6Collection returned = lmptr_->getLeases6(leasetype6_[i], + *duid, 142); + // We should match two per lease type. + ASSERT_EQ(2, returned.size()); + EXPECT_TRUE(*(returned[0]) == *leases[tick++]); + EXPECT_TRUE(*(returned[1]) == *leases[tick++]); + } + + // Verify getting a collection of leases by type, duid, iad, and subnet id. + // Iterate over the lease types, asking for leases based on + // lease type, duid, iad, and subnet_id. + for (int i = 0; i < 3; i++) { + Lease6Collection returned = lmptr_->getLeases6(leasetype6_[i], + *duid, 142, 23); + // We should match one per lease type. + ASSERT_EQ(1, returned.size()); + EXPECT_TRUE(*(returned[0]) == *leases[i*2]); + } + + // Verify getting a single lease by type, duid, iad, and subnet id. + for (int i = 0; i < 3; i++) { + Lease6Ptr returned = lmptr_->getLease6(leasetype6_[i], + *duid, 142, 23); + // We should match one per lease type. + ASSERT_TRUE(returned); + EXPECT_TRUE(*returned == *leases[i*2]); + } +} + /// @brief Check GetLease6 methods - access by DUID/IAID/SubnetID /// /// Adds leases to the database and checks that they can be accessed via @@ -939,6 +1029,7 @@ TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) { EXPECT_FALSE(returned); } + // @brief Get Lease4 by DUID, IAID & subnet ID (2) // // Check that the system can cope with a DUID of any size. @@ -1051,7 +1142,7 @@ TEST_F(MySqlLeaseMgrTest, updateLease6) { // ... and check what is returned is what is expected. l_returned.reset(); - l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]); + l_returned = lmptr_->getLease6(Lease6::LEASE_IA_PD, ioaddress6_[1]); ASSERT_TRUE(l_returned); detailCompareLease(leases[1], l_returned); @@ -1063,14 +1154,14 @@ TEST_F(MySqlLeaseMgrTest, updateLease6) { lmptr_->updateLease6(leases[1]); l_returned.reset(); - l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]); + l_returned = lmptr_->getLease6(Lease6::LEASE_IA_TA, ioaddress6_[1]); ASSERT_TRUE(l_returned); detailCompareLease(leases[1], l_returned); // Check we can do an update without changing data. lmptr_->updateLease6(leases[1]); l_returned.reset(); - l_returned = lmptr_->getLease6(leasetype6_[1], ioaddress6_[1]); + l_returned = lmptr_->getLease6(Lease6::LEASE_IA_TA, ioaddress6_[1]); ASSERT_TRUE(l_returned); detailCompareLease(leases[1], l_returned);