memfile_lease_mgr.cc 10.8 KB
Newer Older
Stephen Morris's avatar
Stephen Morris committed
1
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14
//
// 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.

15
#include <dhcpsrv/dhcpsrv_log.h>
16
#include <dhcpsrv/memfile_lease_mgr.h>
17
#include <exceptions/exceptions.h>
18

19
#include <iostream>
20 21 22

using namespace isc::dhcp;

23 24
Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
    : LeaseMgr(parameters) {
25
    LOG_WARN(dhcpsrv_logger, DHCPSRV_MEMFILE_WARNING);
26 27 28 29 30
}

Memfile_LeaseMgr::~Memfile_LeaseMgr() {
}

31 32
bool
Memfile_LeaseMgr::addLease(const Lease4Ptr& lease) {
33 34
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_ADD_ADDR4).arg(lease->addr_.toText());
35

36 37 38 39 40 41
    if (getLease4(lease->addr_)) {
        // there is a lease with specified address already
        return (false);
    }
    storage4_.insert(lease);
    return (true);
42 43
}

44 45
bool
Memfile_LeaseMgr::addLease(const Lease6Ptr& lease) {
46 47
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_ADD_ADDR6).arg(lease->addr_.toText());
48

49
    if (getLease6(lease->type_, lease->addr_)) {
50 51 52 53 54 55 56
        // there is a lease with specified address already
        return (false);
    }
    storage6_.insert(lease);
    return (true);
}

57 58
Lease4Ptr
Memfile_LeaseMgr::getLease4(const isc::asiolink::IOAddress& addr) const {
59 60
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_ADDR4).arg(addr.toText());
61

62 63 64
    typedef Lease4Storage::nth_index<0>::type SearchIndex;
    const SearchIndex& idx = storage4_.get<0>();
    Lease4Storage::iterator l = idx.find(addr);
65 66 67
    if (l == storage4_.end()) {
        return (Lease4Ptr());
    } else {
68
        return (Lease4Ptr(new Lease4(**l)));
69
    }
70 71
}

72 73
Lease4Collection
Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr) const {
74
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
75
              DHCPSRV_MEMFILE_GET_HWADDR).arg(hwaddr.toText());
76 77 78 79 80 81 82 83 84 85 86
    typedef Lease4Storage::nth_index<0>::type SearchIndex;
    Lease4Collection collection;
    const SearchIndex& idx = storage4_.get<0>();
    for(SearchIndex::const_iterator lease = idx.begin();
        lease != idx.end(); ++lease) {

        // Every Lease4 has a hardware address, so we can compare it
        if((* lease)->hwaddr_ == hwaddr.hwaddr_) {
            collection.push_back((* lease));
        }
    }
87

88
    return (collection);
89 90
}

91 92
Lease4Ptr
Memfile_LeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
93 94
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_SUBID_HWADDR).arg(subnet_id)
95 96
        .arg(hwaddr.toText());

97 98 99
    // We are going to use index #1 of the multi index container.
    // We define SearchIndex locally in this function because
    // currently only this function uses this index.
100
    typedef Lease4Storage::nth_index<1>::type SearchIndex;
101
    // Get the index.
102
    const SearchIndex& idx = storage4_.get<1>();
103 104 105 106
    // Try to find the lease using HWAddr and subnet id.
    SearchIndex::const_iterator lease =
        idx.find(boost::make_tuple(hwaddr.hwaddr_, subnet_id));
    // Lease was not found. Return empty pointer to the caller.
107
    if (lease == idx.end()) {
108
        return (Lease4Ptr());
109 110
    }

111
    // Lease was found. Return it to the caller.
112
    return (Lease4Ptr(new Lease4(**lease)));
113 114
}

115 116
Lease4Collection
Memfile_LeaseMgr::getLease4(const ClientId& clientid) const {
117 118
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_CLIENTID).arg(clientid.toText());
119 120 121 122 123 124 125 126
    typedef Memfile_LeaseMgr::Lease4Storage::nth_index<0>::type SearchIndex;
    Lease4Collection collection;
    const SearchIndex& idx = storage4_.get<0>();
    for(SearchIndex::const_iterator lease = idx.begin();
        lease != idx.end(); ++ lease) {

        // 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
127
        if((*lease)->client_id_ && *(*lease)->client_id_ == clientid) {
128 129 130 131 132
            collection.push_back((* lease));
        }
    }

    return (collection);
133
}
134

135 136
Lease4Ptr
Memfile_LeaseMgr::getLease4(const ClientId& client_id,
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
                            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 {
167 168
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_SUBID_CLIENTID).arg(subnet_id)
169
              .arg(client_id.toText());
170

171 172 173
    // We are going to use index #2 of the multi index container.
    // We define SearchIndex locally in this function because
    // currently only this function uses this index.
174
    typedef Lease4Storage::nth_index<2>::type SearchIndex;
175
    // Get the index.
176
    const SearchIndex& idx = storage4_.get<2>();
177 178 179 180
    // Try to get the lease using client id and subnet id.
    SearchIndex::const_iterator lease =
        idx.find(boost::make_tuple(client_id.getClientId(), subnet_id));
    // Lease was not found. Return empty pointer to the caller.
181
    if (lease == idx.end()) {
182
        return (Lease4Ptr());
183
    }
184
    // Lease was found. Return it to the caller.
185
    return (Lease4Ptr(new Lease4(**lease)));
186 187
}

188
Lease6Ptr
189 190
Memfile_LeaseMgr::getLease6(Lease6::LeaseType /* not used yet */,
                            const isc::asiolink::IOAddress& addr) const {
191 192
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_ADDR6).arg(addr.toText());
193 194 195 196 197

    Lease6Storage::iterator l = storage6_.find(addr);
    if (l == storage6_.end()) {
        return (Lease6Ptr());
    } else {
198
        return (Lease6Ptr(new Lease6(**l)));
199 200 201
    }
}

202
Lease6Collection
203 204
Memfile_LeaseMgr::getLease6(Lease6::LeaseType /* not used yet */,
                            const DUID& duid, uint32_t iaid) const {
205 206
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_IAID_DUID).arg(iaid).arg(duid.toText());
207

208 209 210
    return (Lease6Collection());
}

211
Lease6Ptr
212 213
Memfile_LeaseMgr::getLease6(Lease6::LeaseType /* not used yet */,
                            const DUID& duid, uint32_t iaid,
214
                            SubnetID subnet_id) const {
215
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
216 217 218
              DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
              .arg(iaid).arg(subnet_id).arg(duid.toText());

219 220 221 222 223 224 225 226 227 228 229 230
    // We are going to use index #1 of the multi index container.
    // We define SearchIndex locally in this function because
    // currently only this function uses this index.
    typedef Lease6Storage::nth_index<1>::type SearchIndex;
    // Get the index.
    const SearchIndex& idx = storage6_.get<1>();
    // Try to get the lease using the DUID, IAID and Subnet ID.
    SearchIndex::const_iterator lease =
        idx.find(boost::make_tuple(duid.getDuid(), iaid, subnet_id));
    // Lease was not found. Return empty pointer.
    if (lease == idx.end()) {
        return (Lease6Ptr());
231
    }
232
    // Lease was found, return it to the caller.
233
    return (Lease6Ptr(new Lease6(**lease)));
234 235
}

236 237
void
Memfile_LeaseMgr::updateLease4(const Lease4Ptr& lease) {
238 239
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_UPDATE_ADDR4).arg(lease->addr_.toText());
240

241 242 243 244 245 246
    Lease4Storage::iterator lease_it = storage4_.find(lease->addr_);
    if (lease_it == storage4_.end()) {
        isc_throw(NoSuchLease, "failed to update the lease with address "
                  << lease->addr_.toText() << " - no such lease");
    }
    **lease_it = *lease;
247 248
}

249 250
void
Memfile_LeaseMgr::updateLease6(const Lease6Ptr& lease) {
251 252
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_UPDATE_ADDR6).arg(lease->addr_.toText());
253

254 255 256 257 258 259
    Lease6Storage::iterator lease_it = storage6_.find(lease->addr_);
    if (lease_it == storage6_.end()) {
        isc_throw(NoSuchLease, "failed to update the lease with address "
                  << lease->addr_.toText() << " - no such lease");
    }
    **lease_it = *lease;
260 261
}

262 263
bool
Memfile_LeaseMgr::deleteLease(const isc::asiolink::IOAddress& addr) {
264 265
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_DELETE_ADDR).arg(addr.toText());
266
    if (addr.isV4()) {
267 268 269 270 271 272 273 274 275
        // v4 lease
        Lease4Storage::iterator l = storage4_.find(addr);
        if (l == storage4_.end()) {
            // No such lease
            return (false);
        } else {
            storage4_.erase(l);
            return (true);
        }
276

277
    } else {
278
        // v6 lease
279 280 281 282 283 284 285 286
        Lease6Storage::iterator l = storage6_.find(addr);
        if (l == storage6_.end()) {
            // No such lease
            return (false);
        } else {
            storage6_.erase(l);
            return (true);
        }
287 288 289
    }
}

290 291
std::string
Memfile_LeaseMgr::getDescription() const {
292 293 294 295
    return (std::string("This is a dummy memfile backend implementation.\n"
                        "It does not offer any useful lease management and its only\n"
                        "purpose is to test abstract lease manager API."));
}
296 297 298

void
Memfile_LeaseMgr::commit() {
299
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MEMFILE_COMMIT);
300 301 302 303
}

void
Memfile_LeaseMgr::rollback() {
304 305
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_ROLLBACK);
306
}