diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index 3e47a35390790ca44afbbdde2f222039ac6ac23b..79b52fe079592e2c5fabee1b7a063726a8e534db 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -204,6 +204,11 @@ A debug message issued when the server is attempting to obtain an IPv6 lease from the memory file database for a client with the specified IAID (Identity Association ID), Subnet ID and DUID (DHCP Unique Identifier). +% DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID obtaining IPv4 lease for client ID %1, hardware address %2 and subnet ID %3 +A debug message issued when the server is attempting to obtain an IPv4 +lease from the memory file database for a client with the specified +client ID, hardware address and subnet ID. + % DHCPSRV_MEMFILE_GET_SUBID_CLIENTID obtaining IPv4 lease for subnet ID %1 and client ID %2 A debug message issued when the server is attempting to obtain an IPv4 lease from the memory file database for a client with the specified diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index 64dec20d3311e29beb27f3a1f017df8e02c680c7..0b855689955b8344f468087b1f4f6487f31a05ad 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -124,11 +124,7 @@ Memfile_LeaseMgr::getLease4(const ClientId& clientid) const { // client-id is not mandatory in DHCPv4. There can be a lease that does // not have a client-id. Dereferencing null pointer would be a bad thing - if (!(*lease)->client_id_) { - continue; - } - - if(*(*lease)->client_id_ == clientid) { + if((*lease)->client_id_ && *(*lease)->client_id_ == clientid) { collection.push_back((* lease)); } } @@ -138,7 +134,36 @@ Memfile_LeaseMgr::getLease4(const ClientId& clientid) const { Lease4Ptr Memfile_LeaseMgr::getLease4(const ClientId& client_id, - SubnetID subnet_id) const { + const HWAddr& hwaddr, + SubnetID subnet_id) const { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_MEMFILE_GET_CLIENTID_HWADDR_SUBID).arg(client_id.toText()) + .arg(hwaddr.toText()) + .arg(subnet_id); + + // We are going to use index #3 of the multi index container. + // We define SearchIndex locally in this function because + // currently only this function uses this index. + typedef Lease4Storage::nth_index<3>::type SearchIndex; + // Get the index. + const SearchIndex& idx = storage4_.get<3>(); + // Try to get the lease using client id, hardware address and subnet id. + SearchIndex::const_iterator lease = + idx.find(boost::make_tuple(client_id.getClientId(), hwaddr.hwaddr_, + subnet_id)); + + if (lease == idx.end()) { + // Lease was not found. Return empty pointer to the caller. + return (Lease4Ptr()); + } + + // Lease was found. Return it to the caller. + return (*lease); +} + +Lease4Ptr +Memfile_LeaseMgr::getLease4(const ClientId& client_id, + SubnetID subnet_id) const { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id) .arg(client_id.toText()); diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 4ac753650f1c88804db42c7e1292dc0735451d92..df6475c2944a914e87c1d52099bd893142db97d3 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -107,6 +107,21 @@ public: /// @param clientid client identifier virtual Lease4Collection getLease4(const ClientId& clientid) const; + /// @brief Returns IPv4 lease for specified client-id/hwaddr/subnet-id tuple + /// + /// There can be at most one lease for a given client-id/hwaddr tuple + /// in a single pool, so this method with either return a single lease + /// or NULL. + /// + /// @param clientid client identifier + /// @param hwaddr hardware address of the client + /// @param subnet_id identifier of the subnet that lease must belong to + /// + /// @return a pointer to the lease (or NULL if a lease is not found) + virtual Lease4Ptr getLease4(const ClientId& clientid, + const HWAddr& hwaddr, + SubnetID subnet_id) const; + /// @brief Returns existing IPv4 lease for specified client-id /// /// There can be at most one lease for a given HW address in a single @@ -321,6 +336,35 @@ protected: // The subnet id is accessed through the subnet_id_ member. boost::multi_index::member > + >, + + // Specification of the fourth index starts here. + boost::multi_index::ordered_unique< + // This is a composite index that uses two values to search for a + // lease: client id and subnet id. + boost::multi_index::composite_key< + Lease4, + // The client id value is not directly accessible through the + // Lease4 object as it is wrapped with the ClientIdPtr object. + // Therefore we use the KeyFromKeyExtractor class to access + // client id through this cascaded structure. The client id + // is used as an index value. + KeyFromKeyExtractor< + // Specify that the vector holding client id value can be obtained + // from the ClientId object. + boost::multi_index::const_mem_fun, + &ClientId::getClientId>, + // Specify that the ClientId object (actually pointer to it) can + // be accessed by the client_id_ member of Lease4 class. + boost::multi_index::member + >, + // The hardware address is held in the hwaddr_ member of the + // Lease4 object. + boost::multi_index::member, + &Lease4::hwaddr_>, + // The subnet id is accessed through the subnet_id_ member. + boost::multi_index::member + > > > > Lease4Storage; // Specify the type name for this container. diff --git a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc index cf36d2ce8b730684ec9ce1ef6ba96570236b0fb9..507999f53ddd5d6dec0a36b23c450af3e7fef262 100644 --- a/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc @@ -145,6 +145,10 @@ TEST_F(MemfileLeaseMgrTest, getLease4ClientId) { ASSERT_EQ(1, returned.size()); // We should retrieve our lease... detailCompareLease(lease, *returned.begin()); + lease = initializeLease4(straddress4_[2]); + returned = lease_mgr->getLease4(*lease->client_id_); + + ASSERT_EQ(0, returned.size()); } // Checks that lease4 retrieval client id is null is working @@ -170,9 +174,8 @@ TEST_F(MemfileLeaseMgrTest, getLease4HWAddr) { boost::scoped_ptr lease_mgr(new Memfile_LeaseMgr(pmap)); // Let's initialize two different leases 4 and just add the first ... Lease4Ptr leaseA = initializeLease4(straddress4_[5]); - Lease4Ptr leaseB = initializeLease4(straddress4_[6]); HWAddr hwaddrA(leaseA->hwaddr_, HTYPE_ETHER); - HWAddr hwaddrB(leaseB->hwaddr_, HTYPE_ETHER); + HWAddr hwaddrB(vector(6, 0x80), HTYPE_ETHER); EXPECT_TRUE(lease_mgr->addLease(leaseA)); @@ -185,4 +188,26 @@ TEST_F(MemfileLeaseMgrTest, getLease4HWAddr) { ASSERT_EQ(1, returned.size()); } +// Checks lease4 retrieval with clientId, HWAddr and subnet_id +TEST_F(MemfileLeaseMgrTest, getLease4ClientIdHWAddrSubnetId) { + const LeaseMgr::ParameterMap pmap; + boost::scoped_ptr lease_mgr(new Memfile_LeaseMgr(pmap)); + + Lease4Ptr leaseA = initializeLease4(straddress4_[4]); + Lease4Ptr leaseB = initializeLease4(straddress4_[5]); + HWAddr hwaddrA(leaseA->hwaddr_, HTYPE_ETHER); + HWAddr hwaddrB(leaseB->hwaddr_, HTYPE_ETHER); + EXPECT_TRUE(lease_mgr->addLease(leaseA)); + // First case we should retrieve our lease + Lease4Ptr lease = lease_mgr->getLease4(*leaseA->client_id_, hwaddrA, leaseA->subnet_id_); + detailCompareLease(lease, leaseA); + lease = lease_mgr->getLease4(*leaseB->client_id_, hwaddrA, leaseA->subnet_id_); + detailCompareLease(lease, leaseA); + // But not the folowing, with different hwaddr and subnet + lease = lease_mgr->getLease4(*leaseA->client_id_, hwaddrB, leaseA->subnet_id_); + EXPECT_TRUE(lease == Lease4Ptr()); + lease = lease_mgr->getLease4(*leaseA->client_id_, hwaddrA, leaseB->subnet_id_); + EXPECT_TRUE(lease == Lease4Ptr()); +} + }; // end of anonymous namespace