]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2869] Implemented getByR*Id6
authorFrancis Dupont <fdupont@isc.org>
Thu, 25 May 2023 16:46:47 +0000 (18:46 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 6 Jul 2023 20:11:32 +0000 (22:11 +0200)
src/lib/dhcpsrv/dhcpsrv_messages.cc
src/lib/dhcpsrv/dhcpsrv_messages.h
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/mysql_lease_mgr.h
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/pgsql_lease_mgr.h

index 46cfcd48085321d3ff950f13519c9dc66fdcdc5f..006aa4d8b73a8a6cc19b181d5077e2a04a5670de 100644 (file)
@@ -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",
index 0f4f6340eaa16b2c40473ecd163481163bac147b..e4e7124e31f27bdb26a5d3eb9660fe77f5f2b39d 100644 (file)
@@ -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;
index 1382380c214bbb5a82fabf743b14018f90eca191..04128491a53b0db70f9abb9ba0718747913e0e6b 100644 (file)
@@ -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.
index bb16b3422367c9a88c843aff655e41ceb7e54c17..47203365691dbc1927e73b31b98e05f3dcfe1880 100644 (file)
@@ -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<unsigned>(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<unsigned>(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<uint8_t> 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<IOAddress> 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<char*>(&relay_id_data[0]);
+        bind[0].buffer_length = relay_id_size;
+        bind[0].length = &relay_id_size;
+
+        // Bind the lower bound address.
+        std::vector<uint8_t> 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<char*>(&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<uint32_t>(page_size.page_size_);
+        bind[2].buffer_type = MYSQL_TYPE_LONG;
+        bind[2].buffer = reinterpret_cast<char*>(&ps);
+        bind[2].is_unsigned = MLM_TRUE;
+
+        // Get the lease addresses.
+        std::vector<MYSQL_BIND> 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<char*>(&relay_id_data[0]);
+        bind[0].buffer_length = relay_id_size;
+        bind[0].length = &relay_id_size;
+
+        // Bind the start address.
+        std::vector<uint8_t> 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<char*>(&start_addr_data[0]);
+        bind[1].buffer_length = start_addr_size;
+        bind[1].length = &start_addr_size;
+
+        // Bind the last address.
+        std::vector<uint8_t> 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<char*>(&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<uint32_t>(page_size.page_size_);
+        bind[3].buffer_type = MYSQL_TYPE_LONG;
+        bind[3].buffer = reinterpret_cast<char*>(&ps);
+        bind[3].is_unsigned = MLM_TRUE;
+
+        // Get the lease addresses.
+        std::vector<MYSQL_BIND> 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<char*>(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<unsigned>(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<unsigned>(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<uint8_t> 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<IOAddress> 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<char*>(&remote_id_data[0]);
+        bind[0].buffer_length = remote_id_size;
+        bind[0].length = &remote_id_size;
+
+        // Bind the lower bound address.
+        std::vector<uint8_t> 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<char*>(&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<uint32_t>(page_size.page_size_);
+        bind[2].buffer_type = MYSQL_TYPE_LONG;
+        bind[2].buffer = reinterpret_cast<char*>(&ps);
+        bind[2].is_unsigned = MLM_TRUE;
+
+        // Get the lease addresses.
+        std::vector<MYSQL_BIND> 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<char*>(&remote_id_data[0]);
+        bind[0].buffer_length = remote_id_size;
+        bind[0].length = &remote_id_size;
+
+        // Bind the start address.
+        std::vector<uint8_t> 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<char*>(&start_addr_data[0]);
+        bind[1].buffer_length = start_addr_size;
+        bind[1].length = &start_addr_size;
+
+        // Bind the last address.
+        std::vector<uint8_t> 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<char*>(&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<uint32_t>(page_size.page_size_);
+        bind[3].buffer_type = MYSQL_TYPE_LONG;
+        bind[3].buffer = reinterpret_cast<char*>(&ps);
+        bind[3].is_unsigned = MLM_TRUE;
+
+        // Get the lease addresses.
+        std::vector<MYSQL_BIND> 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<char*>(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
index e080f8863cd0524aa284080de3d3aad171fc040c..afa18833d5b6eac94555e06761f6bd2059599ec3 100644 (file)
@@ -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
index a87293067999bb5510c088850e69c351cb0bd9b9..c852186e42492ab5af3516e6793d5d842f61b6f1 100644 (file)
@@ -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<unsigned>(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<unsigned>(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<uint8_t> relay_id_data = relay_id.getDuid();
+    if (relay_id_data.size() == 0) {
+        isc_throw(BadValue, "empty relay id");
+    }
+
+    Lease6Collection result;
+    std::list<IOAddress> 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<uint8_t> 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<std::string>(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<uint8_t> 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<uint8_t> 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<std::string>(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<uint8_t> 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<unsigned>(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<unsigned>(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<IOAddress> 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<uint8_t> 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<std::string>(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<uint8_t> 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<uint8_t> 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<std::string>(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<uint8_t> 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
index 7f0c3c6bc072699788db4cdedb5f21a59a84085a..b320a63ec987296176c92eb4a6ae53bf546b78ba 100644 (file)
@@ -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