Commit 4784ca56 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[master] Merge branch 'trac2140' (Abstract API for DHCP database)

Conflicts:
	ChangeLog
	src/lib/dhcp/tests/Makefile.am
parents 5fadea67 df196f76
490. [func] tomek
libdhcp++: An abstract API for lease database has been
implemented. It offers a common interface to all concrete
database backends.
(Trac #2140, git df196f7609757253c4f2f918cd91012bb3af1163)
489. [func] muks
The isc::dns::RRsetList class has been removed. It was now unused
inside the BIND 10 codebase, and the interface was considered
......
......@@ -16,6 +16,7 @@ CLEANFILES = *.gcno *.gcda
lib_LTLIBRARIES = libb10-dhcp++.la libb10-dhcpsrv.la
libb10_dhcp___la_SOURCES =
libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
libb10_dhcp___la_SOURCES += lease_mgr.cc lease_mgr.h
libb10_dhcp___la_SOURCES += iface_mgr.cc iface_mgr.h
libb10_dhcp___la_SOURCES += iface_mgr_linux.cc
libb10_dhcp___la_SOURCES += iface_mgr_bsd.cc
......@@ -28,6 +29,7 @@ libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
libb10_dhcp___la_SOURCES += dhcp6.h dhcp4.h
libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
libb10_dhcp___la_SOURCES += duid.cc duid.h
libb10_dhcpsrv_la_SOURCES = cfgmgr.cc cfgmgr.h
libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
......
// Copyright (C) 2012 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 <vector>
#include <exceptions/exceptions.h>
#include <stdint.h>
#include <util/io_utilities.h>
#include <dhcp/duid.h>
namespace isc {
namespace dhcp {
DUID::DUID(const std::vector<uint8_t>& duid) {
if (duid.size() > MAX_DUID_LEN) {
isc_throw(OutOfRange, "DUID too large");
} else {
duid_ = duid;
}
}
DUID::DUID(const uint8_t * data, size_t len) {
if (len > MAX_DUID_LEN) {
isc_throw(OutOfRange, "DUID too large");
}
duid_ = std::vector<uint8_t>(data, data + len);
}
const std::vector<uint8_t> DUID::getDuid() const {
return (duid_);
}
DUID::DUIDType DUID::getType() const {
if (duid_.size() < 2) {
return (DUID_UNKNOWN);
}
uint16_t type = (duid_[0] << 8) + duid_[1];
if (type < DUID_MAX) {
return (static_cast<DUID::DUIDType>(type));
} else {
return (DUID_UNKNOWN);
}
}
bool DUID::operator == (const DUID& other) const {
return (this->duid_ == other.duid_);
}
bool DUID::operator != (const DUID& other) const {
return (this->duid_ != other.duid_);
}
/// constructor based on vector<uint8_t>
ClientId::ClientId(const std::vector<uint8_t>& clientid)
:DUID(clientid) {
}
/// constructor based on C-style data
ClientId::ClientId(const uint8_t *clientid, size_t len)
:DUID(clientid, len) {
}
/// @brief returns a copy of client-id data
const std::vector<uint8_t> ClientId::getClientId() const {
return (duid_);
}
// compares two client-ids
bool ClientId::operator == (const ClientId& other) const {
return (this->duid_ == other.duid_);
}
// compares two client-ids
bool ClientId::operator != (const ClientId& other) const {
return (this->duid_ != other.duid_);
}
}; // end of isc::dhcp namespace
}; // end of isc namespace
// Copyright (C) 2012 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 <stdint.h>
#include <unistd.h>
#include <vector>
#include <asiolink/io_address.h>
namespace isc {
namespace dhcp {
/// @brief Holds DUID (DHCPv6 Unique Identifier)
///
/// This class holds DUID, that is used in client-id, server-id and
/// several other options. It is used to identify DHCPv6 entity.
class DUID {
public:
/// @brief maximum duid size
/// As defined in RFC3315, section 9.1
static const size_t MAX_DUID_LEN = 128;
/// @brief specifies DUID type
typedef enum {
DUID_UNKNOWN = 0, ///< invalid/unknown type
DUID_LLT = 1, ///< link-layer + time, see RFC3315, section 9.2
DUID_EN = 2, ///< enterprise-id, see RFC3315, section 9.3
DUID_LL = 3, ///< link-layer, see RFC3315, section 9.4
DUID_UUID = 4, ///< UUID, see RFC6355
DUID_MAX ///< not a real type, just maximum defined value + 1
} DUIDType;
/// @brief creates a DUID
DUID(const std::vector<uint8_t>& duid);
/// @brief creates a DUID
DUID(const uint8_t *duid, size_t len);
/// @brief returns a const reference to the actual DUID value
///
/// Note: For safety reasons, this method returns a copy of data as
/// otherwise the reference would be only valid as long as the object that
/// returned it. In any case, this method should be used only sporadically.
/// If there are frequent uses, we must implement some other method
/// (e.g. storeSelf()) that will avoid data copying.
const std::vector<uint8_t> getDuid() const;
/// @brief returns DUID type
DUIDType getType() const;
// compares two DUIDs
bool operator == (const DUID& other) const;
// compares two DUIDs
bool operator != (const DUID& other) const;
protected:
/// the actual content of the DUID
std::vector<uint8_t> duid_;
};
/// @brief Holds Client identifier or client IPv4 address
///
/// This class is intended to be a generic IPv4 client identifier. It can hold
/// a client-id
class ClientId : DUID {
public:
/// constructor based on vector<uint8_t>
ClientId(const std::vector<uint8_t>& clientid);
/// constructor based on C-style data
ClientId(const uint8_t *clientid, size_t len);
/// @brief returns reference to the client-id data
///
const std::vector<uint8_t> getClientId() const;
// compares two client-ids
bool operator == (const ClientId& other) const;
// compares two client-ids
bool operator != (const ClientId& other) const;
};
}; // end of isc::dhcp namespace
}; // end of isc namespace
// Copyright (C) 2012 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 <sstream>
#include <iostream>
#include <map>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <exceptions/exceptions.h>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include "lease_mgr.h"
using namespace std;
using namespace isc::dhcp;
LeaseMgr::LeaseMgr(const std::string& dbconfig) {
if (dbconfig.length() == 0) {
return;
}
vector<string> tokens;
boost::split(tokens, dbconfig, boost::is_any_of("\t "));
BOOST_FOREACH(std::string token, tokens) {
size_t pos = token.find("=");
if (pos != string::npos) {
string name = token.substr(0, pos);
string value = token.substr(pos + 1, -1);
parameters_.insert(pair<string,string>(name, value));
} else {
isc_throw(InvalidParameter, "Cannot parse " << token
<< ", expected format is name=value");
}
}
}
std::string LeaseMgr::getParameter(const std::string& name) const {
map<string, string>::const_iterator param = parameters_.find(name);
if (param == parameters_.end()) {
isc_throw(BadValue, "Parameter not found");
}
return (param->second);
}
LeaseMgr::~LeaseMgr() {
}
// Copyright (C) 2012 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 <string>
#include <fstream>
#include <vector>
#include <map>
#include <asiolink/io_address.h>
#include <boost/shared_ptr.hpp>
#include <dhcp/option.h>
#include <dhcp/duid.h>
/// @file dhcp/lease_mgr.h
/// @brief An abstract API for lease database
///
/// This file contains declarations of Lease4, Lease6 and LeaseMgr classes.
/// They are essential components of the interface to any database backend.
/// Each concrete database backend (e.g. MySQL) will define a class derived
/// from LeaseMgr class.
///
/// Failover considerations:
/// There are no intermediate plans to implement DHCPv4 failover
/// (draft-ietf-dhc-failover-12.txt). Currently (Oct. 2012) the DHCPv6 failover
/// is being defined in DHC WG in IETF (draft-ietf-dhcpv6-failover-requirements,
/// draft-ietf-dhcpv6-dailover-design), but the work is not advanced enough
/// for implementation plans yet. v4 failover requires additional parameters
/// to be kept with a lease. It is likely that v6 failover will require similar
/// fields. Such implementation will require database schema extension.
/// We have designed a way to expand/upgrade schemas during upgrades: a database
/// schema is versioned and sanity checks about required version will be done
/// upon start and/or upgrade. With this mechanism in place, we can add new
/// fields to the database. In particular we can use that capability to
/// introduce failover related fields.
///
/// However, there is another approach that can be reliably used to provide
/// failover, even without the actual failover protocol implemented. As the
/// first backend will use MySQL, we will be able to use Multi-Master capability
/// offered by MySQL and use two separatate Kea instances connecting to the
/// same database.
///
/// Nevertheless, we hope to have failover protocol eventually implemented in
/// the Kea.
namespace isc {
namespace dhcp {
/// @brief specifies unique subnet identifier
/// @todo: Move this to subnet.h once ticket #2237 is merged
typedef uint32_t SubnetID;
/// @brief Structure that holds a lease for IPv4 address
///
/// For performance reasons it is a simple structure, not a class. If we chose
/// make it a class, all fields would have to made private and getters/setters
/// would be required. As this is a critical part of the code that will be used
/// extensively, direct access is warranted.
struct Lease4 {
/// IPv4 address
isc::asiolink::IOAddress addr_;
/// @brief Address extension
///
/// It is envisaged that in some cases IPv4 address will be accompanied with some
/// additional data. One example of such use are Address + Port solutions (or
/// Port-restricted Addresses), where several clients may get the same address, but
/// different port ranges. This feature is not expected to be widely used.
/// Under normal circumstances, the value should be 0.
uint32_t ext_;
/// @brief hardware address
std::vector<uint8_t> hwaddr_;
/// @brief client identifier
boost::shared_ptr<ClientId> client_id_;
/// @brief renewal timer
///
/// Specifies renewal time. Although technically it is a property of IA container,
/// not the address itself, since our data model does not define separate IA
/// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
/// for the same IA, each must have consistent T1 and T2 values. Specified in
/// seconds since cltt.
uint32_t t1_;
/// @brief rebinding timer
///
/// Specifies rebinding time. Although technically it is a property of IA container,
/// not the address itself, since our data model does not define separate IA
/// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
/// for the same IA, each must have consistent T1 and T2 values. Specified in
/// seconds since cltt.
uint32_t t2_;
/// @brief valid lifetime
///
/// Expressed as number of seconds since cltt
uint32_t valid_lft_;
/// @brief client last transmission time
///
/// Specifies a timestamp, when last transmission from a client was received.
time_t cltt_;
/// @brief Subnet identifier
///
/// Specifies subnet-id of the subnet that the lease belongs to
SubnetID subnet_id_;
/// @brief Is this a fixed lease?
///
/// Fixed leases are kept after they are released/expired.
bool fixed_;
/// @brief client hostname
///
/// This field may be empty
std::string hostname_;
/// @brief did we update AAAA record for this lease?
bool fqdn_fwd_;
/// @brief did we update PTR record for this lease?
bool fqdn_rev_;
/// @brief Lease comments.
///
/// Currently not used. It may be used for keeping comments made by the
/// system administrator.
std::string comments_;
/// @todo: Add DHCPv4 failover related fields here
};
/// @brief Pointer to a Lease4 structure.
typedef boost::shared_ptr<Lease4> Lease4Ptr;
/// @brief A collection of IPv4 leases.
typedef std::vector< boost::shared_ptr<Lease4Ptr> > Lease4Collection;
/// @brief Structure that holds a lease for IPv6 address and/or prefix
///
/// For performance reasons it is a simple structure, not a class. Had we chose to
/// make it a class, all fields would have to be made private and getters/setters
/// would be required. As this is a critical part of the code that will be used
/// extensively, direct access rather than through getters/setters is warranted.
struct Lease6 {
typedef enum {
LEASE_IA_NA, /// the lease contains non-temporary IPv6 address
LEASE_IA_TA, /// the lease contains temporary IPv6 address
LEASE_IA_PD /// the lease contains IPv6 prefix (for prefix delegation)
} LeaseType;
/// @brief specifies lease type (normal addr, temporary addr, prefix)
LeaseType type_;
/// IPv6 address
isc::asiolink::IOAddress addr_;
/// IPv6 prefix length (used only for PD)
uint8_t prefixlen_;
/// @brief IAID
///
/// Identity Association IDentifier. DHCPv6 stores all addresses and prefixes
/// in IA containers (IA_NA, IA_TA, IA_PD). Most containers may appear more
/// than once in a message. To differentiate between them, IAID field is present
uint32_t iaid_;
/// @brief hardware address
///
/// This field is not really used and is optional at best. The concept of identifying
/// clients by their hardware address was replaced in DHCPv6 by DUID concept. Each
/// client has its own unique DUID (DHCP Unique IDentifier). Furthermore, client's
/// HW address is not always available, because client may be behind a relay (relay
/// stores only link-local address).
std::vector<uint8_t> hwaddr_;
/// @brief client identifier
boost::shared_ptr<DUID> duid_;
/// @brief preferred lifetime
///
/// This parameter specifies preferred lifetime since the lease was assigned/renewed
/// (cltt), expressed in seconds.
uint32_t preferred_lft_;
/// @brief valid lifetime
///
/// This parameter specified valid lifetime since the lease was assigned/renewed
/// (cltt), expressed in seconds.
uint32_t valid_lft_;
/// @brief T1 timer
///
/// Specifies renewal time. Although technically it is a property of IA container,
/// not the address itself, since our data model does not define separate IA
/// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
/// for the same IA, each must have consistent T1 and T2 values. Specified in
/// seconds since cltt.
uint32_t t1_;
/// @brief T2 timer
///
/// Specifies rebinding time. Although technically it is a property of IA container,
/// not the address itself, since our data model does not define separate IA
/// entity, we are keeping it in the lease. In case of multiple addresses/prefixes
/// for the same IA, each must have consistent T1 and T2 values. Specified in
/// seconds since cltt.
uint32_t t2_;
/// @brief client last transmission time
///
/// Specifies a timestamp, when last transmission from a client was received.
time_t cltt_;
/// @brief Subnet identifier
///
/// Specifies subnet-id of the subnet that the lease belongs to
SubnetID subnet_id_;
/// @brief Is this a fixed lease?
///
/// Fixed leases are kept after they are released/expired.
bool fixed_;
/// @brief client hostname
///
/// This field may be empty
std::string hostname_;
/// @brief did we update AAAA record for this lease?
bool fqdn_fwd_;
/// @brief did we update PTR record for this lease?
bool fqdn_rev_;
/// @brief Lease comments
///
/// This field is currently not used.
std::string comments_;
/// @todo: Add DHCPv6 failover related fields here
};
/// @brief Pointer to a Lease6 structure.
typedef boost::shared_ptr<Lease6> Lease6Ptr;
/// @brief Const pointer to a Lease6 structure.
typedef boost::shared_ptr<const Lease6> ConstLease6Ptr;
/// @brief A collection of IPv6 leases.
typedef std::vector< boost::shared_ptr<Lease6Ptr> > Lease6Collection;
/// @brief Abstract Lease Manager
///
/// This is an abstract API for lease database backends. It provides unified
/// interface to all backends. As this is an abstract class, it should not
/// be used directly, but rather specialized derived class should be used
/// instead.
class LeaseMgr {
public:
/// Client Hardware address
typedef std::vector<uint8_t> HWAddr;
/// @brief The sole lease manager constructor
///
/// dbconfig is a generic way of passing parameters. Parameters
/// are passed in the "name=value" format, separated by spaces.
/// Values may be enclosed in double quotes, if needed.
///
/// @param dbconfig database configuration
LeaseMgr(const std::string& dbconfig);
/// @brief Destructor (closes file)
virtual ~LeaseMgr();
/// @brief Adds an IPv4 lease.
///
/// @param lease lease to be added
virtual bool addLease(Lease4Ptr lease) = 0;
/// @brief Adds an IPv6 lease.
///
/// @param lease lease to be added
virtual bool addLease(Lease6Ptr lease) = 0;
/// @brief Returns existing IPv4 lease for specified IPv4 address and subnet_id
///
/// This method is used to get a lease for specific subnet_id. There can be
/// at most one lease for any given subnet, so this method returns a single
/// pointer.
///
/// @param addr address of the searched lease
/// @param subnet_id ID of the subnet the lease must belong to
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr,
SubnetID subnet_id) const = 0;
/// @brief Returns an IPv4 lease for specified IPv4 address
///
/// This method return a lease that is associated with a given address.
/// For other query types (by hardware addr, by client-id) there can be
/// several leases in different subnets (e.g. for mobile clients that
/// got address in different subnets). However, for a single address
/// there can be only one lease, so this method returns a pointer to
/// a single lease, not a container of leases.
///
/// @param addr address of the searched lease
/// @param subnet_id ID of the subnet the lease must belong to
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
virtual Lease4Ptr getLease4(isc::asiolink::IOAddress addr) const = 0;
/// @brief Returns existing IPv4 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
virtual Lease4Collection getLease4(const HWAddr& hwaddr) const = 0;
/// @brief Returns existing IPv4 leases for specified hardware address
/// and a subnet
///
/// There can be at most one lease for a given HW address in a single
/// pool, so this method with either return a single lease or NULL.
///
/// @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 HWAddr& hwaddr,
SubnetID subnet_id) const = 0;
/// @brief Returns existing IPv4 lease for specified client-id