]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[94-cb-implement-mysqlconfigbackenddhcpv6-prepare] Adapted code for DHCPv6 support...
authorFrancis Dupont <fdupont@isc.org>
Sat, 9 Feb 2019 22:55:37 +0000 (23:55 +0100)
committerFrancis Dupont <fdupont@isc.org>
Fri, 22 Feb 2019 22:59:25 +0000 (17:59 -0500)
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.cc
src/hooks/dhcp/mysql_cb/mysql_cb_impl.h
src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h
src/hooks/dhcp/mysql_cb/tests/mysql_cb_impl_unittest.cc
src/lib/config_backend/constants.h

index 5d6cae5e2888b35d5f6c48df661bd8f7fed4eb29..c9106e616fa0bba0852f2ea3d105a4bdbb919de1 100644 (file)
 #include <utility>
 #include <vector>
 
+// Specialize macros for DHCPv4
+
+#define MYSQL_GET_OPTION(table_prefix, ...) \
+    MYSQL_GET_OPTION_COMMON(table_prefix, "", __VA_ARGS__)
+
+#define MYSQL_INSERT_OPTION(table_prefix) \
+    MYSQL_INSERT_OPTION_COMMON(table_prefix, "", "")
+
+#define MYSQL_UPDATE_OPTION(table_prefix, ...) \
+    MYSQL_UPDATE_OPTION_COMMON(table_prefix, "", __VA_ARGS__)
+
 using namespace isc::cb;
 using namespace isc::db;
 using namespace isc::data;
@@ -273,7 +284,7 @@ public:
         // statement.
         MySqlBindingCollection out_bindings = {
             MySqlBinding::createInteger<uint32_t>(), // subnet_id
-            MySqlBinding::createString(SUBNET_PREFIX_BUF_LENGTH), // subnet_prefix
+            MySqlBinding::createString(SUBNET4_PREFIX_BUF_LENGTH), // subnet_prefix
             MySqlBinding::createString(DHCP4O6_INTERFACE_BUF_LENGTH), // 4o6_interface
             MySqlBinding::createString(DHCP4O6_INTERFACE_ID_BUF_LENGTH), // 4o6_interface_id
             MySqlBinding::createString(DHCP4O6_SUBNET_BUF_LENGTH), // 4o6_subnet
@@ -1056,7 +1067,7 @@ public:
                 if (require_element) {
                     if (require_element->getType() != Element::list) {
                         isc_throw(BadValue, "invalid require_client_classes value "
-                              << out_bindings[14]->getString());
+                              << out_bindings[9]->getString());
                     }
                     for (auto i = 0; i < require_element->size(); ++i) {
                         auto require_item = require_element->get(i);
@@ -1918,7 +1929,7 @@ public:
                               const std::string& space) {
 
         MySqlBindingCollection in_bindings = {
-            MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>(code)),
+            MySqlBinding::createInteger<uint16_t>(code),
             MySqlBinding::createString(space)
         };
 
index 39a2d719307876cacdace6e80807bfdef748a7e2..53e5d5e1c4df63486c9e7f8e995334419dab4799 100644 (file)
@@ -287,19 +287,35 @@ MySqlConfigBackendImpl::getOptions(const int index,
     // statement.
     MySqlBindingCollection out_bindings = {
         MySqlBinding::createInteger<uint64_t>(), // option_id
-        MySqlBinding::createInteger<uint8_t>(), // code
+        // code will go here.
         MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // value
         MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // formatted_value
         MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // space
         MySqlBinding::createInteger<uint8_t>(), // persistent
-        MySqlBinding::createInteger<uint32_t>(), // dhcp4_subnet_id
+        MySqlBinding::createInteger<uint32_t>(), // dhcp[46]_subnet_id
         MySqlBinding::createInteger<uint8_t>(), // scope_id
         MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
         MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // shared_network_name
         MySqlBinding::createInteger<uint64_t>(), // pool_id
-        MySqlBinding::createTimestamp() //modification_ts
+        // pd_pool_id in DHCPv6
+        MySqlBinding::createTimestamp() // modification_ts
     };
 
+    // Insert code in the second position.
+    if (universe == Option::V4) {
+        out_bindings.insert(out_bindings.begin() + 1,
+                            MySqlBinding::createInteger<uint8_t>());
+    } else {
+        out_bindings.insert(out_bindings.begin() + 1,
+                            MySqlBinding::createInteger<uint16_t>());
+    }
+
+    // Insert pd_pool_id before the modification_ts / last field
+    if (universe == Option::V6) {
+        out_bindings.insert(out_bindings.end() - 1,
+                            MySqlBinding::createInteger<uint64_t>());
+    }
+
     uint64_t last_option_id = 0;
 
     conn_.selectQuery(index, in_bindings, out_bindings,
@@ -328,7 +344,12 @@ MySqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
     // first thing to do is to see if there is a definition for our
     // parsed option. The option code and space is needed for it.
     std::string space = (*(first_binding + 4))->getString();
-    uint16_t code = (*(first_binding + 1))->getInteger<uint8_t>();
+    uint16_t code;
+    if (universe == Option::V4) {
+        code = (*(first_binding + 1))->getInteger<uint8_t>();
+    } else {
+        code = (*(first_binding + 1))->getInteger<uint16_t>();
+    }
 
     // See if the option has standard definition.
     OptionDefinitionPtr def = LibDHCP::getOptionDef(space, code);
@@ -385,7 +406,10 @@ MySqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
     // its option space and timestamp.
     OptionDescriptorPtr desc(new OptionDescriptor(option, persistent, formatted_value));
     desc->space_name_ = space;
-    desc->setModificationTime((*(first_binding + 11))->getTimestamp());
+    // In DHCPv6 the pd_pool_id field shifts the position of the
+    // modification_ts field by one.
+    size_t ts_idx = (universe == Option::V4 ? 11 : 12);
+    desc->setModificationTime((*(first_binding + ts_idx))->getTimestamp());
 
     return (desc);
 }
index f947251f69b168665d51c5f7af7fe5a23cc7c907..4650d69039455570bdb7094552fa2a7ade488fd1 100644 (file)
@@ -316,6 +316,9 @@ public:
     ///
     /// Query should order by option_id.
     ///
+    /// @note The universe is reused to switch between DHCPv4 and DHCPv6
+    /// option layouts.
+    /// @param family Address family (either AF_INET or AF_INET6).
     /// @param index Index of the query to be used.
     /// @param in_bindings Input bindings specifying selection criteria. The
     /// size of the bindings collection must match the number of placeholders
@@ -339,13 +342,16 @@ public:
     /// - formatted_value,
     /// - space,
     /// - persistent,
-    /// - dhcp4_subnet_id,
+    /// - dhcp4_subnet_id/dhcp6_subnet_id,
     /// - scope_id,
     /// - user_context,
     /// - shared_network_name,
     /// - pool_id,
+    /// - [pd_pool_id,]
     /// - modification_ts
     ///
+    /// @note The universe is reused to switch between DHCPv4 and DHCPv6
+    /// option layouts.
     /// @param universe V4 or V6.
     /// @param first_binding Iterator of the output binding containing
     /// option_id.
index bfbead612e44965277c5be7be19eae58c4033029..b5c4cbc1ed716f274c94989d5e2beaae1c4793d2 100644 (file)
@@ -111,6 +111,88 @@ namespace {
     " ORDER BY s.subnet_id, p.id, x.option_id, o.option_id"
 #endif
 
+#ifndef MYSQL_GET_SUBNET6
+#define MYSQL_GET_SUBNET6(...) \
+    "SELECT" \
+    "  s.subnet_id," \
+    "  s.subnet_prefix," \
+    "  s.client_class," \
+    "  s.interface," \
+    "  s.modification_ts," \
+    "  s.preferred_lifetime," \
+    "  s.rapid_commit," \
+    "  s.rebind_timer," \
+    "  s.relay," \
+    "  s.renew_timer," \
+    "  s.require_client_classes," \
+    "  s.reservation_mode," \
+    "  s.shared_network_name," \
+    "  s.user_context," \
+    "  s.valid_lifetime," \
+    "  p.id," \
+    "  p.start_address," \
+    "  p.end_address," \
+    "  p.subnet_id," \
+    "  p.modification_ts," \
+    "  d.id," \
+    "  d.prefix," \
+    "  d.prefix_length," \
+    "  d.delegated_prefix_length," \
+    "  d.dhcp6_subnet_id," \
+    "  d.modification_ts," \
+    "  x.option_id," \
+    "  x.code," \
+    "  x.value," \
+    "  x.formatted_value," \
+    "  x.space," \
+    "  x.persistent," \
+    "  x.dhcp6_subnet_id," \
+    "  x.scope_id," \
+    "  x.user_context," \
+    "  x.shared_network_name," \
+    "  x.pool_id," \
+    "  x.pd_pool_id," \
+    "  x.modification_ts," \
+    "  y.option_id," \
+    "  y.code," \
+    "  y.value," \
+    "  y.formatted_value," \
+    "  y.space," \
+    "  y.persistent," \
+    "  y.dhcp6_subnet_id," \
+    "  y.scope_id," \
+    "  y.user_context," \
+    "  y.shared_network_name," \
+    "  y.pool_id," \
+    "  y.pd_pool_id," \
+    "  y.modification_ts," \
+    "  o.option_id," \
+    "  o.code," \
+    "  o.value," \
+    "  o.formatted_value," \
+    "  o.space," \
+    "  o.persistent," \
+    "  o.dhcp6_subnet_id," \
+    "  o.scope_id," \
+    "  o.user_context," \
+    "  o.shared_network_name," \
+    "  o.pool_id," \
+    "  o.pd_pool_id," \
+    "  o.modification_ts " \
+    "FROM dhcp6_subnet AS s " \
+    "INNER JOIN dhcp6_subnet_server AS a " \
+    "  ON s.subnet_id = a.subnet_id " \
+    "INNER JOIN dhcp6_server AS srv " \
+    "  ON (a.server_id = srv.id) OR (a.server_id = 1) " \
+    "LEFT JOIN dhcp6_pool AS p ON s.subnet_id = p.subnet_id " \
+    "LEFT JOIN dhcp6_pd_pool AS d ON s.subnet_id = d.dhcp6_subnet_id " \
+    "LEFT JOIN dhcp6_options AS x ON x.scope_id = 5 AND p.id = x.pool_id " \
+    "LEFT JOIN dhcp6_options AS y ON y.scope_id = 6 AND d.id = y.pd_pool_id " \
+    "LEFT JOIN dhcp6_options AS o ON o.scope_id = 1 AND s.subnet_id = o.dhcp6_subnet_id " \
+    "WHERE (srv.tag = ? OR srv.id = 1) " #__VA_ARGS__ \
+    " ORDER BY s.subnet_id, p.id, x.option_id, o.option_id"
+#endif
+
 #ifndef MYSQL_GET_SHARED_NETWORK4
 #define MYSQL_GET_SHARED_NETWORK4(...) \
     "SELECT" \
@@ -149,6 +231,46 @@ namespace {
     " ORDER BY n.id, o.option_id"
 #endif
 
+#ifndef MYSQL_GET_SHARED_NETWORK6
+#define MYSQL_GET_SHARED_NETWORK6(...) \
+    "SELECT" \
+    "  n.id," \
+    "  n.name," \
+    "  n.client_class," \
+    "  n.interface," \
+    "  n.modification_ts," \
+    "  n.preferred_lifetime," \
+    "  n.rapid_commit," \
+    "  n.rebind_timer," \
+    "  n.relay," \
+    "  n.renew_timer," \
+    "  n.require_client_classes," \
+    "  n.reservation_mode," \
+    "  n.user_context," \
+    "  n.valid_lifetime," \
+    "  o.option_id," \
+    "  o.code," \
+    "  o.value," \
+    "  o.formatted_value," \
+    "  o.space," \
+    "  o.persistent," \
+    "  o.dhcp6_subnet_id," \
+    "  o.scope_id," \
+    "  o.user_context," \
+    "  o.shared_network_name," \
+    "  o.pool_id," \
+    "  o.pd_pool_id," \
+    "  o.modification_ts " \
+    "FROM dhcp6_shared_network AS n " \
+    "INNER JOIN dhcp6_shared_network_server AS a " \
+    "  ON n.id = a.shared_network_id " \
+    "INNER JOIN dhcp6_server AS s " \
+    "  ON (a.server_id = s.id) OR (a.server_id = 1) " \
+    "LEFT JOIN dhcp6_options AS o ON o.scope_id = 4 AND n.name = o.shared_network_name " \
+    "WHERE (s.tag = ? OR s.id = 1) " #__VA_ARGS__ \
+    " ORDER BY n.id, o.option_id"
+#endif
+
 #ifndef MYSQL_GET_OPTION_DEF
 #define MYSQL_GET_OPTION_DEF(table_prefix, ...) \
     "SELECT" \
@@ -171,8 +293,8 @@ namespace {
     " ORDER BY d.id"
 #endif
 
-#ifndef MYSQL_GET_OPTION
-#define MYSQL_GET_OPTION(table_prefix, ...) \
+#ifndef MYSQL_GET_OPTION_COMMON
+#define MYSQL_GET_OPTION_COMMON(table_prefix, pd_pool_id, ...) \
     "SELECT" \
     "  o.option_id," \
     "  o.code," \
@@ -180,11 +302,12 @@ namespace {
     "  o.formatted_value," \
     "  o.space," \
     "  o.persistent," \
-    "  o.dhcp4_subnet_id," \
+    "  o." #table_prefix "_subnet_id," \
     "  o.scope_id," \
     "  o.user_context," \
     "  o.shared_network_name," \
     "  o.pool_id," \
+    pd_pool_id \
     "  o.modification_ts " \
     "FROM " #table_prefix "_options AS o " \
     "INNER JOIN " #table_prefix "_options_server AS a" \
@@ -251,6 +374,17 @@ namespace {
     ") VALUES (?, ?, ?, ?)"
 #endif
 
+#ifndef MYSQL_INSERT_PD_POOL
+#define MYSQL_INSERT_PD_POOL() \
+    "INSERT INTO dhcp6_pd_pool(" \
+    "  prefix," \
+    "  prefix_length," \
+    "  delegated_prefix_length," \
+    "  dhcp6_subnet_id," \
+    "  modification_ts" \
+    ") VALUES (?, ?, ?, ?, ?)"
+#endif
+
 #ifndef MYSQL_INSERT_SHARED_NETWORK_SERVER
 #define MYSQL_INSERT_SHARED_NETWORK_SERVER(table_prefix) \
     "INSERT INTO " #table_prefix "_shared_network_server(" \
@@ -287,8 +421,8 @@ namespace {
     ") VALUES (?, (SELECT id FROM " #table_prefix "_server WHERE tag = ?), ?)"
 #endif
 
-#ifndef MYSQL_INSERT_OPTION
-#define MYSQL_INSERT_OPTION(table_prefix) \
+#ifndef MYSQL_INSERT_OPTION_COMMON
+#define MYSQL_INSERT_OPTION_COMMON(table_prefix, pd_pool_id, last) \
     "INSERT INTO " #table_prefix "_options (" \
     "  code," \
     "  value," \
@@ -301,8 +435,9 @@ namespace {
     "  user_context," \
     "  shared_network_name," \
     "  pool_id," \
+    pd_pool_id \
     "  modification_ts" \
-    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" last ")"
 #endif
 
 #ifndef MYSQL_INSERT_OPTION_SERVER
@@ -349,8 +484,8 @@ namespace {
     "WHERE s.tag = ? AND d.code = ? AND d.space = ?"
 #endif
 
-#ifndef MYSQL_UPDATE_OPTION
-#define MYSQL_UPDATE_OPTION(table_prefix, ...) \
+#ifndef MYSQL_UPDATE_OPTION_COMMON
+#define MYSQL_UPDATE_OPTION_COMMON(table_prefix, pd_pool_id, ...) \
     "UPDATE " #table_prefix "_options AS o " \
     "INNER JOIN " #table_prefix "_options_server AS a" \
     "  ON o.option_id = a.option_id " \
@@ -368,6 +503,7 @@ namespace {
     "  o.user_context = ?," \
     "  o.shared_network_name = ?," \
     "  o.pool_id = ?," \
+    pd_pool_id \
     "  o.modification_ts = ? " \
     "WHERE s.tag = ? " #__VA_ARGS__
 #endif
@@ -398,6 +534,12 @@ namespace {
     "WHERE subnet_id = ?"
 #endif
 
+#ifndef MYSQL_DELETE_PD_POOLS
+#define MYSQL_DELETE_PD_POOLS() \
+    "DELETE FROM dhcp6_pd_pool " \
+    "WHERE subnet_id = ?"
+#endif
+
 #ifndef MYSQL_DELETE_SHARED_NETWORK
 #define MYSQL_DELETE_SHARED_NETWORK(table_prefix, ...) \
     "DELETE n FROM " #table_prefix "_shared_network AS n " \
@@ -441,6 +583,19 @@ namespace {
     "   WHERE start_address = ? AND end_address = ?)"
 #endif
 
+#ifndef MYSQL_DELETE_OPTION_PD_POOL
+#define MYSQL_DELETE_OPTION_PD_POOL(...) \
+    "DELETE o FROM dhcp6_options AS o " \
+    "INNER JOIN dhcp6_options_server AS a" \
+    "  ON o.option_id = a.option_id " \
+    "INNER JOIN dhcp6_server AS s" \
+    "  ON a.server_id = s.id " \
+    "WHERE s.tag = ? " #__VA_ARGS__ \
+    "  AND o.pd_pool_id = " \
+    "  (SELECT id FROM dhcp6_pd_pool" \
+    "   WHERE prefix = ? AND prefix_length = ?)"
+#endif
+
 } // end of anonymous namespace
 
 } // end of namespace isc::dhcp
index b2d76beb88ac0ec0780f1907b9d55db5496ecaa8..72e315b85b568fa53885f584f271aab480fe2fc9 100644 (file)
@@ -57,5 +57,5 @@ TEST(MySqlConfigBackendImplTest, createTripletFromBinding) {
 }
 
 
-} 
+}
 
index 3feefc237e0406f73b82a212f575533e0e7bd247..c85366eebe3e60d9ae2c0296da3f407f3d00ee52 100644 (file)
@@ -16,7 +16,11 @@ namespace cb {
 /// fetched variable length data in them.
 ///
 //@{
-constexpr unsigned long SUBNET_PREFIX_BUF_LENGTH = 32;
+constexpr unsigned long SUBNET4_PREFIX_BUF_LENGTH = 32;
+
+constexpr unsigned long SUBNET6_PREFIX_BUF_LENGTH = 64;
+
+constexpr unsigned long POOL_ADDRESS6_BUF_LENGTH = 45;
 
 constexpr unsigned long DHCP4O6_INTERFACE_BUF_LENGTH = 128;