diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.cc b/src/lib/dhcpsrv/dhcpsrv_messages.cc index 46cfcd4808..006aa4d8b7 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.cc +++ b/src/lib/dhcpsrv/dhcpsrv_messages.cc @@ -172,7 +172,9 @@ extern const isc::log::MessageID DHCPSRV_MYSQL_GET_LINKADDR6 = "DHCPSRV_MYSQL_GE extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE4 = "DHCPSRV_MYSQL_GET_PAGE4"; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE6 = "DHCPSRV_MYSQL_GET_PAGE6"; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID4 = "DHCPSRV_MYSQL_GET_RELAYID4"; +extern const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID6 = "DHCPSRV_MYSQL_GET_RELAYID6"; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_REMOTEID4 = "DHCPSRV_MYSQL_GET_REMOTEID4"; +extern const isc::log::MessageID DHCPSRV_MYSQL_GET_REMOTEID6 = "DHCPSRV_MYSQL_GET_REMOTEID6"; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID4 = "DHCPSRV_MYSQL_GET_SUBID4"; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID6 = "DHCPSRV_MYSQL_GET_SUBID6"; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID_CLIENTID = "DHCPSRV_MYSQL_GET_SUBID_CLIENTID"; @@ -230,7 +232,9 @@ extern const isc::log::MessageID DHCPSRV_PGSQL_GET_LINKADDR6 = "DHCPSRV_PGSQL_GE extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE4 = "DHCPSRV_PGSQL_GET_PAGE4"; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE6 = "DHCPSRV_PGSQL_GET_PAGE6"; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID4 = "DHCPSRV_PGSQL_GET_RELAYID4"; +extern const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID6 = "DHCPSRV_PGSQL_GET_RELAYID6"; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_REMOTEID4 = "DHCPSRV_PGSQL_GET_REMOTEID4"; +extern const isc::log::MessageID DHCPSRV_PGSQL_GET_REMOTEID6 = "DHCPSRV_PGSQL_GET_REMOTEID6"; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID4 = "DHCPSRV_PGSQL_GET_SUBID4"; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID6 = "DHCPSRV_PGSQL_GET_SUBID6"; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_CLIENTID = "DHCPSRV_PGSQL_GET_SUBID_CLIENTID"; @@ -452,7 +456,9 @@ const char* values[] = { "DHCPSRV_MYSQL_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2", "DHCPSRV_MYSQL_GET_PAGE6", "obtaining at most %1 IPv6 leases starting from address %2", "DHCPSRV_MYSQL_GET_RELAYID4", "obtaining at most %1 IPv4 leases starting from address %2 with relay id %3 and cltt between %4 and %5", + "DHCPSRV_MYSQL_GET_RELAYID6", "obtaining at most %1 IPv6 leases starting from address %2 with relay id %3 and link %4/%5", "DHCPSRV_MYSQL_GET_REMOTEID4", "obtaining at most %1 IPv4 leases starting from address %2 with remote id %3 and cltt between %4 and %5", + "DHCPSRV_MYSQL_GET_REMOTEID6", "obtaining at most %1 IPv6 leases starting from address %2 with remote id %3 and link %4/%5", "DHCPSRV_MYSQL_GET_SUBID4", "obtaining IPv4 leases for subnet ID %1", "DHCPSRV_MYSQL_GET_SUBID6", "obtaining IPv6 leases for subnet ID %1", "DHCPSRV_MYSQL_GET_SUBID_CLIENTID", "obtaining IPv4 lease for subnet ID %1 and client ID %2", @@ -510,7 +516,9 @@ const char* values[] = { "DHCPSRV_PGSQL_GET_PAGE4", "obtaining at most %1 IPv4 leases starting from address %2", "DHCPSRV_PGSQL_GET_PAGE6", "obtaining at most %1 IPv6 leases starting from address %2", "DHCPSRV_PGSQL_GET_RELAYID4", "obtaining at most %1 IPv4 leases starting from address %2 with relay id %3 and cltt between %4 and %5", + "DHCPSRV_PGSQL_GET_RELAYID6", "obtaining at most %1 IPv6 leases starting from address %2 with relay id %3 and link %4/%5", "DHCPSRV_PGSQL_GET_REMOTEID4", "obtaining at most %1 IPv4 leases starting from address %2 with remote id %3 and cltt between %4 and %5", + "DHCPSRV_PGSQL_GET_REMOTEID6", "obtaining at most %1 IPv6 leases starting from address %2 with remote id %3 and link %4/%5", "DHCPSRV_PGSQL_GET_SUBID4", "obtaining IPv4 leases for subnet ID %1", "DHCPSRV_PGSQL_GET_SUBID6", "obtaining IPv6 leases for subnet ID %1", "DHCPSRV_PGSQL_GET_SUBID_CLIENTID", "obtaining IPv4 lease for subnet ID %1 and client ID %2", diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.h b/src/lib/dhcpsrv/dhcpsrv_messages.h index 0f4f6340ea..e4e7124e31 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.h +++ b/src/lib/dhcpsrv/dhcpsrv_messages.h @@ -173,7 +173,9 @@ extern const isc::log::MessageID DHCPSRV_MYSQL_GET_LINKADDR6; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE4; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_PAGE6; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID4; +extern const isc::log::MessageID DHCPSRV_MYSQL_GET_RELAYID6; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_REMOTEID4; +extern const isc::log::MessageID DHCPSRV_MYSQL_GET_REMOTEID6; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID4; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID6; extern const isc::log::MessageID DHCPSRV_MYSQL_GET_SUBID_CLIENTID; @@ -231,7 +233,9 @@ extern const isc::log::MessageID DHCPSRV_PGSQL_GET_LINKADDR6; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE4; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_PAGE6; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID4; +extern const isc::log::MessageID DHCPSRV_PGSQL_GET_RELAYID6; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_REMOTEID4; +extern const isc::log::MessageID DHCPSRV_PGSQL_GET_REMOTEID6; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID4; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID6; extern const isc::log::MessageID DHCPSRV_PGSQL_GET_SUBID_CLIENTID; diff --git a/src/lib/dhcpsrv/dhcpsrv_messages.mes b/src/lib/dhcpsrv/dhcpsrv_messages.mes index 1382380c21..04128491a5 100644 --- a/src/lib/dhcpsrv/dhcpsrv_messages.mes +++ b/src/lib/dhcpsrv/dhcpsrv_messages.mes @@ -885,11 +885,19 @@ A debug message issued when the server is attempting to obtain a page of IPv4 leases beginning with the specified address with a relay id and client transaction time between start and end dates. +% DHCPSRV_MYSQL_GET_RELAYID6 obtaining at most %1 IPv6 leases starting from address %2 with relay id %3 and link %4/%5 +A debug message issued when the server is attempting to obtain a page of +IPv6 leases beginning with the specified address with a relay id and a link. + % DHCPSRV_MYSQL_GET_REMOTEID4 obtaining at most %1 IPv4 leases starting from address %2 with remote id %3 and cltt between %4 and %5 A debug message issued when the server is attempting to obtain a page of IPv4 leases beginning with the specified address with a remote id and client transaction time between start and end dates. +% DHCPSRV_MYSQL_GET_REMOTEID6 obtaining at most %1 IPv6 leases starting from address %2 with remote id %3 and link %4/%5 +A debug message issued when the server is attempting to obtain a page of +IPv6 leases beginning with the specified address with a remote id and a link. + % DHCPSRV_MYSQL_GET_SUBID4 obtaining IPv4 leases for subnet ID %1 A debug message issued when the server is attempting to obtain all IPv4 leases for a given subnet identifier from the MySQL database. @@ -1157,11 +1165,19 @@ A debug message issued when the server is attempting to obtain a page of IPv4 leases beginning with the specified address with a relay id and client transaction time between start and end dates. +% DHCPSRV_PGSQL_GET_RELAYID6 obtaining at most %1 IPv6 leases starting from address %2 with relay id %3 and link %4/%5 +A debug message issued when the server is attempting to obtain a page of +IPv6 leases beginning with the specified address with a relay id and a link. + % DHCPSRV_PGSQL_GET_REMOTEID4 obtaining at most %1 IPv4 leases starting from address %2 with remote id %3 and cltt between %4 and %5 A debug message issued when the server is attempting to obtain a page of IPv4 leases beginning with the specified address with a remote id and client transaction time between start and end dates. +% DHCPSRV_PGSQL_GET_REMOTEID6 obtaining at most %1 IPv6 leases starting from address %2 with remote id %3 and link %4/%5 +A debug message issued when the server is attempting to obtain a page of +IPv6 leases beginning with the specified address with a remote id and a link. + % DHCPSRV_PGSQL_GET_SUBID4 obtaining IPv4 leases for subnet ID %1 A debug message issued when the server is attempting to obtain all IPv4 leases for a given subnet identifier from the PostgreSQL database. diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.cc b/src/lib/dhcpsrv/mysql_lease_mgr.cc index bb16b34223..4720336569 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.cc +++ b/src/lib/dhcpsrv/mysql_lease_mgr.cc @@ -309,6 +309,15 @@ tagged_statements = { { "state, user_context, pool_id " "FROM lease6 " "WHERE address = ? AND lease_type = ?"}, + {MySqlLeaseMgr::GET_LEASE6_ADDR_ANY, + "SELECT address, duid, valid_lifetime, " + "expire, subnet_id, pref_lifetime, " + "lease_type, iaid, prefix_len, " + "fqdn_fwd, fqdn_rev, hostname, " + "hwaddr, hwtype, hwaddr_source, " + "state, user_context " + "FROM lease6 " + "WHERE address = ?"}, {MySqlLeaseMgr::GET_LEASE6_DUID_IAID, "SELECT address, duid, valid_lifetime, " "expire, subnet_id, pref_lifetime, " @@ -4354,21 +4363,335 @@ MySqlLeaseMgr::getExtendedInfo6Common(MySqlLeaseContextPtr& ctx, } Lease6Collection -MySqlLeaseMgr::getLeases6ByRelayId(const DUID& /* relay_id */, - const IOAddress& /* link_addr */, - uint8_t /* link_len */, - const IOAddress& /* lower_bound_address */, - const LeasePageSize& /* page_size */) { - isc_throw(NotImplemented, "MySqlLeaseMgr::getLeases6ByRelayId not implemented"); +MySqlLeaseMgr::getLeases6ByRelayId(const DUID& relay_id, + const IOAddress& link_addr, + uint8_t link_len, + const IOAddress& lower_bound_address, + const LeasePageSize& page_size) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_MYSQL_GET_RELAYID6) + .arg(page_size.page_size_) + .arg(lower_bound_address.toText()) + .arg(relay_id.toText()) + .arg(link_addr.toText()) + .arg(static_cast(link_len)); + + // Expecting IPv6 valid prefix and address. + if (!link_addr.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << link_addr); + } + if (link_len > 128) { + isc_throw(OutOfRange, "invalid IPv6 prefix length " + << static_cast(link_len)); + } + if (!lower_bound_address.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << lower_bound_address); + } + + std::vector relay_id_data = relay_id.getDuid(); + unsigned long relay_id_size = relay_id_data.size(); + if (relay_id_size == 0) { + isc_throw(BadValue, "empty relay id"); + } + + Lease6Collection result; + std::list addresses;; + + // Get a context. + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + if (!link_len) { + // Bind the relay id. + MYSQL_BIND bind[3]; + memset(bind, 0, sizeof(bind)); + + 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 lower bound address. + std::vector lb_addr_data = lower_bound_address.toBytes(); + unsigned long lb_addr_size = lb_addr_data.size(); + if (lb_addr_size != 16) { + isc_throw(DbOperationError, "lower bound address is not 16 byte long"); + } + bind[1].buffer_type = MYSQL_TYPE_BLOB; + bind[1].buffer = reinterpret_cast(&lb_addr_data[0]); + bind[1].buffer_length = lb_addr_size; + bind[1].length = &lb_addr_size; + + // Bind the size value. + uint32_t ps = static_cast(page_size.page_size_); + bind[2].buffer_type = MYSQL_TYPE_LONG; + bind[2].buffer = reinterpret_cast(&ps); + bind[2].is_unsigned = MLM_TRUE; + + // Get the lease addresses. + std::vector inbind(&bind[0], &bind[3]); + addresses = getExtendedInfo6Common(ctx, GET_RELAY_ID6, inbind); + } else { + const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len); + const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len); + IOAddress start_addr = lower_bound_address; + if (lower_bound_address < first_addr) { + start_addr = first_addr; + } else if (last_addr <= lower_bound_address) { + // Range was already done. + return (result); + } else { + // The lower bound address is from the last call so skip it. + start_addr = IOAddress::increase(lower_bound_address); + } + + // Bind the relay id. + MYSQL_BIND bind[4]; + memset(bind, 0, sizeof(bind)); + + 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 start address. + std::vector start_addr_data = start_addr.toBytes(); + unsigned long start_addr_size = start_addr_data.size(); + if (start_addr_size != 16) { + isc_throw(DbOperationError, "start address is not 16 byte long"); + } + bind[1].buffer_type = MYSQL_TYPE_BLOB; + bind[1].buffer = reinterpret_cast(&start_addr_data[0]); + bind[1].buffer_length = start_addr_size; + bind[1].length = &start_addr_size; + + // Bind the last address. + std::vector last_addr_data = last_addr.toBytes(); + unsigned long last_addr_size = last_addr_data.size(); + if (last_addr_size != 16) { + isc_throw(DbOperationError, "last address is not 16 byte long"); + } + bind[2].buffer_type = MYSQL_TYPE_BLOB; + bind[2].buffer = reinterpret_cast(&last_addr_data[0]); + bind[2].buffer_length = last_addr_size; + bind[2].length = &last_addr_size; + + // Bind the size value. + uint32_t ps = static_cast(page_size.page_size_); + bind[3].buffer_type = MYSQL_TYPE_LONG; + bind[3].buffer = reinterpret_cast(&ps); + bind[3].is_unsigned = MLM_TRUE; + + // Get the lease addresses. + std::vector inbind(&bind[0], &bind[4]); + addresses = getExtendedInfo6Common(ctx, GET_RELAY_ID6_LINK, inbind); + } + + // Short cut when nothing was found. + if (addresses.empty()) { + return (result); + } + + // Return all leases with matching addresses. + IOAddress last_addr = lower_bound_address; + for (const IOAddress& addr : addresses) { + if (addr == last_addr) { + // Already seen: skip it. + continue; + } + last_addr = addr; + + // Set up the WHERE clause value. + MYSQL_BIND inbind[1]; + memset(inbind, 0, sizeof(inbind)); + + // Bind the lease address. + std::string addr_data = addr.toText(); + unsigned long addr_size = addr_data.size(); + inbind[0].buffer_type = MYSQL_TYPE_STRING; + inbind[0].buffer = const_cast(addr_data.c_str()); + inbind[0].buffer_length = addr_size; + inbind[0].length = &addr_size; + + // Get the lease. + Lease6Ptr lease; + getLease(ctx, GET_LEASE6_ADDR_ANY, inbind, lease); + + if (lease) { + result.push_back(lease); + } + } + return (result); } Lease6Collection -MySqlLeaseMgr::getLeases6ByRemoteId(const OptionBuffer& /* remote_id */, - const IOAddress& /* link_addr */, - uint8_t /* link_len */, - const IOAddress& /* lower_bound_address */, - const LeasePageSize& /* page_size*/) { - isc_throw(NotImplemented, "MySqlLeaseMgr::getLeases6ByRemoteId not implemented"); +MySqlLeaseMgr::getLeases6ByRemoteId(const OptionBuffer& remote_id, + const IOAddress& link_addr, + uint8_t link_len, + const IOAddress& lower_bound_address, + const LeasePageSize& page_size) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_MYSQL_GET_REMOTEID6) + .arg(page_size.page_size_) + .arg(lower_bound_address.toText()) + .arg(idToText(remote_id)) + .arg(link_addr.toText()) + .arg(static_cast(link_len)); + + // Expecting IPv6 valid prefix and address. + if (!link_addr.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << link_addr); + } + if (link_len > 128) { + isc_throw(OutOfRange, "invalid IPv6 prefix length " + << static_cast(link_len)); + } + if (!lower_bound_address.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << lower_bound_address); + } + + std::vector remote_id_data = remote_id; + unsigned long remote_id_size = remote_id_data.size(); + if (remote_id_size == 0) { + isc_throw(BadValue, "empty remote id"); + } + + Lease6Collection result; + std::list addresses;; + + // Get a context. + MySqlLeaseContextAlloc get_context(*this); + MySqlLeaseContextPtr ctx = get_context.ctx_; + + if (!link_len) { + // Bind the remote id. + MYSQL_BIND bind[3]; + memset(bind, 0, sizeof(bind)); + + 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 lower bound address. + std::vector lb_addr_data = lower_bound_address.toBytes(); + unsigned long lb_addr_size = lb_addr_data.size(); + if (lb_addr_size != 16) { + isc_throw(DbOperationError, "lower bound address is not 16 byte long"); + } + bind[1].buffer_type = MYSQL_TYPE_BLOB; + bind[1].buffer = reinterpret_cast(&lb_addr_data[0]); + bind[1].buffer_length = lb_addr_size; + bind[1].length = &lb_addr_size; + + // Bind the size value. + uint32_t ps = static_cast(page_size.page_size_); + bind[2].buffer_type = MYSQL_TYPE_LONG; + bind[2].buffer = reinterpret_cast(&ps); + bind[2].is_unsigned = MLM_TRUE; + + // Get the lease addresses. + std::vector inbind(&bind[0], &bind[3]); + addresses = getExtendedInfo6Common(ctx, GET_REMOTE_ID6, inbind); + } else { + const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len); + const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len); + IOAddress start_addr = lower_bound_address; + if (lower_bound_address < first_addr) { + start_addr = first_addr; + } else if (last_addr <= lower_bound_address) { + // Range was already done. + return (result); + } else { + // The lower bound address is from the last call so skip it. + start_addr = IOAddress::increase(lower_bound_address); + } + + // Bind the remote id. + MYSQL_BIND bind[4]; + memset(bind, 0, sizeof(bind)); + + 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 start address. + std::vector start_addr_data = start_addr.toBytes(); + unsigned long start_addr_size = start_addr_data.size(); + if (start_addr_size != 16) { + isc_throw(DbOperationError, "start address is not 16 byte long"); + } + bind[1].buffer_type = MYSQL_TYPE_BLOB; + bind[1].buffer = reinterpret_cast(&start_addr_data[0]); + bind[1].buffer_length = start_addr_size; + bind[1].length = &start_addr_size; + + // Bind the last address. + std::vector last_addr_data = last_addr.toBytes(); + unsigned long last_addr_size = last_addr_data.size(); + if (last_addr_size != 16) { + isc_throw(DbOperationError, "last address is not 16 byte long"); + } + bind[2].buffer_type = MYSQL_TYPE_BLOB; + bind[2].buffer = reinterpret_cast(&last_addr_data[0]); + bind[2].buffer_length = last_addr_size; + bind[2].length = &last_addr_size; + + // Bind the size value. + uint32_t ps = static_cast(page_size.page_size_); + bind[3].buffer_type = MYSQL_TYPE_LONG; + bind[3].buffer = reinterpret_cast(&ps); + bind[3].is_unsigned = MLM_TRUE; + + // Get the lease addresses. + std::vector inbind(&bind[0], &bind[4]); + addresses = getExtendedInfo6Common(ctx, GET_REMOTE_ID6_LINK, inbind); + } + + // Short cut when nothing was found. + if (addresses.empty()) { + return (result); + } + + // Return all leases with matching addresses. + IOAddress last_addr = lower_bound_address; + for (const IOAddress& addr : addresses) { + if (addr == last_addr) { + // Already seen: skip it. + continue; + } + last_addr = addr; + + // Set up the WHERE clause value. + MYSQL_BIND inbind[1]; + memset(inbind, 0, sizeof(inbind)); + + // Bind the lease address. + std::string addr_data = addr.toText(); + unsigned long addr_size = addr_data.size(); + inbind[0].buffer_type = MYSQL_TYPE_STRING; + inbind[0].buffer = const_cast(addr_data.c_str()); + inbind[0].buffer_length = addr_size; + inbind[0].length = &addr_size; + + // Get the lease. + Lease6Ptr lease; + getLease(ctx, GET_LEASE6_ADDR_ANY, inbind, lease); + + if (lease) { + result.push_back(lease); + } + } + return (result); } Lease6Collection diff --git a/src/lib/dhcpsrv/mysql_lease_mgr.h b/src/lib/dhcpsrv/mysql_lease_mgr.h index e080f8863c..afa18833d5 100644 --- a/src/lib/dhcpsrv/mysql_lease_mgr.h +++ b/src/lib/dhcpsrv/mysql_lease_mgr.h @@ -741,7 +741,8 @@ public: GET_LEASE4_REMOTEID_QSET, // Get page of leases by remote ID and query start and end times. GET_LEASE4_REMOTEID_QET, // Get page of leases by remote ID and query end time. GET_LEASE6, // Get all IPv6 leases - GET_LEASE6_ADDR, // Get lease6 by address + GET_LEASE6_ADDR, // Get lease6 by address and type + GET_LEASE6_ADDR_ANY, // Get lease6 by address GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID GET_LEASE6_PAGE, // Get page of leases beginning with an address diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.cc b/src/lib/dhcpsrv/pgsql_lease_mgr.cc index a872930679..c852186e42 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.cc +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.cc @@ -312,6 +312,17 @@ PgSqlTaggedStatement tagged_statements[] = { "FROM lease6 " "WHERE address = cast($1 as inet) AND lease_type = $2"}, + // GET_LEASE6_ADDR_ANY + { 1, { OID_VARCHAR }, + "get_lease6_addr_nay", + "SELECT address, duid, valid_lifetime, " + "extract(epoch from expire)::bigint, subnet_id, pref_lifetime, " + "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, " + "hwaddr, hwtype, hwaddr_source, " + "state, user_context " + "FROM lease6 " + "WHERE address = $1"}, + // GET_LEASE6_DUID_IAID { 3, { OID_BYTEA, OID_INT8, OID_INT2 }, "get_lease6_duid_iaid", @@ -3429,21 +3440,274 @@ PgSqlLeaseMgr::getExtendedInfo6Common(PgSqlLeaseContextPtr& ctx, } Lease6Collection -PgSqlLeaseMgr::getLeases6ByRelayId(const DUID& /* relay_id */, - const IOAddress& /* link_addr */, - uint8_t /* link_len */, - const IOAddress& /* lower_bound_address */, - const LeasePageSize& /* page_size */) { - isc_throw(NotImplemented, "PgSqlLeaseMgr::getLeases6ByRelayId not implemented"); +PgSqlLeaseMgr::getLeases6ByRelayId(const DUID& relay_id, + const IOAddress& link_addr, + uint8_t link_len, + const IOAddress& lower_bound_address, + const LeasePageSize& page_size) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_PGSQL_GET_RELAYID6) + .arg(page_size.page_size_) + .arg(lower_bound_address.toText()) + .arg(relay_id.toText()) + .arg(link_addr.toText()) + .arg(static_cast(link_len)); + + // Expecting IPv6 valid prefix and address. + if (!link_addr.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << link_addr); + } + if (link_len > 128) { + isc_throw(OutOfRange, "invalid IPv6 prefix length " + << static_cast(link_len)); + } + if (!lower_bound_address.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << lower_bound_address); + } + + std::vector relay_id_data = relay_id.getDuid(); + if (relay_id_data.size() == 0) { + isc_throw(BadValue, "empty relay id"); + } + + Lease6Collection result; + std::list addresses;; + + // Get a context. + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx = get_context.ctx_; + + if (!link_len) { + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the relay id. + bind_array.add(relay_id_data); + + // Bind the lower bound address. + std::vector lb_addr_data = lower_bound_address.toBytes(); + if (lb_addr_data.size() != 16) { + isc_throw(DbOperationError, "lower bound address is not 16 byte long"); + } + bind_array.add(lb_addr_data); + + // Bind page size value. + std::string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array.add(page_size_data); + + addresses = getExtendedInfo6Common(ctx, GET_RELAY_ID6, bind_array); + } else { + const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len); + const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len); + IOAddress start_addr = lower_bound_address; + if (lower_bound_address < first_addr) { + start_addr = first_addr; + } else if (last_addr <= lower_bound_address) { + // Range was already done. + return (result); + } else { + // The lower bound address is from the last call so skip it. + start_addr = IOAddress::increase(lower_bound_address); + } + + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the relay id. + bind_array.add(relay_id_data); + + // Bind the start address. + std::vector start_addr_data = start_addr.toBytes(); + if (start_addr_data.size() != 16) { + isc_throw(DbOperationError, "start address is not 16 byte long"); + } + bind_array.add(start_addr_data); + + // Bind the last address. + std::vector last_addr_data = last_addr.toBytes(); + if (last_addr_data.size() != 16) { + isc_throw(DbOperationError, "last address is not 16 byte long"); + } + bind_array.add(last_addr_data); + + // Bind page size value. + std::string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array.add(page_size_data); + + addresses = getExtendedInfo6Common(ctx, GET_RELAY_ID6_LINK, bind_array); + } + + // Short cut when nothing was found. + if (addresses.empty()) { + return (result); + } + + // Return all leases with matching addresses. + IOAddress last_addr = lower_bound_address; + for (const IOAddress& addr : addresses) { + if (addr == last_addr) { + // Already seen: skip it. + continue; + } + last_addr = addr; + + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the lease address. + std::vector addr_data = addr.toBytes(); + bind_array.add(addr_data); + + // Get the lease. + Lease6Ptr lease; + getLease(ctx, GET_LEASE6_ADDR_ANY, bind_array, lease); + + if (lease) { + result.push_back(lease); + } + } + return (result); } Lease6Collection -PgSqlLeaseMgr::getLeases6ByRemoteId(const OptionBuffer& /* remote_id */, - const IOAddress& /* link_addr */, - uint8_t /* link_len */, - const IOAddress& /* lower_bound_address */, - const LeasePageSize& /* page_size*/) { - isc_throw(NotImplemented, "PgSqlLeaseMgr::getLeases6ByRemoteId not implemented"); +PgSqlLeaseMgr::getLeases6ByRemoteId(const OptionBuffer& remote_id, + const IOAddress& link_addr, + uint8_t link_len, + const IOAddress& lower_bound_address, + const LeasePageSize& page_size) { + LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, + DHCPSRV_PGSQL_GET_REMOTEID6) + .arg(page_size.page_size_) + .arg(lower_bound_address.toText()) + .arg(idToText(remote_id)) + .arg(link_addr.toText()) + .arg(static_cast(link_len)); + + // Expecting IPv6 valid prefix and address. + if (!link_addr.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << link_addr); + } + if (link_len > 128) { + isc_throw(OutOfRange, "invalid IPv6 prefix length " + << static_cast(link_len)); + } + if (!lower_bound_address.isV6()) { + isc_throw(InvalidAddressFamily, "expected IPv6 address while " + "retrieving leases from the lease database, got " + << lower_bound_address); + } + + if (remote_id.size() == 0) { + isc_throw(BadValue, "empty remote id"); + } + + Lease6Collection result; + std::list addresses;; + + // Get a context. + PgSqlLeaseContextAlloc get_context(*this); + PgSqlLeaseContextPtr ctx = get_context.ctx_; + + if (!link_len) { + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the remote id. + bind_array.add(remote_id); + + // Bind the lower bound address. + std::vector lb_addr_data = lower_bound_address.toBytes(); + if (lb_addr_data.size() != 16) { + isc_throw(DbOperationError, "lower bound address is not 16 byte long"); + } + bind_array.add(lb_addr_data); + + // Bind page size value. + std::string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array.add(page_size_data); + + addresses = getExtendedInfo6Common(ctx, GET_REMOTE_ID6, bind_array); + } else { + const IOAddress& first_addr = firstAddrInPrefix(link_addr, link_len); + const IOAddress& last_addr = lastAddrInPrefix(link_addr, link_len); + IOAddress start_addr = lower_bound_address; + if (lower_bound_address < first_addr) { + start_addr = first_addr; + } else if (last_addr <= lower_bound_address) { + // Range was already done. + return (result); + } else { + // The lower bound address is from the last call so skip it. + start_addr = IOAddress::increase(lower_bound_address); + } + + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the remote id. + bind_array.add(remote_id); + + // Bind the start address. + std::vector start_addr_data = start_addr.toBytes(); + if (start_addr_data.size() != 16) { + isc_throw(DbOperationError, "start address is not 16 byte long"); + } + bind_array.add(start_addr_data); + + // Bind the last address. + std::vector last_addr_data = last_addr.toBytes(); + if (last_addr_data.size() != 16) { + isc_throw(DbOperationError, "last address is not 16 byte long"); + } + bind_array.add(last_addr_data); + + // Bind page size value. + std::string page_size_data = + boost::lexical_cast(page_size.page_size_); + bind_array.add(page_size_data); + + addresses = getExtendedInfo6Common(ctx, GET_REMOTE_ID6_LINK, bind_array); + } + + // Short cut when nothing was found. + if (addresses.empty()) { + return (result); + } + + // Return all leases with matching addresses. + IOAddress last_addr = lower_bound_address; + for (const IOAddress& addr : addresses) { + if (addr == last_addr) { + // Already seen: skip it. + continue; + } + last_addr = addr; + + // Set up the WHERE clause value. + PsqlBindArray bind_array; + + // Bind the lease address. + std::vector addr_data = addr.toBytes(); + bind_array.add(addr_data); + + // Get the lease. + Lease6Ptr lease; + getLease(ctx, GET_LEASE6_ADDR_ANY, bind_array, lease); + + if (lease) { + result.push_back(lease); + } + } + return (result); } Lease6Collection diff --git a/src/lib/dhcpsrv/pgsql_lease_mgr.h b/src/lib/dhcpsrv/pgsql_lease_mgr.h index 7f0c3c6bc0..b320a63ec9 100644 --- a/src/lib/dhcpsrv/pgsql_lease_mgr.h +++ b/src/lib/dhcpsrv/pgsql_lease_mgr.h @@ -717,7 +717,8 @@ public: GET_LEASE4_REMOTEID_QSET, // Get page of leases by remote ID and query start and end times. GET_LEASE4_REMOTEID_QET, // Get page of leases by remote ID and query end time. GET_LEASE6, // Get all IPv6 leases - GET_LEASE6_ADDR, // Get lease6 by address + GET_LEASE6_ADDR, // Get lease6 by address and type + GET_LEASE6_ADDR_ANY, // Get lease6 by address GET_LEASE6_DUID_IAID, // Get lease6 by DUID and IAID GET_LEASE6_DUID_IAID_SUBID, // Get lease6 by DUID, IAID and subnet ID GET_LEASE6_PAGE, // Get page of leases beginning with an address