memfile_lease_mgr.cc 10.6 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 50 51 52 53 54 55 56
    if (getLease6(lease->addr_)) {
        // 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 189
Lease6Ptr
Memfile_LeaseMgr::getLease6(const isc::asiolink::IOAddress& addr) const {
190 191
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_ADDR6).arg(addr.toText());
192 193 194 195 196

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

201 202
Lease6Collection
Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid) const {
203 204
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_GET_IAID_DUID).arg(iaid).arg(duid.toText());
205

206 207 208
    return (Lease6Collection());
}

209 210 211
Lease6Ptr
Memfile_LeaseMgr::getLease6(const DUID& duid, uint32_t iaid,
                            SubnetID subnet_id) const {
212
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
213 214 215
              DHCPSRV_MEMFILE_GET_IAID_SUBID_DUID)
              .arg(iaid).arg(subnet_id).arg(duid.toText());

216 217 218 219 220 221 222 223 224 225 226 227
    // 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());
228
    }
229
    // Lease was found, return it to the caller.
230
    return (Lease6Ptr(new Lease6(**lease)));
231 232
}

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

238 239 240 241 242 243
    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;
244 245
}

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

251 252 253 254 255 256
    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;
257 258
}

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

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

287 288
std::string
Memfile_LeaseMgr::getDescription() const {
289 290 291 292
    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."));
}
293 294 295

void
Memfile_LeaseMgr::commit() {
296
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MEMFILE_COMMIT);
297 298 299 300
}

void
Memfile_LeaseMgr::rollback() {
301 302
    LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
              DHCPSRV_MEMFILE_ROLLBACK);
303
}