diff --git a/src/lib/dhcpsrv/lease_mgr.cc b/src/lib/dhcpsrv/lease_mgr.cc index 2b588b60df..4e7e1c540f 100644 --- a/src/lib/dhcpsrv/lease_mgr.cc +++ b/src/lib/dhcpsrv/lease_mgr.cc @@ -1266,5 +1266,15 @@ LeaseMgr::addExtendedInfo6(const Lease6Ptr& lease) { return (added); } +size_t +LeaseMgr::byRelayId6size() const { + return (0); +} + +size_t +LeaseMgr::byRemoteId6size() const { + return (0); +} + } // namespace isc::dhcp } // namespace isc diff --git a/src/lib/dhcpsrv/lease_mgr.h b/src/lib/dhcpsrv/lease_mgr.h index e372d04b7b..ce60d3dff4 100644 --- a/src/lib/dhcpsrv/lease_mgr.h +++ b/src/lib/dhcpsrv/lease_mgr.h @@ -1043,6 +1043,20 @@ public: /// @brief Wipe extended info table (v6). virtual void wipeExtendedInfoTables6() = 0; + /// @brief Return the by-relay-id table size. + /// + /// Must be derived by backends implementing the table. + /// + /// @return Always 0. + virtual size_t byRelayId6size() const; + + /// @brief Return the by-remote-id table size. + /// + /// Must be derived by backends implementing the table. + /// + /// @return Always 0. + virtual size_t byRemoteId6size() const; + protected: /// Extended information / Bulk Lease Query shared interface. diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.cc b/src/lib/dhcpsrv/memfile_lease_mgr.cc index dbb39dfcf6..e501e8f97b 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.cc +++ b/src/lib/dhcpsrv/memfile_lease_mgr.cc @@ -3051,6 +3051,16 @@ Memfile_LeaseMgr::wipeExtendedInfoTables6() { } } +size_t +Memfile_LeaseMgr::byRelayId6size() const { + return (relay_id6_.size()); +} + +size_t +Memfile_LeaseMgr::byRemoteId6size() const { + return (remote_id6_.size()); +} + Lease6Collection Memfile_LeaseMgr::getLeases6ByRelayId(const DUID& relay_id, const IOAddress& link_addr, diff --git a/src/lib/dhcpsrv/memfile_lease_mgr.h b/src/lib/dhcpsrv/memfile_lease_mgr.h index 21805cb515..e979cf10dd 100644 --- a/src/lib/dhcpsrv/memfile_lease_mgr.h +++ b/src/lib/dhcpsrv/memfile_lease_mgr.h @@ -1427,6 +1427,16 @@ public: /// @brief Wipe extended info table (v6). virtual void wipeExtendedInfoTables6() override; + /// @brief Return the by-relay-id table size. + /// + /// @return The size of the by-relay-id table. + virtual size_t byRelayId6size() const override; + + /// @brief Return the by-remote-id table size. + /// + /// @return The size of the by-remote-id table. + virtual size_t byRemoteId6size() const override; + private: /// @brief Returns existing IPv4 leases with a given relay-id. diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index a6aef3ad20..60f96c3e4d 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -3829,11 +3829,11 @@ MySqlLeaseMgr::deleteRelayId6(const IOAddress& addr) { std::vector addr_data = addr.toBytes(); // Do not check the address length as it does not really matter. - unsigned long addr_length = addr_data.size(); + unsigned long addr_size = addr_data.size(); bind[0].buffer_type = MYSQL_TYPE_BLOB; bind[0].buffer = reinterpret_cast(&addr_data[0]); - bind[0].buffer_length = addr_length; - bind[0].length = &addr_length; + bind[0].buffer_length = addr_size; + bind[0].length = &addr_size; // Delete from lease6_relay_id table. StatementIndex stindex = DELETE_RELAY_ID6; @@ -3859,11 +3859,11 @@ MySqlLeaseMgr::deleteRemoteId6(const IOAddress& addr) { std::vector addr_data = addr.toBytes(); // Do not check the address length as it does not really matter. - unsigned long addr_length = addr_data.size(); + unsigned long addr_size = addr_data.size(); bind[0].buffer_type = MYSQL_TYPE_BLOB; bind[0].buffer = reinterpret_cast(&addr_data[0]); - bind[0].buffer_length = addr_length; - bind[0].length = &addr_length; + bind[0].buffer_length = addr_size; + bind[0].length = &addr_size; // Delete from lease6_remote_id table. StatementIndex stindex = DELETE_REMOTE_ID6; @@ -3878,15 +3878,91 @@ MySqlLeaseMgr::deleteRemoteId6(const IOAddress& addr) { } void -MySqlLeaseMgr::addRelayId6(const IOAddress& /* lease_addr */, - const vector& /* relay_id */) { - isc_throw(NotImplemented, "MySqlLeaseMgr::addRelayId6 not implemented"); +MySqlLeaseMgr::addRelayId6(const IOAddress& lease_addr, + const vector& relay_id) { + // Get a context. + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + // Bind the relay id. + MYSQL_BIND bind[2]; + memset(bind, 0, sizeof(bind)); + + unsigned long relay_id_size = relay_id.size(); + if (relay_id_size == 0) { + isc_throw(BadValue, "empty relay id"); + } + std::vector relay_id_data = relay_id; + bind[0].buffer_type = MYSQL_TYPE_BLOB; + bind[0].buffer = reinterpret_cast(&relay_id_data[0]); + bind[0].buffer_length = relay_id_size; + bind[0].length = &relay_id_size; + + // Bind the lease address. + std::vector lease_addr_data = lease_addr.toBytes(); + unsigned long lease_addr_length = lease_addr_data.size(); + if (lease_addr_length != 16) { + isc_throw(DbOperationError, "lease6 address is not 16 byte long"); + } + bind[1].buffer_type = MYSQL_TYPE_BLOB; + bind[1].buffer = reinterpret_cast(&lease_addr_data[0]); + bind[1].buffer_length = lease_addr_length; + bind[1].length = &lease_addr_length; + + // Add to lease6_relay_id table. + StatementIndex stindex = ADD_RELAY_ID6; + + // Bind the input parameters to the statement. + int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], bind); + checkError(ctx, status, stindex, "unable to bind WHERE clause parameter"); + + // Execute. + status = MysqlExecuteStatement(ctx->conn_.statements_[stindex]); + checkError(ctx, status, stindex, "unable to execute"); } void -MySqlLeaseMgr::addRemoteId6(const IOAddress& /* lease_addr */, - const vector& /* remote_id */) { - isc_throw(NotImplemented, "MySqlLeaseMgr::addRemoteId6 not implemented"); +MySqlLeaseMgr::addRemoteId6(const IOAddress& lease_addr, + const vector& remote_id) { + // Get a context. + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + // Bind the remote id. + MYSQL_BIND bind[2]; + memset(bind, 0, sizeof(bind)); + + unsigned long remote_id_size = remote_id.size(); + if (remote_id_size == 0) { + isc_throw(BadValue, "empty remote id"); + } + std::vector remote_id_data = remote_id; + bind[0].buffer_type = MYSQL_TYPE_BLOB; + bind[0].buffer = reinterpret_cast(&remote_id_data[0]); + bind[0].buffer_length = remote_id_size; + bind[0].length = &remote_id_size; + + // Bind the lease address. + std::vector lease_addr_data = lease_addr.toBytes(); + unsigned long lease_addr_length = lease_addr_data.size(); + if (lease_addr_length != 16) { + isc_throw(DbOperationError, "lease6 address is not 16 byte long"); + } + bind[1].buffer_type = MYSQL_TYPE_BLOB; + bind[1].buffer = reinterpret_cast(&lease_addr_data[0]); + bind[1].buffer_length = lease_addr_length; + bind[1].length = &lease_addr_length; + + // Add to lease6_remote_id table. + StatementIndex stindex = ADD_REMOTE_ID6; + + // Bind the input parameters to the statement. + int status = mysql_stmt_bind_param(ctx->conn_.statements_[stindex], bind); + checkError(ctx, status, stindex, "unable to bind WHERE clause parameter"); + + // Execute. + status = MysqlExecuteStatement(ctx->conn_.statements_[stindex]); + checkError(ctx, status, stindex, "unable to execute"); } namespace { @@ -4333,7 +4409,7 @@ MySqlLeaseMgr::buildExtendedInfoTables6(bool /* update */, bool /* current */) { void MySqlLeaseMgr::wipeExtendedInfoTables6() { - // Get a context + // Get a context. MySqlLeaseContextAlloc get_context(*this); MySqlLeaseContextPtr ctx = get_context.ctx_; @@ -4350,5 +4426,71 @@ MySqlLeaseMgr::wipeExtendedInfoTables6() { } } +size_t +MySqlLeaseMgr::byRelayId6size() const { + // Get a context. + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + StatementIndex stindex = COUNT_RELAY_ID6; + + // Bind the output. + MYSQL_BIND bind[1]; + memset(bind, 0, sizeof(bind)); + + int64_t result = 0; + bind[0].buffer_type = MYSQL_TYPE_LONGLONG; + bind[0].buffer = reinterpret_cast(&result); + + int status = mysql_stmt_bind_result(ctx->conn_.statements_[stindex], &bind[0]); + checkError(ctx, status, stindex, "unable to bind SELECT clause parameters"); + + // Execute. + status = MysqlExecuteStatement(ctx->conn_.statements_[stindex]); + if (status != 0) { + checkError(ctx, status, stindex, "unable to execute"); + } + + // Fetch the result. + status = mysql_stmt_fetch(ctx->conn_.statements_[stindex]); + if (status != 0) { + checkError(ctx, status, stindex, "unable to fetch results"); + } + return(result); +} + +size_t +MySqlLeaseMgr::byRemoteId6size() const { + // Get a context. + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + StatementIndex stindex = COUNT_REMOTE_ID6; + + // Bind the output. + MYSQL_BIND bind[1]; + memset(bind, 0, sizeof(bind)); + + int64_t result = 0; + bind[0].buffer_type = MYSQL_TYPE_LONGLONG; + bind[0].buffer = reinterpret_cast(&result); + + int status = mysql_stmt_bind_result(ctx->conn_.statements_[stindex], &bind[0]); + checkError(ctx, status, stindex, "unable to bind SELECT clause parameters"); + + // Execute. + status = MysqlExecuteStatement(ctx->conn_.statements_[stindex]); + if (status != 0) { + checkError(ctx, status, stindex, "unable to execute"); + } + + // Fetch the result. + status = mysql_stmt_fetch(ctx->conn_.statements_[stindex]); + if (status != 0) { + checkError(ctx, status, stindex, "unable to fetch results"); + } + return(result); +} + } // namespace dhcp } // namespace isc diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h index 925731d292..70a2d5dd9b 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.h +++ b/src/lib/dhcpsrv/mysql_lease_mgr.h @@ -1187,6 +1187,16 @@ public: /// @brief Wipe by-relay-id table (v6). virtual void wipeExtendedInfoTables6() override; + /// @brief Return the by-relay-id table size. + /// + /// @return The size of the by-relay-id table. + virtual size_t byRelayId6size() const override; + + /// @brief Return the by-remote-id table size. + /// + /// @return The size of the by-remote-id table. + virtual size_t byRemoteId6size() const override; + private: /// @brief Context RAII allocator. class MySqlLeaseContextAlloc { diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc index 45a0ca44d4..76a626ec27 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc @@ -3042,15 +3042,81 @@ PgSqlLeaseMgr::deleteRemoteId6(const IOAddress& addr) { } void -PgSqlLeaseMgr::addRelayId6(const IOAddress& /* lease_addr */, - const vector& /* relay_id */) { - isc_throw(NotImplemented, "PgSqlLeaseMgr::addRelayId6 not implemented"); +PgSqlLeaseMgr::addRelayId6(const IOAddress& lease_addr, + const vector& relay_id) { + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the relay id. + if (relay_id.empty()) { + isc_throw(BadValue, "empty relay id"); + } + bind_array.add(relay_id); + + // Bind the lease address. + std::vector lease_addr_data = lease_addr.toBytes(); + if (lease_addr_data.size() != 16) { + isc_throw(DbOperationError, "lease6 address is not 16 byte long"); + } + bind_array.add(lease_addr_data); + + // Get a context. + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx = get_context.ctx_; + + // Add to lease6_remote_id table. + StatementIndex stindex = ADD_RELAY_ID6; + + PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name, + tagged_statements[stindex].nbparams, + &bind_array.values_[0], + &bind_array.lengths_[0], + &bind_array.formats_[0], 0)); + + int s = PQresultStatus(r); + + if (s != PGRES_COMMAND_OK) { + ctx->conn_.checkStatementError(r, tagged_statements[stindex]); + } } void -PgSqlLeaseMgr::addRemoteId6(const IOAddress& /* lease_addr */, - const vector& /* remote_id */) { - isc_throw(NotImplemented, "PgSqlLeaseMgr::addRemoteId6 not implemented"); +PgSqlLeaseMgr::addRemoteId6(const IOAddress& lease_addr, + const vector& remote_id) { + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the remote id. + if (remote_id.empty()) { + isc_throw(BadValue, "empty remote id"); + } + bind_array.add(remote_id); + + // Bind the lease address. + std::vector lease_addr_data = lease_addr.toBytes(); + if (lease_addr_data.size() != 16) { + isc_throw(DbOperationError, "lease6 address is not 16 byte long"); + } + bind_array.add(lease_addr_data); + + // Get a context. + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx = get_context.ctx_; + + // Add to lease6_remote_id table. + StatementIndex stindex = ADD_REMOTE_ID6; + + PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name, + tagged_statements[stindex].nbparams, + &bind_array.values_[0], + &bind_array.lengths_[0], + &bind_array.formats_[0], 0)); + + int s = PQresultStatus(r); + + if (s != PGRES_COMMAND_OK) { + ctx->conn_.checkStatementError(r, tagged_statements[stindex]); + } } namespace { @@ -3450,5 +3516,37 @@ PgSqlLeaseMgr::wipeExtendedInfoTables6() { ctx->conn_.checkStatementError(r2, tagged_statements[stindex2]); } +size_t +PgSqlLeaseMgr::byRelayId6size() const { + // Get a context. + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx(get_context.ctx_); + + // Execute COUNT_RELAY_ID6. + StatementIndex stindex = COUNT_RELAY_ID6; + PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name, + 0, 0, 0, 0, 0)); + ctx->conn_.checkStatementError(r, tagged_statements[stindex]); + uint64_t count; + PgSqlExchange::getColumnValue(r, 0, 0, count); + return (static_cast(count)); +} + +size_t +PgSqlLeaseMgr::byRemoteId6size() const { + // Get a context. + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx(get_context.ctx_); + + // Execute COUNT_REMOTE_ID6. + StatementIndex stindex = COUNT_REMOTE_ID6; + PgSqlResult r(PQexecPrepared(ctx->conn_, tagged_statements[stindex].name, + 0, 0, 0, 0, 0)); + ctx->conn_.checkStatementError(r, tagged_statements[stindex]); + uint64_t count; + PgSqlExchange::getColumnValue(r, 0, 0, count); + return (static_cast(count)); +} + } // namespace dhcp } // namespace isc diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.h b/src/lib/dhcpsrv/pgsql_lease_mgr.h index fafeebfc2e..6b333e0ba2 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.h +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.h @@ -1141,6 +1141,16 @@ public: /// @brief Wipe extended info table (v6). virtual void wipeExtendedInfoTables6() override; + /// @brief Return the by-relay-id table size. + /// + /// @return The size of the by-relay-id table. + virtual size_t byRelayId6size() const override; + + /// @brief Return the by-remote-id table size. + /// + /// @return The size of the by-remote-id table. + virtual size_t byRemoteId6size() const override; + /// @brief Write V4 leases to a file. virtual void writeLeases4(const std::string& /*filename*/) override;