static constexpr char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] = "::";
static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0;
static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1;
+static constexpr char NULL_RESERVED_KEY[] = "";
static constexpr cass_int32_t NULL_IAID = -1;
static constexpr cass_int32_t NULL_OPTION_UNIVERSE = -1;
static constexpr cass_int32_t NULL_OPTION_CODE = -1;
/// This value corresponds to the @ref Host::IdentifierType value.
cass_int32_t reserved_ipv6_prefix_address_type_;
+ /// @brief Key for authentication
+ std::string reserved_key_;
+
/// @brief The reservation's IAID
cass_int32_t iaid_;
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
// host
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
// denormalized reservation, option
- "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? "
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? "
") "
"IF NOT EXISTS "
}},
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
+ "reserved_key, "
"iaid, "
"option_universe, "
"option_code, "
data.add(&reserved_ipv6_prefix_length_);
// reserved_ipv6_prefix_address_type: int
data.add(&reserved_ipv6_prefix_address_type_);
+ // reserved_key: text
+ data.add(&reserved_key_);
// iaid: int
data.add(&iaid_);
/// @}
reserved_ipv6_prefix_length_ = NULL_RESERVED_IPV6_PREFIX_LENGTH;
// reserved_ipv6_prefix_address_type: int
reserved_ipv6_prefix_address_type_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE;
+ // reserved_key: text
+ key_ = NULL_RESERVED_KEY;
iaid_ = NULL_IAID;
} else {
// reserved_ipv6_prefix_address: text
reserved_ipv6_prefix_address_type_ =
reservation->getType() == IPv6Resrv::TYPE_NA ? 0 : 2;
+ // reserved_key: text
+ reserved_key_ = reservation->getKeys();
+
// iaid: int
/// @todo: We don't support iaid in the IPv6Resrv yet.
iaid_ = 0;
data.add(&reserved_ipv6_prefix_address_);
data.add(&reserved_ipv6_prefix_length_);
data.add(&reserved_ipv6_prefix_address_type_);
+ data.add(&reserved_key_);
data.add(&iaid_);
// Option
}
return (IPv6Resrv(type, IOAddress(reserved_ipv6_prefix_address_),
- reserved_ipv6_prefix_length_));
+ reserved_ipv6_prefix_length_, reserved_key_));
}
const OptionWrapper
static constexpr StatementTag DELETE_LEASE6 = "DELETE_LEASE6";
static constexpr StatementTag GET_LEASE6_EXPIRE = "GET_LEASE6_EXPIRE";
static constexpr StatementTag GET_LEASE6_ADDR = "GET_LEASE6_ADDR";
+ static constexpr StatementTag GET_LEASE6_DUID = "GET_LEASE6_DUID";
static constexpr StatementTag GET_LEASE6_DUID_IAID = "GET_LEASE6_DUID_IAID";
static constexpr StatementTag GET_LEASE6_DUID_IAID_SUBID = "GET_LEASE6_DUID_IAID_SUBID";
static constexpr StatementTag GET_LEASE6_LIMIT = "GET_LEASE6_LIMIT";
"LIMIT ? "
"ALLOW FILTERING "}},
- // Gets an IPv6 lease with specified IPv4 address
+ // Gets an IPv6 lease with specified IPv6 address
{GET_LEASE6_ADDR,
{GET_LEASE6_ADDR,
"SELECT "
"AND lease_type = ? "
"ALLOW FILTERING "}},
+ // Gets an IPv6 lease with specified duid
+ {GET_LEASE6_DUID,
+ {GET_LEASE6_DUID,
+ "SELECT "
+ "address, valid_lifetime, expire, subnet_id, pref_lifetime, duid, iaid, "
+ "lease_type, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, hwtype, "
+ "hwaddr_source, state "
+ "FROM lease6 "
+ "WHERE duid = ? "
+ "ALLOW FILTERING "}},
+
// Gets an IPv6 lease(s) with specified duid and iaid
{GET_LEASE6_DUID_IAID,
{GET_LEASE6_DUID_IAID,
return (result);
}
+Lease6Ptr
+CqlLeaseMgr::getLease6(const DUID& duid) const {
+ std::string duid_data = duid.toText();
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_DUID)
+ .arg(duid_data);
+
+ // Set up the WHERE clause value
+ AnyArray data;
+
+ CassBlob duid_data(duid.getDuid());
+
+ data.add(&duid_data);
+
+ // Get the data.
+ Lease6Collection result;
+ std::unique_ptr<CqlLease6Exchange> exchange6(new CqlLease6Exchange(dbconn_));
+ exchange6->getLeaseCollection(CqlLease6Exchange::GET_LEASE6_DUID, data, result);
+
+ return (result);
+}
+
Lease6Collection
CqlLeaseMgr::getLeases6(Lease::Type lease_type, const DUID &duid, uint32_t iaid) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_IAID_DUID)
getLeases6(const asiolink::IOAddress& lower_bound_address,
const LeasePageSize& page_size) const override;
+ /// @brief Returns all IPv6 leases.
+ ///
+ /// @return Lease collection (may be empty if no IPv6 lease found).
+ virtual Lease6Collection getLeases6(const DUID& duid) const;
+
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
A debug message issued when the server is attempting to obtain an IPv6
lease from the MySQL database for the specified address.
+% DHCPSRV_MYSQL_GET_DUID obtaining IPv6 lease for duid %1,
+A debug message issued when the server is attempting to obtain an IPv6
+lease from the MySQL database for the specified duid.
+
% DHCPSRV_MYSQL_GET_CLIENTID obtaining IPv4 leases for client ID %1
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
leases from the PostgreSQL database for a client with the specified IAID
(Identity Association ID) and DUID (DHCP Unique Identifier).
+% DHCPSRV_PGSQL_GET_DUID obtaining IPv6 leases for DUID %1,
+A debug message issued when the server is attempting to obtain a set of IPv6
+leases from the PostgreSQL database for a client with the specified DUID (DHCP Unique Identifier).
+
% DHCPSRV_PGSQL_GET_IAID_SUBID_DUID obtaining IPv4 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 PostgreSQL database for a client with the specified IAID
#include <util/encode/hex.h>
#include <util/strutil.h>
#include <asiolink/io_address.h>
+#include <boost/random/uniform_int_distribution.hpp>
+#include <boost/random/mersenne_twister.hpp>
#include <exceptions/exceptions.h>
#include <sstream>
IPv6Resrv::IPv6Resrv(const Type& type,
const asiolink::IOAddress& prefix,
const uint8_t prefix_len)
- : type_(type), prefix_(asiolink::IOAddress("::")), prefix_len_(128) {
+ : type_(type), prefix_(asiolink::IOAddress("::")),
+ prefix_len_(128), keys_("") {
// Validate and set the actual values.
set(type, prefix, prefix_len);
}
+
+IPv6Resrv::IPv6Resrv(const Type& type,
+ const asiolink::IOAddress& prefix,
+ const std::string& keys,
+ const uint8_t prefix_len)
+ : type_(type), prefix_(asiolink::IOAddress("::")),
+ prefix_len_(128), keys_("") {
+ // Validate and set the actual values.
+ set(type, prefix, prefix_len, keys);
+}
+
void
IPv6Resrv::set(const Type& type, const asiolink::IOAddress& prefix,
- const uint8_t prefix_len) {
+ const uint8_t prefix_len, const std::string& keys) {
if (!prefix.isV6() || prefix.isV6Multicast()) {
isc_throw(isc::BadValue, "invalid prefix '" << prefix
<< "' for new IPv6 reservation");
isc_throw(isc::BadValue, "invalid prefix length '"
<< static_cast<int>(prefix_len)
<< "' for reserved IPv6 address, expected 128");
+ } else if (!keys.empty()) {
+ //Don't overwrite with an empty string
+ keys_ = keys;
}
type_ = type;
prefix_len_ = prefix_len;
}
+std::string
+IPv6Resrv::getRandomKeyString()
+{
+ std::array <char, 128> randomString;
+
+ std::random_device rd;
+ boost::random::mt19937 gen(rd());
+
+ std::for_each(randomString.begin(), randomString.end() - 1,
+ [&gen](char& a){ boost::random::uniform_int_distribution<char> dist('!', '~');
+ a = dist(gen); } );
+
+ return std::string(randomString.begin(), randomString.end());
+}
+
std::string
IPv6Resrv::toText() const {
std::ostringstream s;
s << prefix_;
// For PD, append prefix length.
+ // @todo: add to text for keys
if (getType() == TYPE_PD) {
s << "/" << static_cast<int>(prefix_len_);
}
IPv6Resrv::operator==(const IPv6Resrv& other) const {
return (type_ == other.type_ &&
prefix_ == other.prefix_ &&
- prefix_len_ == other.prefix_len_);
+ prefix_len_ == other.prefix_len_ &&
+ keys_ == other.keys_ );
}
bool
const asiolink::IOAddress& prefix,
const uint8_t prefix_len = 128);
+ /// @brief Constructor.
+ ///
+ /// Creates a reservation from the IPv6 address ,prefix length and
+ /// key value. If the prefix length is not specified, the default value
+ /// of 128 is used. This value indicates that the reservation is made
+ /// for an IPv6 address for a client which supports reconfiguration.
+ ///
+ /// @param type Reservation type: NA or PD.
+ /// @param prefix Address or prefix to be reserved.
+ /// @param keys to be reserved.
+ /// @param prefix_len Prefix length.
+ ///
+ /// @throw isc::BadValue if prefix is not IPv6 prefix, is a
+ /// multicast address or the prefix length is greater than 128.
+ IPv6Resrv(const Type& type,
+ const asiolink::IOAddress& prefix,
+ const std::string& keys,
+ const uint8_t prefix_len = 128);
+
/// @brief Returns prefix for the reservation.
const asiolink::IOAddress& getPrefix() const {
return (prefix_);
return (type_);
}
+ /// @brief Returns the keys.
+ ///
+ /// Keys are used for signing the Reconfigure Message.
+ /// The accessor should ensure 128 characters
+ std::string getKeys() const {
+ return (keys_);
+ }
+
/// @brief Sets a new prefix and prefix length.
///
/// @param type Reservation type: NA or PD.
/// @throw isc::BadValue if prefix is not IPv6 prefix, is a
/// multicast address or the prefix length is greater than 128.
void set(const Type& type, const asiolink::IOAddress& prefix,
- const uint8_t prefix_len);
+ const uint8_t prefix_len, const std::string& keys = "");
/// @brief Returns information about the reservation in the textual format.
std::string toText() const;
+ /// @brief Generates random 128 bit string
+ ///
+ /// Random string is generated by default will be used for
+ /// the keys to be used for signing Reconfigure Message.
+
+ static std::string getRandomKeyString();
+
/// @brief Equality operator.
///
/// @param other Reservation to compare to.
Type type_; ///< Reservation type.
asiolink::IOAddress prefix_; ///< Prefix
uint8_t prefix_len_; ///< Prefix length.
+ std::string keys_; ///< keys for authentication.
};
getLeases6(const asiolink::IOAddress& lower_bound_address,
const LeasePageSize& page_size) const = 0;
+ /// @brief Returns collection of lease for matching DUID
+ ///
+ /// @return Lease collection (may be empty if no IPv6 lease found for the DUID).
+ virtual Lease6Collection getLeases6(const DUID& duid) const = 0;
+
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
return (collection);
}
+Lease6Collection
+Memfile_LeaseMgr::getLeases6(const DUID& duid) const {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MEMFILE_GET6);
+
+ Lease6Collection collection;
+ for (auto lease = storage6_.begin(); lease != storage6_.end(); ++lease ) {
+ if ( (**lease).duid_->getDuid() == duid.getDuid() )
+ collection.push_back(Lease6Ptr(new Lease6(**lease)));
+ }
+
+ return (collection);
+}
+
void
Memfile_LeaseMgr::getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const {
getLeases6(const asiolink::IOAddress& lower_bound_address,
const LeasePageSize& page_size) const;
+ /// @brief Returns all IPv6 leases.
+ ///
+ /// @return Lease collection (may be empty if no IPv6 lease found).
+ virtual Lease6Collection getLeases6(const DUID& duid) const;
+
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
/// @brief Maximum length of the boot file name.
const size_t BOOT_FILE_NAME_MAX_LEN = 128;
+/// @brief Maximum length of keys.
+const size_t KEY_MAX_LEN = 128;
+
+/// @brief Numeric value representing last supported identifier.
/// @brief Numeric value representing last supported identifier.
///
/// This value is used to validate whether the identifier type stored in
private:
/// @brief Number of columns holding IPv6 reservation information.
- static const size_t RESERVATION_COLUMNS = 5;
+ static const size_t RESERVATION_COLUMNS = 6;
public:
reservation_id_(0),
reserv_type_(0), reserv_type_null_(MLM_FALSE),
ipv6_address_buffer_len_(0), prefix_len_(0), iaid_(0),
- reservation_id_index_(findAvailColumn()),
+ key_len_(0),reservation_id_index_(findAvailColumn()),
address_index_(reservation_id_index_ + 1),
prefix_len_index_(reservation_id_index_ + 2),
type_index_(reservation_id_index_ + 3),
iaid_index_(reservation_id_index_ + 4),
+ key_index_(reservation_id_index_ + 5),
most_recent_reservation_id_(0) {
memset(ipv6_address_buffer_, 0, sizeof(ipv6_address_buffer_));
columns_[prefix_len_index_] = "prefix_len";
columns_[type_index_] = "type";
columns_[iaid_index_] = "dhcp6_iaid";
+ columns_[key_index_] = "auth_key";
}
/// @brief Returns last fetched reservation id.
ipv6_address_buffer_[ipv6_address_buffer_len_] = '\0';
std::string address = ipv6_address_buffer_;
- IPv6Resrv r(type, IOAddress(address), prefix_len_);
+
+ key_buffer_[key_len_] = '\0';
+ std::string key = key_buffer_;
+
+ IPv6Resrv r(type, IOAddress(address), key, prefix_len_);
return (r);
};
bind_[iaid_index_].buffer = reinterpret_cast<char*>(&iaid_);
bind_[iaid_index_].is_unsigned = MLM_TRUE;
+ // key for auth VARCHAR(128)
+ key_len_ = sizeof(key_buffer_) - 1;
+ bind_[key_index_].buffer_type = MYSQL_TYPE_STRING;
+ bind_[key_index_].buffer = key_buffer_;
+ bind_[key_index_].buffer_length = key_len_;
+ bind_[key_index_].length = &key_len_;
+
// Add the error flags
setErrorIndicators(bind_, error_);
/// @brief IAID.
uint32_t iaid_;
+ /// @brief Buffer length for holding keys in textual format.
+ char key_buffer_[KEY_MAX_LEN + 1];
+
+ /// @brief Length of the keys
+ unsigned long key_len_;
+
/// @name Indexes of columns holding information about IPv6 reservations.
//@{
/// @brief Index of reservation_id column.
/// @brief Index of IAID column.
size_t iaid_index_;
+ /// @brief Index of keys column.
+ size_t key_index_;
+
//@}
/// @brief Reservation id for last processed row.
///
/// This class is only used to insert IPv6 reservations into the
/// ipv6_reservations table. It is not used to retrieve IPv6 reservations. To
-/// retrieve IPv6 reservation the @ref MySqlIPv6HostExchange class should be
+/// retrieve IPv6 reservation the @ref MySqlHostIPv6Exchange class should be
/// used instead.
///
/// When a new IPv6 reservation is inserted into the database, an appropriate
private:
/// @brief Set number of columns for ipv6_reservation table.
- static const size_t RESRV_COLUMNS = 6;
+ static const size_t RESRV_COLUMNS = 7;
public:
columns_[2] = "prefix_len";
columns_[3] = "type";
columns_[4] = "dhcp6_iaid";
+ columns_[5] = "auth_key";
BOOST_STATIC_ASSERT(4 < RESRV_COLUMNS);
}
bind_[4].buffer = reinterpret_cast<char*>(&host_id_);
bind_[4].is_unsigned = MLM_TRUE;
+ // key VARCHAR(128)
+ // why we need member for len
+ key_ = resv.getKeys();
+ key_len_ = key_.length();
+ bind_[5].buffer_type = MYSQL_TYPE_BLOB;
+ bind_[5].buffer = reinterpret_cast<char*>
+ (const_cast<char*>(key_.c_str()));
+ bind_[5].buffer_length = key_len_;
+ bind_[5].length = &key_len_;
+
} catch (const std::exception& ex) {
isc_throw(DbOperationError,
"Could not create bind array from IPv6 Reservation: "
/// @brief Address (or prefix).
std::string address_;
+ /// @brief Keys for Authentication
+ std::string key_;
+
+ /// @brief length of keys for Authentication
+ unsigned long key_len_;
+
/// @brief Length of the textual address representation.
unsigned long address_len_;
"o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
"o6.persistent, o6.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
- "r.dhcp6_iaid "
+ "r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o4 "
"ON h.host_id = o4.host_id "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
"o.persistent, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
- "r.dhcp6_iaid "
+ "r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o "
"ON h.host_id = o.host_id "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
"o.persistent, o.user_context,"
"r.reservation_id, r.address, r.prefix_len, r.type, "
- "r.dhcp6_iaid "
+ "r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o "
"ON h.host_id = o.host_id "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
"o.persistent, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
- "r.dhcp6_iaid "
+ "r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o "
"ON h.host_id = o.host_id "
// Inserts a single IPv6 reservation into 'reservations' table.
{MySqlHostDataSourceImpl::INSERT_V6_RESRV,
"INSERT INTO ipv6_reservations(address, prefix_len, type, "
- "dhcp6_iaid, host_id) "
- "VALUES (?,?,?,?,?)"},
+ "dhcp6_iaid, host_id, auth_key) "
+ "VALUES (?,?,?,?,?,?)"},
// Inserts a single DHCPv4 option into 'dhcp4_options' table.
// Using fixed scope_id = 3, which associates an option with host.
"state, user_context "
"FROM lease6 "
"WHERE address = ? AND lease_type = ?"},
- {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
+ {MySqlLeaseMgr::GET_LEASE6_DUID_IAID,
"SELECT address, duid, valid_lifetime, "
"expire, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len, "
return (result);
}
+Lease6Collection
+MySqlLeaseMgr::getLeases6(const DUID& duid) const {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_GET_DUID);
+
+ Lease6Collection result = getLeases6();
+
+ //erase the ones not containing the matching DUID
+ for (auto iter = result.begin(); iter != result.end();
+ iter++) {
+ if ((*iter)->duid_->getDuid() != duid.getDuid()) {
+ result.erase(iter);
+ }
+ }
+
+ return (result);
+}
+
void
MySqlLeaseMgr::getExpiredLeases4(Lease4Collection& expired_leases,
const size_t max_leases) const {
getLeases6(const asiolink::IOAddress& lower_bound_address,
const LeasePageSize& page_size) const;
+ /// @brief Returns all IPv6 leases.
+ ///
+ /// @return Lease collection (may be empty if no IPv6 lease found).
+ virtual Lease6Collection getLeases6(const DUID& duid) const;
+
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
private:
/// @brief Number of columns holding IPv6 reservation information.
- static const size_t RESERVATION_COLUMNS = 5;
+ static const size_t RESERVATION_COLUMNS = 6;
public:
prefix_len_index_(reservation_id_index_ + 2),
type_index_(reservation_id_index_ + 3),
iaid_index_(reservation_id_index_ + 4),
+ key_index_(reservation_id_index_ + 5),
most_recent_reservation_id_(0) {
// Provide names of additional columns returned by the queries.
columns_[prefix_len_index_] = "prefix_len";
columns_[type_index_] = "type";
columns_[iaid_index_] = "dhcp6_iaid";
+ columns_[key_index_] = "auth_key";
BOOST_STATIC_ASSERT(4 < RESERVATION_COLUMNS);
}
uint16_t prefix_len;
getColumnValue(r, row, prefix_len_index_, prefix_len);
+ // key_: string
+ string key;
+ getColumnValue(r, row, key_index_, key);
+
// @todo once we support populating iaid
// iaid: INT
// int iaid;
// getColumnValue(r, row, iaid_index_, iaid);
// Create the reservation.
- IPv6Resrv reservation(resv_type, IOAddress(address), prefix_len);
+ IPv6Resrv reservation(resv_type, IOAddress(address), key, prefix_len);
return (reservation);
};
/// @brief Index of IAID column.
size_t iaid_index_;
+ /// @brief Index of IAID column.
+ size_t key_index_;
+
//@}
/// @brief Reservation id for last processed row.
private:
/// @brief Set number of columns for ipv6_reservation table.
- static const size_t RESRV_COLUMNS = 6;
+ static const size_t RESRV_COLUMNS = 7;
public:
columns_[2] = "prefix_len";
columns_[3] = "type";
columns_[4] = "dhcp6_iaid";
- BOOST_STATIC_ASSERT(5 < RESRV_COLUMNS);
+ columns_[5] = "auth_key";
+ BOOST_STATIC_ASSERT(6 < RESRV_COLUMNS);
}
/// @brief Populate a bind array representing an IPv6 reservation
// host_id: BIGINT NOT NULL
bind_array->add(host_id);
+
+ // type: VARCHAR(128) NOT NULL
+ bind_array->add(resv.getKeys());
+
} catch (const std::exception& ex) {
isc_throw(DbOperationError,
"Could not create bind array from IPv6 Reservation: "
" o4.persistent, o4.user_context, "
" o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
" o6.persistent, o6.user_context, "
- " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
+ " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o4 ON h.host_id = o4.host_id "
"LEFT JOIN dhcp6_options AS o6 ON h.host_id = o6.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, h.dhcp4_boot_file_name, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
" o.persistent, o.user_context, "
- " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
+ " r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
"LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
" o.persistent, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, "
- " r.dhcp6_iaid "
+ " r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
"LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
" o.persistent, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, "
- " r.dhcp6_iaid "
+ " r.dhcp6_iaid, r.auth_key "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
"LEFT JOIN ipv6_reservations AS r ON h.host_id = r.host_id "
//PgSqlHostDataSourceImpl::INSERT_V6_RESRV
// Inserts a single IPv6 reservation into 'reservations' table.
- {5,
+ {6,
{ OID_VARCHAR, OID_INT2, OID_INT4, OID_INT4, OID_INT4 },
"insert_v6_resrv",
"INSERT INTO ipv6_reservations(address, prefix_len, type, "
- " dhcp6_iaid, host_id) "
- "VALUES ($1, $2, $3, $4, $5)"
+ " dhcp6_iaid, host_id, auth_key) "
+ "VALUES ($1, $2, $3, $4, $5, $6)"
},
// PgSqlHostDataSourceImpl::INSERT_V4_HOST_OPTION
return (result);
}
+Lease6Collection
+PgSqlLeaseMgr::getLeases6( const DUID& duid ) const {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
+ DHCPSRV_PGSQL_GET_DUID)
+ .arg(duid.toText());
+
+ Lease6Collection result = getLeases6();
+
+ //erase the ones not containing the matching DUID
+ for (auto iter = result.begin(); iter != result.end();
+ iter++) {
+ if ((*iter)->duid_->getDuid() != duid.getDuid()) {
+ result.erase(iter);
+ }
+ }
+
+ return (result);
+}
+
Lease6Collection
PgSqlLeaseMgr::getLeases6() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_GET6);
getLeases6(const asiolink::IOAddress& lower_bound_address,
const LeasePageSize& page_size) const;
+ /// @brief Returns all IPv6 leases.
+ ///
+ /// @return Lease collection (may be empty if no IPv6 lease found).
+ virtual Lease6Collection getLeases6(const DUID& duid) const;
+
/// @brief Returns a collection of expired DHCPv4 leases.
///
/// This method returns at most @c max_leases expired leases. The leases
destroyCqlSchema(false, true);
// Create a host with a reservation.
- HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", Host::IDENT_HWADDR, false);
+ HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", Host::IDENT_HWADDR, false, "key##1");
// Let's assign some DHCPv4 subnet to the host, because we will use the
// DHCPv4 subnet to try to retrieve the host after failed insertion.
host->setIPv4SubnetID(SubnetID(4));
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <cstdlib>
+#include <unordered_map>
#include <sstream>
using namespace isc;
EXPECT_EQ("2001:db8:1::cafe", resrv.getPrefix().toText());
EXPECT_EQ(128, resrv.getPrefixLen());
EXPECT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
+ EXPECT_EQ("", resrv.getKeys());
+
+ //create reservation with keys
+ IPv6Resrv resrv_keys(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::cafe"), "#ssd@@dce3");
+ EXPECT_EQ("2001:db8:1::cafe", resrv_keys.getPrefix().toText());
+ EXPECT_EQ(128, resrv_keys.getPrefixLen());
+ EXPECT_EQ(IPv6Resrv::TYPE_NA, resrv_keys.getType());
+ EXPECT_EQ("#ssd@@dce3", resrv_keys.getKeys());
}
// This test verifies that it is possible to create IPv6 prefix
EXPECT_EQ("2001:db8:1::", resrv.getPrefix().toText());
EXPECT_EQ(64, resrv.getPrefixLen());
EXPECT_EQ(IPv6Resrv::TYPE_PD, resrv.getType());
+ EXPECT_EQ("", resrv.getKeys());
+
+ //create reservation with keys
+ IPv6Resrv resrv_keys(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), "#ssd@@dce3", 64);
+ EXPECT_EQ("2001:db8:1::", resrv_keys.getPrefix().toText());
+ EXPECT_EQ(64, resrv_keys.getPrefixLen());
+ EXPECT_EQ(IPv6Resrv::TYPE_PD, resrv_keys.getType());
+ EXPECT_EQ("#ssd@@dce3", resrv_keys.getKeys());
}
// This test verifies that the toText() function prints correctly.
+// @todo: Add test to keys once toText() for keys is implemented.
TEST(IPv6ResrvTest, toText) {
IPv6Resrv resrv_prefix(IPv6Resrv::TYPE_PD, IOAddress("2001:db8:1::"), 64);
EXPECT_EQ("2001:db8:1::/64", resrv_prefix.toText());
isc::BadValue);
}
+// This test verifies that it is possible to modify the keys
+//
+TEST(IPv6ResrvTest, setKeys) {
+ // Create an address reservation without assigning keys.
+ IPv6Resrv resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1"));
+ ASSERT_EQ("2001:db8:1::1", resrv.getPrefix().toText());
+ ASSERT_EQ(128, resrv.getPrefixLen());
+ ASSERT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
+ ASSERT_EQ("", resrv.getKeys());
+
+ // Replace default keys with new value.
+ resrv.set(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1"), 128, "first_set_keys_#");
+ ASSERT_EQ("2001:db8:1::1", resrv.getPrefix().toText());
+ ASSERT_EQ(128, resrv.getPrefixLen());
+ ASSERT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
+ ASSERT_EQ("first_set_keys_#", resrv.getKeys());
+
+ // Modify an existing key for the reservation
+ resrv.set(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1"), 128, "second_set_keys_#");
+ ASSERT_EQ("2001:db8:1::1", resrv.getPrefix().toText());
+ ASSERT_EQ(128, resrv.getPrefixLen());
+ ASSERT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
+ ASSERT_EQ("second_set_keys_#", resrv.getKeys());
+
+ // Enusre not including the key parameter won't affect
+ // the current configured keys
+ resrv.set(IPv6Resrv::TYPE_NA, IOAddress("2001:db8:1::1"), 128);
+ ASSERT_EQ("2001:db8:1::1", resrv.getPrefix().toText());
+ ASSERT_EQ(128, resrv.getPrefixLen());
+ ASSERT_EQ(IPv6Resrv::TYPE_NA, resrv.getType());
+ ASSERT_EQ("second_set_keys_#", resrv.getKeys());
+}
+
// This test checks that the equality operators work fine.
TEST(IPv6ResrvTest, equal) {
EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::"), 64) ==
EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"), 128) !=
IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"), 128));
+ EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"),
+ "key##1", 128) ==
+ IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"),
+ "key##1", 128));
+ EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"),
+ "key##1", 128) !=
+ IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"),
+ "key##1", 128));
+
+ EXPECT_FALSE(IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"),
+ "key##1", 128) ==
+ IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::1"),
+ "key##2", 128));
+ EXPECT_TRUE(IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"),
+ "key##1", 128) !=
+ IPv6Resrv(IPv6Resrv::TYPE_PD, IOAddress("2001:db8::1"),
+ "key##2", 128));
}
/// @brief Test fixture class for @c Host.
EXPECT_FALSE(host->hasIPv6Reservation());
- // Add 4 reservations: 2 for NAs, 2 for PDs.
+ // Add 4 reservations: 2 for NAs, 2 for PDs
ASSERT_NO_THROW(
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
- IOAddress("2001:db8:1::cafe")));
+ IOAddress("2001:db8:1::cafe"), "key##1"));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
- IOAddress("2001:db8:1:1::"), 64));
+ IOAddress("2001:db8:1:1::"), "key##2", 64));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
IOAddress("2001:db8:1:2::"), 64));
host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
// Check that reservations exist.
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
- IOAddress("2001:db8:1::cafe"))));
+ IOAddress("2001:db8:1::cafe"), "key##1")));
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
- IOAddress("2001:db8:1:1::"),
+ IOAddress("2001:db8:1:1::"), "key##2",
64)));
EXPECT_TRUE(host->hasReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
IOAddress("2001:db8:1:2::"),
IPv6ResrvRange addresses = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
ASSERT_EQ(2, std::distance(addresses.first, addresses.second));
EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
- IOAddress("2001:db8:1::cafe")),
+ IOAddress("2001:db8:1::cafe"), "key##1"),
addresses));
EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_NA,
IOAddress("2001:db8:1::1")),
IPv6ResrvRange prefixes = host->getIPv6Reservations(IPv6Resrv::TYPE_PD);
ASSERT_EQ(2, std::distance(prefixes.first, prefixes.second));
EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_PD,
- IOAddress("2001:db8:1:1::"), 64),
+ IOAddress("2001:db8:1:1::"),"key##2", 64),
prefixes));
EXPECT_TRUE(reservationExists(IPv6Resrv(IPv6Resrv::TYPE_PD,
IOAddress("2001:db8:1:2::"), 64),
}
// This test checks that Host object is correctly unparsed,
+// @todo: add support for keys
TEST_F(HostTest, unparse) {
boost::scoped_ptr<Host> host;
ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
EXPECT_EQ(12345, host->getHostId());
}
+// Test verifies if getRandomKeyString can generate 1000 keys which are random
+TEST_F(HostTest, randomKeys) {
+ //use hashtable and set size to 1000
+ std::unordered_map<std::string, int> key_map;
+
+ int dup_element = 0;
+ const uint16_t max_iter = 1000;
+ uint16_t iter_num = 0;
+ size_t max_hash_size = 1000;
+
+ key_map.reserve(max_hash_size);
+
+ for (iter_num = 0; iter_num < max_iter; iter_num++) {
+ std::string key = IPv6Resrv::getRandomKeyString();
+ if (key_map[key]) {
+ dup_element++;
+ break;
+ }
+
+ key_map[key] = 1;
+ }
+
+ EXPECT_EQ(0, dup_element);
+}
+
+
} // end of anonymous namespace
+
+// Test verifies if
return (leases6_);
}
+ /// @brief Returns collection of lease for matching DUID
+ ///
+ /// @param duid ignored
+ /// @return whatever is set in leases6_ field
+ virtual Lease6Collection getLeases6(const DUID& duid) const {
+ return (leases6_);
+ }
+
/// @brief Returns all IPv6 leases for the particular subnet identifier.
///
/// @param subnet_id subnet identifier.
<< " drop command failed :" << PQerrorMessage(conn);
// Create a host with a reservation.
- HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", Host::IDENT_HWADDR, false);
+ HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", Host::IDENT_HWADDR, false, "randomKey");
// Let's assign some DHCPv4 subnet to the host, because we will use the
// DHCPv4 subnet to try to retrieve the host after failed insertion.
host->setIPv4SubnetID(SubnetID(4));
for (int i = 0; i < subnets; ++i) {
// Last boolean value set to false indicates that the same identifier
// must be used for each generated host.
- host = HostDataSourceUtils::initializeHost6(current_address.toText(), id, true, false);
+ host = HostDataSourceUtils::initializeHost6(current_address.toText(), id, true, "", false);
host->setIPv4SubnetID(i + 1000);
host->setIPv6SubnetID(i + 1000);
ASSERT_TRUE(hdsptr_);
// Let's create a couple of hosts...
- HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8::1", id, prefix);
- HostPtr host2 = HostDataSourceUtils::initializeHost6("2001:db8::2", id, prefix);
- HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8::3", id, prefix);
- HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8::4", id, prefix);
+ HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8::1",
+ id, prefix, "key##1");
+ HostPtr host2 = HostDataSourceUtils::initializeHost6("2001:db8::2",
+ id, prefix, "key##2");
+ HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8::3",
+ id, prefix, "key##3");
+ HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8::4",
+ id, prefix, "key##4");
// ... and add them to the data source.
ASSERT_NO_THROW(hdsptr_->add(host1));
ASSERT_TRUE(hdsptr_);
// Let's create a couple of hosts...
- HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8:1::", Host::IDENT_DUID, true);
- HostPtr host2 = HostDataSourceUtils::initializeHost6("2001:db8:2::", Host::IDENT_DUID, true);
- HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8:3::", Host::IDENT_DUID, true);
- HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8:4::", Host::IDENT_DUID, true);
+ HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8:1::", Host::IDENT_DUID, true, "key##1");
+ HostPtr host2 = HostDataSourceUtils::initializeHost6("2001:db8:2::", Host::IDENT_DUID, true, "key##2");
+ HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8:3::", Host::IDENT_DUID, true, "key##3");
+ HostPtr host4 = HostDataSourceUtils::initializeHost6("2001:db8:4::", Host::IDENT_DUID, true, "key##4");
// ... and add them to the data source.
ASSERT_NO_THROW(hdsptr_->add(host1));
ASSERT_TRUE(hdsptr_);
// Create a host reservations with prefix reservation (prefix = true)
- HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
+ HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID,
+ true, "key##1", true);
// Create IPv6 reservation (for an address) and add it to the host
- IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::2"), 128);
+ IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::2"), "key##2", 128);
host->addReservation(resv);
// Add this reservation
HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
// Add some reservations
- IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), len);
- IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::7"), len);
- IPv6Resrv resv3(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::8"), len);
- IPv6Resrv resv4(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::9"), len);
+ IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), "key##1", len);
+ IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::7"), "key##2", len);
+ IPv6Resrv resv3(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::8"), "key##3", len);
+ IPv6Resrv resv4(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::9"), "key##4", len);
host->addReservation(resv1);
host->addReservation(resv2);
HostPtr host2 = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
// Add some reservations
- IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), len);
- IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::7"), len);
- IPv6Resrv resv3(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::8"), len);
- IPv6Resrv resv4(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::9"), len);
+ IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), "key##1", len);
+ IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::7"), "key##2", len);
+ IPv6Resrv resv3(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::8"), "key##3", len);
+ IPv6Resrv resv4(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::9"), "key##4", len);
host1->addReservation(resv1);
host1->addReservation(resv2);
ss >> n_host;
const std::string prefix = std::string("2001:db8::") + n_host;
- hosts.push_back(HostDataSourceUtils::initializeHost6(prefix, Host::IDENT_HWADDR, false));
+ const std::string keys =
+ std::string("arbitary_long_enough_for_stress_test"
+ "but_less_than_128_characters");
+ hosts.push_back(HostDataSourceUtils::initializeHost6(prefix, Host::IDENT_HWADDR, false, keys));
+
IPv6ResrvRange range = hosts.back()->getIPv6Reservations();
ASSERT_EQ(1, std::distance(range.first, range.second));
EXPECT_TRUE(HostDataSourceUtils::reservationExists
ASSERT_TRUE(hdsptr_);
// Let's create a v6 host...
- HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
+ HostPtr host1 = HostDataSourceUtils::initializeHost6("2001:db8::1", Host::IDENT_DUID, false, "key##1");
SubnetID subnet1 = host1->getIPv6SubnetID();
// ... and add it to the data source.
}
HostPtr
-HostDataSourceUtils::initializeHost6(std::string address,
+HostDataSourceUtils::initializeHost6(const std::string address,
Host::IdentifierType identifier,
bool prefix,
+ const std::string& key,
bool new_identifier) {
std::vector<uint8_t> ident;
switch (identifier) {
if (!prefix) {
// Create IPv6 reservation (for an address)
- IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress(address), 128);
+ IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress(address), key, 128);
host->addReservation(resv);
} else {
// Create IPv6 reservation for a /64 prefix
- IPv6Resrv resv(IPv6Resrv::TYPE_PD, IOAddress(address), 64);
+ IPv6Resrv resv(IPv6Resrv::TYPE_PD, IOAddress(address), key, 64);
host->addReservation(resv);
}
return (host);
/// identifier should be generated or the same as previously.
///
/// @return generated Host object
- static HostPtr initializeHost6(std::string address, Host::IdentifierType id,
- bool prefix, bool new_identifier = true);
+ static HostPtr initializeHost6(const std::string address, Host::IdentifierType id,
+ bool prefix, const std::string& key = "", bool new_identifier = true);
/// @brief Generates a hardware address in text version.
///
prefix_len TINYINT(3) UNSIGNED NOT NULL DEFAULT 128,
type TINYINT(4) UNSIGNED NOT NULL DEFAULT 0,
dhcp6_iaid INT UNSIGNED NULL,
+ auth_key VARCHAR(128) NOT NULL,
host_id INT UNSIGNED NOT NULL,
PRIMARY KEY (reservation_id),
INDEX fk_ipv6_reservations_host_idx (host_id ASC),
# Add user contexts into tables holding DHCP options
ALTER TABLE dhcp4_options ADD COLUMN user_context TEXT NULL;
ALTER TABLE dhcp6_options ADD COLUMN user_context TEXT NULL;
+ALTER TABLE ipv6_reservations ADD COLUMN auth_key VARCHAR(128) NOT NULL;
# Create index for searching leases by subnet identifier.
CREATE INDEX lease4_by_subnet_id ON lease4 (subnet_id);
prefix_len SMALLINT NOT NULL DEFAULT '128',
type SMALLINT NOT NULL DEFAULT '0',
dhcp6_iaid INT DEFAULT NULL,
+ auth_key VARCHAR(128) NOT NULL,
host_id INT NOT NULL,
CONSTRAINT key_dhcp6_address_prefix_len UNIQUE (address, prefix_len),
CONSTRAINT fk_ipv6_reservations_host FOREIGN KEY (host_id) REFERENCES hosts (host_id) ON DELETE CASCADE