1 // Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <mysql_cb_dhcp6.h>
10 #include <mysql_cb_impl.h>
11 #include <mysql_query_macros_dhcp.h>
12 #include <asiolink/addr_utilities.h>
13 #include <cc/data.h>
14 #include <config_backend/constants.h>
15 #include <database/database_connection.h>
16 #include <database/db_exceptions.h>
17 #include <dhcp/classify.h>
18 #include <dhcp/dhcp6.h>
19 #include <dhcp/libdhcp++.h>
20 #include <dhcp/option_data_types.h>
21 #include <dhcp/option_space.h>
22 #include <dhcpsrv/cfgmgr.h>
23 #include <dhcpsrv/config_backend_dhcp6_mgr.h>
24 #include <dhcpsrv/network.h>
25 #include <dhcpsrv/pool.h>
26 #include <dhcpsrv/lease.h>
27 #include <dhcpsrv/timer_mgr.h>
28 #include <dhcpsrv/parsers/client_class_def_parser.h>
29 #include <util/buffer.h>
30 #include <util/boost_time_utils.h>
31 #include <util/multi_threading_mgr.h>
32 #include <mysql/mysql_connection.h>
33 #include <boost/date_time/posix_time/posix_time.hpp>
34 #include <boost/lexical_cast.hpp>
35 #include <boost/pointer_cast.hpp>
36 #include <boost/scoped_ptr.hpp>
37 #include <mysql.h>
38 #include <mysqld_error.h>
39 #include <array>
40 #include <sstream>
41 #include <utility>
42 #include <vector>
43 
44 using namespace isc::cb;
45 using namespace isc::db;
46 using namespace isc::data;
47 using namespace isc::asiolink;
48 using namespace isc::log;
49 using namespace isc::util;
50 
51 namespace isc {
52 namespace dhcp {
53 
54 /// @brief Implementation of the MySQL Configuration Backend.
55 class MySqlConfigBackendDHCPv6Impl : public MySqlConfigBackendImpl {
56 public:
57 
58     /// @brief Statement tags.
59     ///
60     /// The contents of the enum are indexes into the list of SQL statements.
61     /// It is assumed that the order is such that the indices of statements
62     /// reading the database are less than those of statements modifying the
63     /// database.
64     enum StatementIndex {
65         CREATE_AUDIT_REVISION,
66         CHECK_CLIENT_CLASS_KNOWN_DEPENDENCY_CHANGE,
67         GET_GLOBAL_PARAMETER6,
68         GET_ALL_GLOBAL_PARAMETERS6,
69         GET_MODIFIED_GLOBAL_PARAMETERS6,
70         GET_SUBNET6_ID_NO_TAG,
71         GET_SUBNET6_ID_ANY,
72         GET_SUBNET6_ID_UNASSIGNED,
73         GET_SUBNET6_PREFIX_NO_TAG,
74         GET_SUBNET6_PREFIX_ANY,
75         GET_SUBNET6_PREFIX_UNASSIGNED,
76         GET_ALL_SUBNETS6,
77         GET_ALL_SUBNETS6_UNASSIGNED,
78         GET_MODIFIED_SUBNETS6,
79         GET_MODIFIED_SUBNETS6_UNASSIGNED,
80         GET_SHARED_NETWORK_SUBNETS6,
81         GET_POOL6_RANGE,
82         GET_POOL6_RANGE_ANY,
83         GET_PD_POOL,
84         GET_PD_POOL_ANY,
85         GET_SHARED_NETWORK6_NAME_NO_TAG,
86         GET_SHARED_NETWORK6_NAME_ANY,
87         GET_SHARED_NETWORK6_NAME_UNASSIGNED,
88         GET_ALL_SHARED_NETWORKS6,
89         GET_ALL_SHARED_NETWORKS6_UNASSIGNED,
90         GET_MODIFIED_SHARED_NETWORKS6,
91         GET_MODIFIED_SHARED_NETWORKS6_UNASSIGNED,
92         GET_OPTION_DEF6_CODE_SPACE,
93         GET_ALL_OPTION_DEFS6,
94         GET_MODIFIED_OPTION_DEFS6,
95         GET_OPTION6_CODE_SPACE,
96         GET_ALL_OPTIONS6,
97         GET_MODIFIED_OPTIONS6,
98         GET_OPTION6_SUBNET_ID_CODE_SPACE,
99         GET_OPTION6_POOL_ID_CODE_SPACE,
100         GET_OPTION6_PD_POOL_ID_CODE_SPACE,
101         GET_OPTION6_SHARED_NETWORK_CODE_SPACE,
102         GET_CLIENT_CLASS6_NAME,
103         GET_ALL_CLIENT_CLASSES6,
104         GET_ALL_CLIENT_CLASSES6_UNASSIGNED,
105         GET_MODIFIED_CLIENT_CLASSES6,
106         GET_MODIFIED_CLIENT_CLASSES6_UNASSIGNED,
107         GET_AUDIT_ENTRIES6_TIME,
108         GET_SERVER6,
109         GET_ALL_SERVERS6,
110         INSERT_GLOBAL_PARAMETER6,
111         INSERT_GLOBAL_PARAMETER6_SERVER,
112         INSERT_SUBNET6,
113         INSERT_SUBNET6_SERVER,
114         INSERT_POOL6,
115         INSERT_PD_POOL,
116         INSERT_SHARED_NETWORK6,
117         INSERT_SHARED_NETWORK6_SERVER,
118         INSERT_OPTION_DEF6,
119         INSERT_OPTION_DEF6_CLIENT_CLASS,
120         INSERT_OPTION_DEF6_SERVER,
121         INSERT_OPTION6,
122         INSERT_OPTION6_SERVER,
123         INSERT_CLIENT_CLASS6,
124         INSERT_CLIENT_CLASS6_SERVER,
125         INSERT_CLIENT_CLASS6_DEPENDENCY,
126         INSERT_SERVER6,
127         UPDATE_GLOBAL_PARAMETER6,
128         UPDATE_SUBNET6,
129         UPDATE_SHARED_NETWORK6,
130         UPDATE_OPTION_DEF6,
131         UPDATE_OPTION_DEF6_CLIENT_CLASS,
132         UPDATE_OPTION6,
133         UPDATE_OPTION6_SUBNET_ID,
134         UPDATE_OPTION6_POOL_ID,
135         UPDATE_OPTION6_PD_POOL_ID,
136         UPDATE_OPTION6_SHARED_NETWORK,
137         UPDATE_OPTION6_CLIENT_CLASS,
138         UPDATE_CLIENT_CLASS6,
139         UPDATE_CLIENT_CLASS6_SAME_POSITION,
140         UPDATE_SERVER6,
141         DELETE_GLOBAL_PARAMETER6,
142         DELETE_ALL_GLOBAL_PARAMETERS6,
143         DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
144         DELETE_SUBNET6_ID_WITH_TAG,
145         DELETE_SUBNET6_ID_ANY,
146         DELETE_SUBNET6_PREFIX_WITH_TAG,
147         DELETE_SUBNET6_PREFIX_ANY,
148         DELETE_ALL_SUBNETS6,
149         DELETE_ALL_SUBNETS6_UNASSIGNED,
150         DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
151         DELETE_SUBNET6_SERVER,
152         DELETE_POOLS6,
153         DELETE_PD_POOLS,
154         DELETE_SHARED_NETWORK6_NAME_WITH_TAG,
155         DELETE_SHARED_NETWORK6_NAME_ANY,
156         DELETE_ALL_SHARED_NETWORKS6,
157         DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED,
158         DELETE_SHARED_NETWORK6_SERVER,
159         DELETE_OPTION_DEF6_CODE_NAME,
160         DELETE_ALL_OPTION_DEFS6,
161         DELETE_ALL_OPTION_DEFS6_UNASSIGNED,
162         DELETE_OPTION_DEFS6_CLIENT_CLASS,
163         DELETE_OPTION6,
164         DELETE_ALL_GLOBAL_OPTIONS6_UNASSIGNED,
165         DELETE_OPTION6_SUBNET_ID,
166         DELETE_OPTION6_POOL_RANGE,
167         DELETE_OPTION6_PD_POOL,
168         DELETE_OPTION6_SHARED_NETWORK,
169         DELETE_OPTIONS6_SUBNET_ID_PREFIX,
170         DELETE_OPTIONS6_SHARED_NETWORK,
171         DELETE_OPTIONS6_CLIENT_CLASS,
172         DELETE_CLIENT_CLASS6_DEPENDENCY,
173         DELETE_CLIENT_CLASS6_SERVER,
174         DELETE_ALL_CLIENT_CLASSES6,
175         DELETE_ALL_CLIENT_CLASSES6_UNASSIGNED,
176         DELETE_CLIENT_CLASS6,
177         DELETE_CLIENT_CLASS6_ANY,
178         DELETE_SERVER6,
179         DELETE_ALL_SERVERS6,
180         NUM_STATEMENTS
181     };
182 
183     /// @brief Constructor.
184     ///
185     /// @param parameters A data structure relating keywords and values
186     /// concerned with the database.
187     explicit MySqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap&
188                                           parameters);
189 
190     /// @brief Destructor.
191     ~MySqlConfigBackendDHCPv6Impl();
192 
193     /// @brief Sends query to retrieve global parameter.
194     ///
195     /// @param server_selector Server selector.
196     /// @param name Name of the parameter to be retrieved.
197     ///
198     /// @return Pointer to the retrieved value or null if such parameter
199     /// doesn't exist.
getGlobalParameter6(const ServerSelector & server_selector,const std::string & name)200     StampedValuePtr getGlobalParameter6(const ServerSelector& server_selector,
201                                         const std::string& name) {
202         StampedValueCollection parameters;
203 
204         auto tags = server_selector.getTags();
205         for (auto tag : tags) {
206             MySqlBindingCollection in_bindings = {
207                 MySqlBinding::createString(tag.get()),
208                 MySqlBinding::createString(name)
209             };
210 
211             getGlobalParameters(GET_GLOBAL_PARAMETER6, in_bindings, parameters);
212         }
213 
214         return (parameters.empty() ? StampedValuePtr() : *parameters.begin());
215     }
216 
217     /// @brief Sends query to insert or update global parameter.
218     ///
219     /// @param server_selector Server selector.
220     /// @param name Name of the global parameter.
221     /// @param value Value of the global parameter.
createUpdateGlobalParameter6(const db::ServerSelector & server_selector,const StampedValuePtr & value)222     void createUpdateGlobalParameter6(const db::ServerSelector& server_selector,
223                                       const StampedValuePtr& value) {
224 
225         if (server_selector.amUnassigned()) {
226             isc_throw(NotImplemented, "managing configuration for no particular server"
227                       " (unassigned) is unsupported at the moment");
228         }
229 
230         auto tag = getServerTag(server_selector, "creating or updating global parameter");
231 
232         MySqlBindingCollection in_bindings = {
233             MySqlBinding::createString(value->getName()),
234             MySqlBinding::createString(value->getValue()),
235             MySqlBinding::createInteger<uint8_t>(value->getType()),
236             MySqlBinding::createTimestamp(value->getModificationTime()),
237             MySqlBinding::createString(tag),
238             MySqlBinding::createString(value->getName())
239         };
240 
241         MySqlTransaction transaction(conn_);
242 
243         // Create scoped audit revision. As long as this instance exists
244         // no new audit revisions are created in any subsequent calls.
245         ScopedAuditRevision
246             audit_revision(this, MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
247                            server_selector, "global parameter set", false);
248 
249         // Try to update the existing row.
250         if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_GLOBAL_PARAMETER6,
251                                     in_bindings) == 0) {
252 
253             // No such parameter found, so let's insert it. We have to adjust the
254             // bindings collection to match the prepared statement for insert.
255             in_bindings.pop_back();
256             in_bindings.pop_back();
257             conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6,
258                               in_bindings);
259 
260             // Successfully inserted global parameter. Now, we have to associate it
261             // with the server tag.
262 
263             // Let's first get the primary key of the global parameter.
264             uint64_t id = mysql_insert_id(conn_.mysql_);
265 
266             // Successfully inserted global parameter. Now, we have to associate it
267             // with the server tag.
268             attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6_SERVER,
269                                    server_selector,
270                                    MySqlBinding::createInteger<uint64_t>(id),
271                                    MySqlBinding::createTimestamp(value->getModificationTime()));
272         }
273 
274         transaction.commit();
275     }
276 
277     /// @brief Sends query to the database to retrieve multiple subnets.
278     ///
279     /// Query should order subnets by subnet_id.
280     ///
281     /// @param index Index of the query to be used.
282     /// @param server_selector Server selector.
283     /// @param in_bindings Input bindings specifying selection criteria. The
284     /// size of the bindings collection must match the number of placeholders
285     /// in the prepared statement. The input bindings collection must be empty
286     /// if the query contains no WHERE clause.
287     /// @param [out] subnets Reference to the container where fetched subnets
288     /// will be inserted.
getSubnets6(const StatementIndex & index,const ServerSelector & server_selector,const MySqlBindingCollection & in_bindings,Subnet6Collection & subnets)289     void getSubnets6(const StatementIndex& index,
290                      const ServerSelector& server_selector,
291                      const MySqlBindingCollection& in_bindings,
292                      Subnet6Collection& subnets) {
293         // Create output bindings. The order must match that in the prepared
294         // statement. Please put comments only at the end of line so
295         // line counting and indexing match.
296         // The server tag must be the last field.
297         MySqlBindingCollection out_bindings = {
298             MySqlBinding::createInteger<uint32_t>(), // subnet_id
299             MySqlBinding::createString(SUBNET6_PREFIX_BUF_LENGTH), // subnet_prefix
300             MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // client_class
301             MySqlBinding::createString(INTERFACE_BUF_LENGTH), // interface
302             MySqlBinding::createTimestamp(), // modification_ts
303             MySqlBinding::createInteger<uint32_t>(), // preferred_lifetime
304             MySqlBinding::createInteger<uint8_t>(), // rapid_commit
305             MySqlBinding::createInteger<uint32_t>(), // rebind_timer
306             MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
307             MySqlBinding::createInteger<uint32_t>(), // renew_timer
308             MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
309             MySqlBinding::createInteger<uint8_t>(), // reservations_global
310             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // shared_network_name
311             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
312             MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
313             MySqlBinding::createInteger<uint64_t>(), // pool: id
314             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: start_address
315             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: end_address
316             MySqlBinding::createInteger<uint32_t>(), // pool: subnet_id
317             MySqlBinding::createTimestamp(), // pool: modification_ts
318             MySqlBinding::createInteger<uint64_t>(), // pd pool: id
319             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: prefix
320             MySqlBinding::createInteger<uint8_t>(), // pd pool: prefix_length
321             MySqlBinding::createInteger<uint8_t>(), // pd pool: delegated_prefix_length
322             MySqlBinding::createInteger<uint32_t>(), // pd pool: subnet_id
323             MySqlBinding::createTimestamp(), // pd pool: modification_ts
324             MySqlBinding::createInteger<uint64_t>(), // pool option: option_id
325             MySqlBinding::createInteger<uint16_t>(), // pool option: code
326             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // pool option: value
327             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pool option: formatted_value
328             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pool option: space
329             MySqlBinding::createInteger<uint8_t>(), // pool option: persistent
330             MySqlBinding::createInteger<uint32_t>(), // pool option: dhcp6_subnet_id
331             MySqlBinding::createInteger<uint8_t>(), // pool option: scope_id
332             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool option: user_context
333             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pool option: shared_network_name
334             MySqlBinding::createInteger<uint64_t>(), // pool option: pool_id
335             MySqlBinding::createTimestamp(), // pool option: modification_ts
336             MySqlBinding::createInteger<uint64_t>(), // pool option: pd_pool_id
337             MySqlBinding::createInteger<uint64_t>(), // pd pool option: option_id
338             MySqlBinding::createInteger<uint16_t>(), // pd pool option: code
339             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // pd pool option: value
340             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pd pool option: formatted_value
341             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pd pool option: space
342             MySqlBinding::createInteger<uint8_t>(), // pd pool option: persistent
343             MySqlBinding::createInteger<uint32_t>(), // pd pool option: dhcp6_subnet_id
344             MySqlBinding::createInteger<uint8_t>(), // pd pool option: scope_id
345             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool option: user_context
346             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pd pool option: shared_network_name
347             MySqlBinding::createInteger<uint64_t>(), // pd pool option: pool_id
348             MySqlBinding::createTimestamp(), // pd pool option: modification_ts
349             MySqlBinding::createInteger<uint64_t>(), // pd pool option: pd_pool_id
350             MySqlBinding::createInteger<uint64_t>(), // option: option_id
351             MySqlBinding::createInteger<uint16_t>(), // option: code
352             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // option: value
353             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
354             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
355             MySqlBinding::createInteger<uint8_t>(), // option: persistent
356             MySqlBinding::createInteger<uint32_t>(), // option: dhcp6_subnet_id
357             MySqlBinding::createInteger<uint8_t>(), // option: scope_id
358             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
359             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
360             MySqlBinding::createInteger<uint64_t>(), // option: pool_id
361             MySqlBinding::createTimestamp(), // option: modification_ts
362             MySqlBinding::createInteger<uint64_t>(), // option: pd_pool_id
363             MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
364             MySqlBinding::createInteger<float>(), // t1_percent
365             MySqlBinding::createInteger<float>(), // t2_percent
366             MySqlBinding::createBlob(INTERFACE_ID_BUF_LENGTH), // interface_id
367             MySqlBinding::createInteger<uint32_t>(), // min_preferred_lifetime
368             MySqlBinding::createInteger<uint32_t>(), // max_preferred_lifetime
369             MySqlBinding::createInteger<uint32_t>(), // min_valid_lifetime
370             MySqlBinding::createInteger<uint32_t>(), // max_valid_lifetime
371             MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class
372             MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes
373             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context
374             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: excluded_prefix
375             MySqlBinding::createInteger<uint8_t>(), // pd pool: excluded_prefix_length
376             MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pd pool: client_class
377             MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pd pool: require_client_classes
378             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool: user_context
379             MySqlBinding::createInteger<uint8_t>(), // ddns_send_updates
380             MySqlBinding::createInteger<uint8_t>(), // ddns_override_no_update
381             MySqlBinding::createInteger<uint8_t>(), // ddns_override_client_update
382             MySqlBinding::createInteger<uint8_t>(), // ddns_replace_client_name
383             MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_generated_prefix
384             MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_qualifying_suffix
385             MySqlBinding::createInteger<uint8_t>(), // reservations_in_subnet
386             MySqlBinding::createInteger<uint8_t>(), // reservations_out_of_pool
387             MySqlBinding::createInteger<float>(), // cache_threshold
388             MySqlBinding::createInteger<uint32_t>(), // cache_max_age
389             MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
390         };
391 
392         uint64_t last_pool_id = 0;
393         uint64_t last_pd_pool_id = 0;
394         uint64_t last_pool_option_id = 0;
395         uint64_t last_pd_pool_option_id = 0;
396         uint64_t last_option_id = 0;
397         Pool6Ptr last_pool;
398         Pool6Ptr last_pd_pool;
399         std::string last_tag;
400 
401         // Execute actual query.
402         conn_.selectQuery(index, in_bindings, out_bindings,
403                           [this, &subnets, &last_pool,  &last_pd_pool,
404                            &last_pool_id, &last_pd_pool_id,
405                            &last_pool_option_id, &last_pd_pool_option_id,
406                            &last_option_id, &last_tag]
407                           (MySqlBindingCollection& out_bindings) {
408             // Get pointer to the last subnet in the collection.
409             Subnet6Ptr last_subnet;
410             if (!subnets.empty()) {
411                 last_subnet = *subnets.rbegin();
412             }
413 
414             // Subnet has been returned. Assuming that subnets are ordered by
415             // subnet identifier, if the subnet identifier of the current row
416             // is different than the subnet identifier of the previously returned
417             // row, it means that we have to construct new subnet object.
418             if (!last_subnet || (last_subnet->getID() != out_bindings[0]->getInteger<uint32_t>())) {
419 
420                 // Reset per subnet component tracking and server tag because
421                 // we're now starting to process a new subnet.
422                 last_pool_id = 0;
423                 last_pd_pool_id = 0;
424                 last_pool_option_id = 0;
425                 last_pd_pool_option_id = 0;
426                 last_option_id = 0;
427                 last_pool.reset();
428                 last_pd_pool.reset();
429                 last_tag.clear();
430 
431                 // Get subnet parameters required by the constructor first.
432 
433                 // subnet_id (0)
434                 SubnetID subnet_id(out_bindings[0]->getInteger<uint32_t>());
435 
436                 // subnet_prefix (1)
437                 std::string subnet_prefix = out_bindings[1]->getString();
438                 auto prefix_pair = Subnet6::parsePrefix(subnet_prefix);
439 
440                 // preferred_lifetime (5)
441                 // min_preferred_lifetime (69)
442                 // max_preferred_lifetime (70)
443                 auto preferred_lifetime = createTriplet(out_bindings[5],
444                                                         out_bindings[69],
445                                                         out_bindings[70]);
446 
447                 // renew_timer (9)
448                 auto renew_timer = createTriplet(out_bindings[9]);
449 
450                 // rebind_timer (7)
451                 auto rebind_timer = createTriplet(out_bindings[7]);
452 
453                 // valid_lifetime (14)
454                 // min_valid_lifetime (71)
455                 // max_valid_lifetime (72)
456                 auto valid_lifetime = createTriplet(out_bindings[14],
457                                                     out_bindings[71],
458                                                     out_bindings[72]);
459 
460                 // Create subnet with basic settings.
461                 last_subnet = Subnet6::create(prefix_pair.first, prefix_pair.second,
462                                               renew_timer, rebind_timer,
463                                               preferred_lifetime,
464                                               valid_lifetime, subnet_id);
465 
466                 // 0 and 1 are subnet_id and subnet_prefix
467 
468                 // client_class (2)
469                 if (!out_bindings[2]->amNull()) {
470                     last_subnet->allowClientClass(out_bindings[2]->getString());
471                 }
472 
473                 // interface (3)
474                 if (!out_bindings[3]->amNull()) {
475                     last_subnet->setIface(out_bindings[3]->getString());
476                 }
477 
478                 // modification_ts (4)
479                 last_subnet->setModificationTime(out_bindings[4]->getTimestamp());
480                 // 5 is preferred_lifetime
481 
482                 // rapid_commit (6)
483                 if (!out_bindings[6]->amNull()) {
484                     last_subnet->setRapidCommit(out_bindings[6]->getBool());
485                 }
486 
487                 // 7 is rebind_timer
488 
489                 // relay (8)
490                 ElementPtr relay_element = out_bindings[8]->getJSON();
491                 if (relay_element) {
492                     if (relay_element->getType() != Element::list) {
493                         isc_throw(BadValue, "invalid relay value "
494                                   << out_bindings[8]->getString());
495                     }
496                     for (auto i = 0; i < relay_element->size(); ++i) {
497                         auto relay_address_element = relay_element->get(i);
498                         if (relay_address_element->getType() != Element::string) {
499                             isc_throw(BadValue, "relay address must be a string");
500                         }
501                         last_subnet->addRelayAddress(IOAddress(relay_element->get(i)->stringValue()));
502                     }
503                 }
504 
505                 // 9 is renew_timer
506 
507                 // require_client_classes (10)
508                 ElementPtr require_element = out_bindings[10]->getJSON();
509                 if (require_element) {
510                     if (require_element->getType() != Element::list) {
511                         isc_throw(BadValue, "invalid require_client_classes value "
512                                   << out_bindings[10]->getString());
513                     }
514                     for (auto i = 0; i < require_element->size(); ++i) {
515                         auto require_item = require_element->get(i);
516                         if (require_item->getType() != Element::string) {
517                             isc_throw(BadValue, "elements of require_client_classes list must"
518                                       "be valid strings");
519                         }
520                         last_subnet->requireClientClass(require_item->stringValue());
521                     }
522                 }
523 
524                 // reservations_global (11)
525                 if (!out_bindings[11]->amNull()) {
526                     last_subnet->setReservationsGlobal(out_bindings[11]->getBool());
527                 }
528 
529                 // shared_network_name (12)
530                 if (!out_bindings[12]->amNull()) {
531                     last_subnet->setSharedNetworkName(out_bindings[12]->getString());
532                 }
533 
534                 // user_context (13)
535                 ElementPtr user_context = out_bindings[13]->getJSON();
536                 if (user_context) {
537                     last_subnet->setContext(user_context);
538                 }
539 
540                 // 14 is valid_lifetime
541 
542                 // 15 to 19 are pool
543                 // 20 to 25 are pd pool
544                 // 26 to 38 are pool option
545                 // 39 to 51 are pd pool option
546                 // 52 to 64 are option
547 
548                 // calculate_tee_times (65)
549                 if (!out_bindings[65]->amNull()) {
550                     last_subnet->setCalculateTeeTimes(out_bindings[65]->getBool());
551                 }
552 
553                 // t1_percent (66)
554                 if (!out_bindings[66]->amNull()) {
555                     last_subnet->setT1Percent(out_bindings[66]->getFloat());
556                 }
557 
558                 // t2_percent (67)
559                 if (!out_bindings[67]->amNull()) {
560                     last_subnet->setT2Percent(out_bindings[67]->getFloat());
561                 }
562 
563                 // interface_id (68)
564                 if (!out_bindings[68]->amNull()) {
565                     auto iface_id_data = out_bindings[68]->getBlob();
566                     if (!iface_id_data.empty()) {
567                         OptionPtr opt_iface_id(new Option(Option::V6, D6O_INTERFACE_ID,
568                                                           iface_id_data));
569                         last_subnet->setInterfaceId(opt_iface_id);
570                     }
571                 }
572 
573                 // 69 and 70 are {min,max}_preferred_lifetime
574 
575                 // 71 and 72 are {min,max}_valid_lifetime
576 
577                 // 73 is pool client_class
578                 // 74 is pool require_client_classes
579                 // 75 is pool user_context
580                 // 76 is pd pool excluded_prefix
581                 // 77 is pd pool excluded_prefix_length
582                 // 78 is pd pool client_class
583                 // 79 is pd pool require_client_classes
584                 // 80 is pd pool user_context
585 
586                 // ddns_send_updates (81)
587                 if (!out_bindings[81]->amNull()) {
588                     last_subnet->setDdnsSendUpdates(out_bindings[81]->getBool());
589                 }
590 
591                 // ddns_override_no_update (82)
592                 if (!out_bindings[82]->amNull()) {
593                     last_subnet->setDdnsOverrideNoUpdate(out_bindings[82]->getBool());
594                 }
595 
596                 // ddns_override_client_update (83)
597                 if (!out_bindings[83]->amNull()) {
598                     last_subnet->setDdnsOverrideClientUpdate(out_bindings[83]->getBool());
599                 }
600 
601                 // ddns_replace_client_name (84)
602                 if (!out_bindings[84]->amNull()) {
603                     last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
604                         (out_bindings[84]->getInteger<uint8_t>()));
605                 }
606 
607                 // ddns_generated_prefix (85)
608                 if (!out_bindings[85]->amNull()) {
609                     last_subnet->setDdnsGeneratedPrefix(out_bindings[85]->getString());
610                 }
611 
612                 // ddns_qualifying_suffix (86)
613                 if (!out_bindings[86]->amNull()) {
614                     last_subnet->setDdnsQualifyingSuffix(out_bindings[86]->getString());
615                 }
616 
617                 // reservations_in_subnet (87)
618                 if (!out_bindings[87]->amNull()) {
619                     last_subnet->setReservationsInSubnet(out_bindings[87]->getBool());
620                 }
621 
622                 // reservations_out_of_pool (88)
623                 if (!out_bindings[88]->amNull()) {
624                     last_subnet->setReservationsOutOfPool(out_bindings[88]->getBool());
625                 }
626 
627                 // cache_threshold (89)
628                 if (!out_bindings[89]->amNull()) {
629                     last_subnet->setCacheThreshold(out_bindings[89]->getFloat());
630                 }
631 
632                 // cache_max_age (90)
633                 if (!out_bindings[90]->amNull()) {
634                     last_subnet->setCacheMaxAge(out_bindings[90]->getInteger<uint32_t>());
635                 }
636 
637                 // server_tag (91 / last)
638 
639                 // Subnet ready. Add it to the list.
640                 auto ret = subnets.insert(last_subnet);
641 
642                 // subnets is a multi index container with unique indexes
643                 // but these indexes are unique too in the database,
644                 // so this is for sanity only.
645                 if (!ret.second) {
646                     isc_throw(Unexpected, "add subnet failed");
647                 }
648             }
649 
650             // Check for new server tags.
651             if (!out_bindings[91]->amNull() &&
652                 (last_tag != out_bindings[91]->getString())) {
653                 last_tag = out_bindings[91]->getString();
654                 if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
655                     last_subnet->setServerTag(last_tag);
656                 }
657             }
658 
659             // Pool is between 15 and 19 with extra between 73 and 75
660 
661             // If the row contains information about the pool and it
662             // appears to be new pool entry (checked by comparing pool
663             // id), let's create the new pool and add it to the
664             // subnet.
665             // pool id (15)
666             // pool start_address (16)
667             // pool end_address (17)
668             if (!out_bindings[15]->amNull() &&
669                 !out_bindings[16]->getString().empty() &&
670                 !out_bindings[17]->getString().empty() &&
671                 (out_bindings[15]->getInteger<uint64_t>() > last_pool_id)) {
672                 last_pool_id = out_bindings[15]->getInteger<uint64_t>();
673                 last_pool = Pool6::create(Lease::TYPE_NA,
674                                           IOAddress(out_bindings[16]->getString()),
675                                           IOAddress(out_bindings[17]->getString()));
676 
677                 // 18 is pool subnet_id (ignored)
678                 // 19 is pool modification_ts (ignored)
679 
680                 // pool client_class (73)
681                 if (!out_bindings[73]->amNull()) {
682                     last_pool->allowClientClass(out_bindings[73]->getString());
683                 }
684 
685                 // pool require_client_classes (74)
686                 ElementPtr require_element = out_bindings[74]->getJSON();
687                 if (require_element) {
688                     if (require_element->getType() != Element::list) {
689                         isc_throw(BadValue, "invalid pool require_client_classes value "
690                                   << out_bindings[74]->getString());
691                     }
692                     for (auto i = 0; i < require_element->size(); ++i) {
693                         auto require_item = require_element->get(i);
694                         if (require_item->getType() != Element::string) {
695                             isc_throw(BadValue, "elements of pool require_client_classes list must"
696                                       "be valid strings");
697                         }
698                         last_pool->requireClientClass(require_item->stringValue());
699                     }
700                 }
701 
702                 // pool user_context (75)
703                 ElementPtr user_context = out_bindings[75]->getJSON();
704                 if (user_context) {
705                     last_pool->setContext(user_context);
706                 }
707 
708                 last_subnet->addPool(last_pool);
709             }
710 
711             // Pd Pool is between 20 and 25 with extra between 76 and 80
712 
713             // If the row contains information about the pd pool and
714             // it appears to be new pd pool entry (checked by
715             // comparing pd pool id), let's create the new pd pool and
716             // add it to the subnet.
717             // pd pool id (20)
718             // pd pool prefix (21)
719             // pd pool prefix_length (22)
720             // pd pool delegated_prefix_length (23)
721             if (!out_bindings[20]->amNull() &&
722                 !out_bindings[21]->getString().empty() &&
723                 (out_bindings[22]->getInteger<uint8_t>() != 0) &&
724                 (out_bindings[23]->getInteger<uint8_t>() != 0) &&
725                 (out_bindings[20]->getInteger<uint64_t>() > last_pd_pool_id)) {
726                 last_pd_pool_id = out_bindings[20]->getInteger<uint64_t>();
727 
728                 // 24 is pd pool subnet_id (ignored)
729                 // 25 is pd pool modification_ts (ignored)
730 
731                 // excluded_prefix (76) and excluded_prefix_length (77)
732                 IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS();
733                 if (!out_bindings[76]->amNull()) {
734                     excluded_prefix = IOAddress(out_bindings[76]->getString());
735                 }
736                 last_pd_pool = Pool6::create(IOAddress(out_bindings[21]->getString()),
737                                              out_bindings[22]->getInteger<uint8_t>(),
738                                              out_bindings[23]->getInteger<uint8_t>(),
739                                              excluded_prefix,
740                                              out_bindings[77]->getInteger<uint8_t>());
741 
742                 // pd pool client_class (78)
743                 if (!out_bindings[78]->amNull()) {
744                     last_pd_pool->allowClientClass(out_bindings[78]->getString());
745                 }
746 
747                 // pd pool require_client_classes (79)
748                 ElementPtr require_element = out_bindings[79]->getJSON();
749                 if (require_element) {
750                     if (require_element->getType() != Element::list) {
751                         isc_throw(BadValue, "invalid pd pool require_client_classes value "
752                                   << out_bindings[79]->getString());
753                     }
754                     for (auto i = 0; i < require_element->size(); ++i) {
755                         auto require_item = require_element->get(i);
756                         if (require_item->getType() != Element::string) {
757                             isc_throw(BadValue, "elements of pd pool require_client_classes list must"
758                                       "be valid strings");
759                         }
760                         last_pd_pool->requireClientClass(require_item->stringValue());
761                     }
762                 }
763 
764                 // pd pool user_context (80)
765                 ElementPtr user_context = out_bindings[80]->getJSON();
766                 if (user_context) {
767                     last_pd_pool->setContext(user_context);
768                 }
769 
770                 last_subnet->addPool(last_pd_pool);
771             }
772 
773             // Parse pool specific option between 26 and 38
774             if (last_pool && !out_bindings[26]->amNull() &&
775                 (last_pool_option_id < out_bindings[26]->getInteger<uint64_t>())) {
776                 last_pool_option_id = out_bindings[26]->getInteger<uint64_t>();
777 
778                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 26);
779                 if (desc) {
780                     last_pool->getCfgOption()->add(*desc, desc->space_name_);
781                 }
782             }
783 
784             // Parse pd pool specific option between 39 and 51
785             if (last_pd_pool && !out_bindings[39]->amNull() &&
786                 (last_pd_pool_option_id < out_bindings[39]->getInteger<uint64_t>())) {
787                 last_pd_pool_option_id = out_bindings[39]->getInteger<uint64_t>();
788 
789                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 39);
790                 if (desc) {
791                     last_pd_pool->getCfgOption()->add(*desc, desc->space_name_);
792                 }
793             }
794 
795             // Parse subnet specific option between 52 and 64
796             if (!out_bindings[52]->amNull() &&
797                 (last_option_id < out_bindings[52]->getInteger<uint64_t>())) {
798                 last_option_id = out_bindings[52]->getInteger<uint64_t>();
799 
800                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 52);
801                 if (desc) {
802                     last_subnet->getCfgOption()->add(*desc, desc->space_name_);
803                 }
804             }
805         });
806 
807         // Now that we're done fetching the whole subnet, we have to
808         // check if it has matching server tags and toss it if it
809         // doesn't. We skip matching the server tags if we're asking
810         // for ANY subnet.
811         auto& subnet_index = subnets.get<SubnetSubnetIdIndexTag>();
812         tossNonMatchingElements(server_selector, subnet_index);
813     }
814 
815     /// @brief Sends query to retrieve single subnet by id.
816     ///
817     /// @param server_selector Server selector.
818     /// @param subnet_id Subnet identifier.
819     ///
820     /// @return Pointer to the returned subnet or NULL if such subnet
821     /// doesn't exist.
getSubnet6(const ServerSelector & server_selector,const SubnetID & subnet_id)822     Subnet6Ptr getSubnet6(const ServerSelector& server_selector,
823                           const SubnetID& subnet_id) {
824         if (server_selector.hasMultipleTags()) {
825             isc_throw(InvalidOperation, "expected one server tag to be specified"
826                       " while fetching a subnet. Got: "
827                       << getServerTagsAsText(server_selector));
828         }
829 
830         MySqlBindingCollection in_bindings = { MySqlBinding::createInteger<uint32_t>(subnet_id) };
831 
832         auto index = GET_SUBNET6_ID_NO_TAG;
833 
834         if (server_selector.amUnassigned()) {
835             index = GET_SUBNET6_ID_UNASSIGNED;
836 
837         } else if (server_selector.amAny()) {
838             index = GET_SUBNET6_ID_ANY;
839         }
840 
841         Subnet6Collection subnets;
842         getSubnets6(index, server_selector, in_bindings, subnets);
843 
844         return (subnets.empty() ? Subnet6Ptr() : *subnets.begin());
845     }
846 
847     /// @brief Sends query to retrieve single subnet by prefix.
848     ///
849     /// The prefix should be in the following format: "2001:db8:1::/64".
850     ///
851     /// @param server_selector Server selector.
852     /// @param subnet_id Subnet identifier.
853     ///
854     /// @return Pointer to the returned subnet or NULL if such subnet
855     /// doesn't exist.
getSubnet6(const ServerSelector & server_selector,const std::string & subnet_prefix)856     Subnet6Ptr getSubnet6(const ServerSelector& server_selector,
857                           const std::string& subnet_prefix) {
858         if (server_selector.hasMultipleTags()) {
859             isc_throw(InvalidOperation, "expected one server tag to be specified"
860                       " while fetching a subnet. Got: "
861                       << getServerTagsAsText(server_selector));
862         }
863 
864         MySqlBindingCollection in_bindings = { MySqlBinding::createString(subnet_prefix) };
865 
866         auto index = GET_SUBNET6_PREFIX_NO_TAG;
867 
868         if (server_selector.amUnassigned()) {
869             index = GET_SUBNET6_PREFIX_UNASSIGNED;
870 
871         } else if (server_selector.amAny()) {
872             index = GET_SUBNET6_PREFIX_ANY;
873         }
874 
875         Subnet6Collection subnets;
876         getSubnets6(index, server_selector, in_bindings, subnets);
877 
878         return (subnets.empty() ? Subnet6Ptr() : *subnets.begin());
879     }
880 
881     /// @brief Sends query to retrieve all subnets.
882     ///
883     /// @param server_selector Server selector.
884     /// @param [out] subnets Reference to the subnet collection structure where
885     /// subnets should be inserted.
getAllSubnets6(const ServerSelector & server_selector,Subnet6Collection & subnets)886     void getAllSubnets6(const ServerSelector& server_selector,
887                         Subnet6Collection& subnets) {
888         if (server_selector.amAny()) {
889             isc_throw(InvalidOperation, "fetching all subnets for ANY "
890                       "server is not supported");
891         }
892         auto index = (server_selector.amUnassigned() ? GET_ALL_SUBNETS6_UNASSIGNED :
893                       GET_ALL_SUBNETS6);
894         MySqlBindingCollection in_bindings;
895         getSubnets6(index, server_selector, in_bindings, subnets);
896     }
897 
898     /// @brief Sends query to retrieve modified subnets.
899     ///
900     /// @param server_selector Server selector.
901     /// @param modification_ts Lower bound modification timestamp.
902     /// @param [out] subnets Reference to the subnet collection structure where
903     /// subnets should be inserted.
getModifiedSubnets6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_ts,Subnet6Collection & subnets)904     void getModifiedSubnets6(const ServerSelector& server_selector,
905                              const boost::posix_time::ptime& modification_ts,
906                              Subnet6Collection& subnets) {
907         if (server_selector.amAny()) {
908             isc_throw(InvalidOperation, "fetching modified subnets for ANY "
909                       "server is not supported");
910         }
911 
912         MySqlBindingCollection in_bindings = {
913             MySqlBinding::createTimestamp(modification_ts)
914         };
915 
916         auto index = (server_selector.amUnassigned() ? GET_MODIFIED_SUBNETS6_UNASSIGNED :
917                       GET_MODIFIED_SUBNETS6);
918         getSubnets6(index, server_selector, in_bindings, subnets);
919     }
920 
921     /// @brief Sends query to retrieve all subnets belonging to a shared network.
922     ///
923     /// @param server_selector Server selector.
924     /// @param shared_network_name Name of the shared network for which the
925     /// subnets should be retrieved.
926     /// @param [out] subnets Reference to the subnet collection structure where
927     /// subnets should be inserted.
getSharedNetworkSubnets6(const ServerSelector & server_selector,const std::string & shared_network_name,Subnet6Collection & subnets)928     void getSharedNetworkSubnets6(const ServerSelector& server_selector,
929                                   const std::string& shared_network_name,
930                                   Subnet6Collection& subnets) {
931         MySqlBindingCollection in_bindings = { MySqlBinding::createString(shared_network_name) };
932         getSubnets6(GET_SHARED_NETWORK_SUBNETS6, server_selector, in_bindings, subnets);
933     }
934 
935     /// @brief Sends query to retrieve multiple pools.
936     ///
937     /// Query should order pools by id.
938     ///
939     /// @param index Index of the query to be used.
940     /// @param in_bindings Input bindings specifying selection criteria. The
941     /// size of the bindings collection must match the number of placeholders
942     /// in the prepared statement. The input bindings collection must be empty
943     /// if the query contains no WHERE clause.
944     /// @param [out] pools Reference to the container where fetched pools
945     /// will be inserted.
946     /// @param [out] pool_ids Identifiers of the pools returned in @c pools
947     /// argument.
getPools(const StatementIndex & index,const MySqlBindingCollection & in_bindings,PoolCollection & pools,std::vector<uint64_t> & pool_ids)948     void getPools(const StatementIndex& index,
949                   const MySqlBindingCollection& in_bindings,
950                   PoolCollection& pools,
951                   std::vector<uint64_t>& pool_ids) {
952         MySqlBindingCollection out_bindings = {
953             MySqlBinding::createInteger<uint64_t>(), // pool: id
954             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: start_address
955             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pool: end_address
956             MySqlBinding::createInteger<uint32_t>(), // pool: subnet_id
957             MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pool: client_class
958             MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pool: require_client_classes
959             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool: user_context
960             MySqlBinding::createTimestamp(), // pool: modification_ts
961             MySqlBinding::createInteger<uint64_t>(), // pool option: option_id
962             MySqlBinding::createInteger<uint16_t>(), // pool option: code
963             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // pool option: value
964             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pool option: formatted_value
965             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pool option: space
966             MySqlBinding::createInteger<uint8_t>(), // pool option: persistent
967             MySqlBinding::createInteger<uint32_t>(), // pool option: dhcp6_subnet_id
968             MySqlBinding::createInteger<uint8_t>(), // pool option: scope_id
969             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool option: user_context
970             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pool option: shared_network_name
971             MySqlBinding::createInteger<uint64_t>(), // pool option: pool_id
972             MySqlBinding::createTimestamp(), //pool option: modification_ts
973             MySqlBinding::createInteger<uint64_t>(), // pool option: pd_pool_id
974         };
975 
976         uint64_t last_pool_id = 0;
977         uint64_t last_pool_option_id = 0;
978         Pool6Ptr last_pool;
979 
980         conn_.selectQuery(index, in_bindings, out_bindings,
981                           [this, &last_pool_id, &last_pool_option_id, &last_pool,
982                            &pools, &pool_ids]
983                           (MySqlBindingCollection& out_bindings) {
984             if (out_bindings[0]->getInteger<uint64_t>() > last_pool_id) {
985 
986                 // pool id (0)
987                 last_pool_id = out_bindings[0]->getInteger<uint64_t>();
988 
989                 // pool start_address (1)
990                 // pool end_address (2)
991                 last_pool = Pool6::create(Lease::TYPE_NA,
992                                           IOAddress(out_bindings[1]->getString()),
993                                           IOAddress(out_bindings[2]->getString()));
994                 // pool client_class (4)
995                 if (!out_bindings[4]->amNull()) {
996                     last_pool->allowClientClass(out_bindings[4]->getString());
997                 }
998 
999                 // pool require_client_classes (5)
1000                 ElementPtr require_element = out_bindings[5]->getJSON();
1001                 if (require_element) {
1002                     if (require_element->getType() != Element::list) {
1003                         isc_throw(BadValue, "invalid pool require_client_classes value "
1004                                   << out_bindings[5]->getString());
1005                     }
1006                     for (auto i = 0; i < require_element->size(); ++i) {
1007                         auto require_item = require_element->get(i);
1008                         if (require_item->getType() != Element::string) {
1009                             isc_throw(BadValue, "elements of pool require_client_classes list must"
1010                                       "be valid strings");
1011                         }
1012                         last_pool->requireClientClass(require_item->stringValue());
1013                     }
1014                 }
1015 
1016                 // pool user_context (6)
1017                 ElementPtr user_context = out_bindings[6]->getJSON();
1018                 if (user_context) {
1019                     last_pool->setContext(user_context);
1020                 }
1021 
1022                 // pool: modification_ts (7)
1023 
1024                 pools.push_back(last_pool);
1025                 pool_ids.push_back(last_pool_id);
1026             }
1027 
1028             // Parse pool specific option (8).
1029             if (last_pool && !out_bindings[8]->amNull() &&
1030                 (last_pool_option_id < out_bindings[8]->getInteger<uint64_t>())) {
1031                 last_pool_option_id = out_bindings[8]->getInteger<uint64_t>();
1032 
1033                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 8);
1034                 if (desc) {
1035                     last_pool->getCfgOption()->add(*desc, desc->space_name_);
1036                 }
1037             }
1038         });
1039     }
1040 
1041     /// @brief Sends query to retrieve multiple pd pools.
1042     ///
1043     /// Query should order pd pools by id.
1044     ///
1045     /// @param index Index of the query to be used.
1046     /// @param in_bindings Input bindings specifying selection criteria. The
1047     /// size of the bindings collection must match the number of placeholders
1048     /// in the prepared statement. The input bindings collection must be empty
1049     /// if the query contains no WHERE clause.
1050     /// @param [out] pd_pools Reference to the container where fetched pools
1051     /// will be inserted.
1052     /// @param [out] pd_pool_ids Identifiers of the pd pools returned in
1053     /// @c pd_pools argument.
getPdPools(const StatementIndex & index,const MySqlBindingCollection & in_bindings,PoolCollection & pd_pools,std::vector<uint64_t> & pd_pool_ids)1054     void getPdPools(const StatementIndex& index,
1055                     const MySqlBindingCollection& in_bindings,
1056                     PoolCollection& pd_pools,
1057                     std::vector<uint64_t>& pd_pool_ids) {
1058         MySqlBindingCollection out_bindings = {
1059             MySqlBinding::createInteger<uint64_t>(), // pd pool: id
1060             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: prefix
1061             MySqlBinding::createInteger<uint8_t>(), // pd pool: prefix_length
1062             MySqlBinding::createInteger<uint8_t>(), // pd pool: delegated_prefix_length
1063             MySqlBinding::createInteger<uint32_t>(), // pd pool: subnet_id
1064             MySqlBinding::createString(POOL_ADDRESS6_BUF_LENGTH), // pd pool: excluded_prefix
1065             MySqlBinding::createInteger<uint8_t>(), // pd pool: excluded_prefix_length
1066             MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // pd pool: client_class
1067             MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // pd pool: require_client_classes
1068             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool: user_context
1069             MySqlBinding::createTimestamp(), // pd pool: modification_ts
1070             MySqlBinding::createInteger<uint64_t>(), // pd pool option: option_id
1071             MySqlBinding::createInteger<uint16_t>(), // pd pool option: code
1072             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // pd pool option: value
1073             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pd pool option: formatted_value
1074             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pd pool option: space
1075             MySqlBinding::createInteger<uint8_t>(), // pd pool option: persistent
1076             MySqlBinding::createInteger<uint32_t>(), // pd pool option: dhcp6_subnet_id
1077             MySqlBinding::createInteger<uint8_t>(), // pd pool option: scope_id
1078             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool option: user_context
1079             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // pd pool option: shared_network_name
1080             MySqlBinding::createInteger<uint64_t>(), // pd pool option: pool_id
1081             MySqlBinding::createTimestamp(), // pd pool option: modification_ts
1082             MySqlBinding::createInteger<uint64_t>() // pd pool option: pd_pool_id
1083         };
1084 
1085         uint64_t last_pd_pool_id = 0;
1086         uint64_t last_pd_pool_option_id = 0;
1087         Pool6Ptr last_pd_pool;
1088 
1089         conn_.selectQuery(index, in_bindings, out_bindings,
1090                           [this, &last_pd_pool_id, &last_pd_pool_option_id,
1091                            &last_pd_pool, &pd_pools, &pd_pool_ids]
1092                           (MySqlBindingCollection& out_bindings) {
1093             if (out_bindings[0]->getInteger<uint64_t>() > last_pd_pool_id) {
1094 
1095                 // pd pool id (0)
1096                 last_pd_pool_id = out_bindings[0]->getInteger<uint64_t>();
1097 
1098                 // pd pool prefix (1)
1099                 // pd pool prefix_length (2)
1100                 // pd pool delegated_prefix_length (3)
1101 
1102                 // pd pool subnet_id (4 / ignored)
1103 
1104                 // excluded_prefix (5) and excluded_prefix_length (6)
1105                 IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS();
1106                 if (!out_bindings[5]->amNull()) {
1107                     excluded_prefix = IOAddress(out_bindings[5]->getString());
1108                 }
1109 
1110                 last_pd_pool = Pool6::create(IOAddress(out_bindings[1]->getString()),
1111                                              out_bindings[2]->getInteger<uint8_t>(),
1112                                              out_bindings[3]->getInteger<uint8_t>(),
1113                                              excluded_prefix,
1114                                              out_bindings[6]->getInteger<uint8_t>());
1115 
1116                 // pd pool client_class (7)
1117                 if (!out_bindings[7]->amNull()) {
1118                     last_pd_pool->allowClientClass(out_bindings[7]->getString());
1119                 }
1120 
1121                 // pd pool require_client_classes (8)
1122                 ElementPtr require_element = out_bindings[8]->getJSON();
1123                 if (require_element) {
1124                     if (require_element->getType() != Element::list) {
1125                         isc_throw(BadValue, "invalid pd pool require_client_classes value "
1126                                   << out_bindings[8]->getString());
1127                     }
1128                     for (auto i = 0; i < require_element->size(); ++i) {
1129                         auto require_item = require_element->get(i);
1130                         if (require_item->getType() != Element::string) {
1131                             isc_throw(BadValue, "elements of pd pool require_client_classes list must"
1132                                       "be valid strings");
1133                         }
1134                         last_pd_pool->requireClientClass(require_item->stringValue());
1135                     }
1136                 }
1137 
1138                 // pd pool user_context (9)
1139                 ElementPtr user_context = out_bindings[9]->getJSON();
1140                 if (user_context) {
1141                     last_pd_pool->setContext(user_context);
1142                 }
1143 
1144                 // pd pool modification_ts (10)
1145 
1146                 pd_pools.push_back(last_pd_pool);
1147                 pd_pool_ids.push_back(last_pd_pool_id);
1148             }
1149 
1150             // Parse pd pool specific option between 11 and 24
1151             if (last_pd_pool && !out_bindings[11]->amNull() &&
1152                 (last_pd_pool_option_id < out_bindings[11]->getInteger<uint64_t>())) {
1153                 last_pd_pool_option_id = out_bindings[11]->getInteger<uint64_t>();
1154 
1155                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 11);
1156                 if (desc) {
1157                     last_pd_pool->getCfgOption()->add(*desc, desc->space_name_);
1158                 }
1159             }
1160         });
1161     }
1162 
1163     /// @brief Sends query to retrieve single pool by address range.
1164     ///
1165     /// @param server_selector Server selector.
1166     /// @param pool_start_address Lower bound pool address.
1167     /// @param pool_end_address Upper bound pool address.
1168     /// @param pool_id Pool identifier for the returned pool.
1169     /// @return Pointer to the pool or null if no such pool found.
getPool6(const ServerSelector & server_selector,const IOAddress & pool_start_address,const IOAddress & pool_end_address,uint64_t & pool_id)1170     Pool6Ptr getPool6(const ServerSelector& server_selector,
1171                       const IOAddress& pool_start_address,
1172                       const IOAddress& pool_end_address,
1173                       uint64_t& pool_id) {
1174         PoolCollection pools;
1175         std::vector<uint64_t> pool_ids;
1176 
1177         if (server_selector.amAny()) {
1178             MySqlBindingCollection in_bindings = {
1179                     MySqlBinding::createString(pool_start_address.toText()),
1180                     MySqlBinding::createString(pool_end_address.toText())
1181             };
1182             getPools(GET_POOL6_RANGE_ANY, in_bindings, pools, pool_ids);
1183 
1184         } else {
1185             auto tags = server_selector.getTags();
1186             for (auto tag : tags) {
1187                 MySqlBindingCollection in_bindings = {
1188                     MySqlBinding::createString(tag.get()),
1189                     MySqlBinding::createString(pool_start_address.toText()),
1190                     MySqlBinding::createString(pool_end_address.toText())
1191                 };
1192                 getPools(GET_POOL6_RANGE, in_bindings, pools, pool_ids);
1193 
1194             }
1195         }
1196 
1197         // Return upon the first pool found.
1198         if (!pools.empty()) {
1199             pool_id = pool_ids[0];
1200             return (boost::dynamic_pointer_cast<Pool6>(*pools.begin()));
1201         }
1202 
1203         pool_id = 0;
1204         return (Pool6Ptr());
1205     }
1206 
1207     /// @brief Sends query to retrieve single pd pool.
1208     ///
1209     /// @param server_selector Server selector.
1210     /// @param pd_pool_prefix Address part of the pd pool prefix.
1211     /// @param pd_pool_prefix_length Length of the pd pool prefix.
1212     /// @param pd_pool_id Pool identifier for the returned pool.
1213     /// @return Pointer to the pool or null if no such pool found.
getPdPool6(const ServerSelector & server_selector,const asiolink::IOAddress & pd_pool_prefix,const uint8_t pd_pool_prefix_length,uint64_t & pd_pool_id)1214     Pool6Ptr getPdPool6(const ServerSelector& server_selector,
1215                         const asiolink::IOAddress& pd_pool_prefix,
1216                         const uint8_t pd_pool_prefix_length,
1217                         uint64_t& pd_pool_id) {
1218         PoolCollection pd_pools;
1219         std::vector<uint64_t> pd_pool_ids;
1220 
1221         if (server_selector.amAny()) {
1222             MySqlBindingCollection in_bindings = {
1223                 MySqlBinding::createString(pd_pool_prefix.toText()),
1224                 MySqlBinding::createInteger<uint8_t>(pd_pool_prefix_length)
1225             };
1226             getPdPools(GET_PD_POOL_ANY, in_bindings, pd_pools, pd_pool_ids);
1227 
1228         } else {
1229             auto tags = server_selector.getTags();
1230             for (auto tag : tags) {
1231                 MySqlBindingCollection in_bindings = {
1232                     MySqlBinding::createString(tag.get()),
1233                     MySqlBinding::createString(pd_pool_prefix.toText()),
1234                     MySqlBinding::createInteger<uint8_t>(pd_pool_prefix_length)
1235                 };
1236                 getPdPools(GET_PD_POOL, in_bindings, pd_pools, pd_pool_ids);
1237             }
1238         }
1239 
1240         if (!pd_pools.empty()) {
1241             pd_pool_id = pd_pool_ids[0];
1242             return (boost::dynamic_pointer_cast<Pool6>(*pd_pools.begin()));
1243         }
1244 
1245         pd_pool_id = 0;
1246 
1247         return (Pool6Ptr());
1248     }
1249 
1250     /// @brief Sends query to insert or update subnet.
1251     ///
1252     /// @param server_selector Server selector.
1253     /// @param subnet Pointer to the subnet to be inserted or updated.
createUpdateSubnet6(const ServerSelector & server_selector,const Subnet6Ptr & subnet)1254     void createUpdateSubnet6(const ServerSelector& server_selector,
1255                              const Subnet6Ptr& subnet) {
1256 
1257         if (server_selector.amAny()) {
1258             isc_throw(InvalidOperation, "creating or updating a subnet for ANY"
1259                       " server is not supported");
1260 
1261         } else if (server_selector.amUnassigned()) {
1262             isc_throw(NotImplemented, "managing configuration for no particular server"
1263                       " (unassigned) is unsupported at the moment");
1264         }
1265 
1266         // Create JSON list of required classes.
1267         ElementPtr required_classes_element = Element::createList();
1268         const auto& required_classes = subnet->getRequiredClasses();
1269         for (auto required_class = required_classes.cbegin();
1270              required_class != required_classes.cend();
1271              ++required_class) {
1272             required_classes_element->add(Element::create(*required_class));
1273         }
1274 
1275         // Create binding for DDNS replace client name mode.
1276         MySqlBindingPtr ddns_rcn_mode_binding;
1277         auto ddns_rcn_mode = subnet->getDdnsReplaceClientNameMode(Network::Inheritance::NONE);
1278         if (!ddns_rcn_mode.unspecified()) {
1279             ddns_rcn_mode_binding = MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>
1280                                                                          (ddns_rcn_mode.get()));
1281         } else {
1282             ddns_rcn_mode_binding = MySqlBinding::createNull();
1283         }
1284 
1285         // Create binding with shared network name if the subnet belongs to a
1286         // shared network.
1287         MySqlBindingPtr shared_network_binding;
1288 
1289         SharedNetwork6Ptr shared_network;
1290         subnet->getSharedNetwork(shared_network);
1291 
1292         // Check if the subnet is associated with a shared network instance.
1293         // If it is, create the binding using the name of the shared network.
1294         if (shared_network) {
1295             shared_network_binding = MySqlBinding::createString(shared_network->getName());
1296 
1297         // If the subnet is associated with a shared network by name (no
1298         // shared network instance), use this name to create the binding.
1299         // This may be the case if the subnet is added as a result of
1300         // receiving a control command that merely specifies shared
1301         // network name. In that case, it is expected that the shared
1302         // network data is already stored in the database.
1303         } else if (!subnet->getSharedNetworkName().empty()) {
1304             shared_network_binding = MySqlBinding::createString(subnet->getSharedNetworkName());
1305 
1306         // If the subnet is not associated with a shared network, create
1307         // null binding.
1308         } else {
1309              shared_network_binding = MySqlBinding::createNull();
1310         }
1311 
1312         // Create the binding holding interface_id.
1313         MySqlBindingPtr interface_id_binding = MySqlBinding::createNull();
1314         auto opt_iface_id = subnet->getInterfaceId(Network::Inheritance::NONE);
1315         if (opt_iface_id) {
1316             auto iface_id_data = opt_iface_id->getData();
1317             if (!iface_id_data.empty()) {
1318                 interface_id_binding = MySqlBinding::createBlob(iface_id_data.begin(),
1319                                                                 iface_id_data.end());
1320             }
1321         }
1322 
1323         // Create input bindings.
1324         MySqlBindingCollection in_bindings = {
1325             MySqlBinding::createInteger<uint32_t>(subnet->getID()),
1326             MySqlBinding::createString(subnet->toText()),
1327             MySqlBinding::condCreateString(subnet->getClientClass(Network::Inheritance::NONE)),
1328             MySqlBinding::condCreateString(subnet->getIface(Network::Inheritance::NONE)),
1329             MySqlBinding::createTimestamp(subnet->getModificationTime()),
1330             createBinding(subnet->getPreferred(Network::Inheritance::NONE)),
1331             createMinBinding(subnet->getPreferred(Network::Inheritance::NONE)),
1332             createMaxBinding(subnet->getPreferred(Network::Inheritance::NONE)),
1333             MySqlBinding::condCreateBool(subnet->getRapidCommit(Network::Inheritance::NONE)),
1334             createBinding(subnet->getT2(Network::Inheritance::NONE)),
1335             createInputRelayBinding(subnet),
1336             createBinding(subnet->getT1(Network::Inheritance::NONE)),
1337             createInputRequiredClassesBinding(subnet),
1338             MySqlBinding::condCreateBool(subnet->getReservationsGlobal(Network::Inheritance::NONE)),
1339             shared_network_binding,
1340             createInputContextBinding(subnet),
1341             createBinding(subnet->getValid(Network::Inheritance::NONE)),
1342             createMinBinding(subnet->getValid(Network::Inheritance::NONE)),
1343             createMaxBinding(subnet->getValid(Network::Inheritance::NONE)),
1344             MySqlBinding::condCreateBool(subnet->getCalculateTeeTimes(Network::Inheritance::NONE)),
1345             MySqlBinding::condCreateFloat(subnet->getT1Percent(Network::Inheritance::NONE)),
1346             MySqlBinding::condCreateFloat(subnet->getT2Percent(Network::Inheritance::NONE)),
1347             interface_id_binding,
1348             MySqlBinding::condCreateBool(subnet->getDdnsSendUpdates(Network::Inheritance::NONE)),
1349             MySqlBinding::condCreateBool(subnet->getDdnsOverrideNoUpdate(Network::Inheritance::NONE)),
1350             MySqlBinding::condCreateBool(subnet->getDdnsOverrideClientUpdate(Network::Inheritance::NONE)),
1351             ddns_rcn_mode_binding,
1352             MySqlBinding::condCreateString(subnet->getDdnsGeneratedPrefix(Network::Inheritance::NONE)),
1353             MySqlBinding::condCreateString(subnet->getDdnsQualifyingSuffix(Network::Inheritance::NONE)),
1354             MySqlBinding::condCreateBool(subnet->getReservationsInSubnet(Network::Inheritance::NONE)),
1355             MySqlBinding::condCreateBool(subnet->getReservationsOutOfPool(Network::Inheritance::NONE)),
1356             MySqlBinding::condCreateFloat(subnet->getCacheThreshold(Network::Inheritance::NONE)),
1357             condCreateInteger<uint32_t>(subnet->getCacheMaxAge(Network::Inheritance::NONE))
1358         };
1359 
1360         MySqlTransaction transaction(conn_);
1361 
1362         // Create scoped audit revision. As long as this instance exists
1363         // no new audit revisions are created in any subsequent calls.
1364         ScopedAuditRevision audit_revision(this,
1365                                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
1366                                            server_selector, "subnet set", true);
1367 
1368         try {
1369 
1370             // Try to insert subnet. If this duplicates unique key, i.e. this
1371             // subnet already exists it will throw DuplicateEntry exception in
1372             // which case we'll try an update.
1373             conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6,
1374                               in_bindings);
1375 
1376         } catch (const DuplicateEntry&) {
1377             deletePools6(subnet);
1378             deletePdPools6(subnet);
1379             deleteOptions6(ServerSelector::ANY(), subnet);
1380 
1381             // Need to add two more bindings for WHERE clause.
1382             in_bindings.push_back(MySqlBinding::createInteger<uint32_t>(subnet->getID()));
1383             in_bindings.push_back(MySqlBinding::createString(subnet->toText()));
1384             conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_SUBNET6,
1385                                     in_bindings);
1386 
1387             MySqlBindingCollection in_server_bindings = {
1388                 MySqlBinding::createInteger<uint32_t>(subnet->getID())
1389             };
1390             conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_SERVER,
1391                                     in_server_bindings);
1392         }
1393 
1394         // Insert associations with the servers.
1395         attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6_SERVER,
1396                                server_selector,
1397                                MySqlBinding::createInteger<uint32_t>(subnet->getID()),
1398                                MySqlBinding::createTimestamp(subnet->getModificationTime()));
1399 
1400         // (Re)create pools.
1401         for (auto pool : subnet->getPools(Lease::TYPE_NA)) {
1402             createPool6(server_selector, boost::dynamic_pointer_cast<Pool6>(pool),
1403                         subnet);
1404         }
1405 
1406         // (Re)create pd pools.
1407         for (auto pd_pool : subnet->getPools(Lease::TYPE_PD)) {
1408             createPdPool6(server_selector, boost::dynamic_pointer_cast<Pool6>(pd_pool),
1409                           subnet);
1410         }
1411 
1412         // (Re)create options.
1413         auto option_spaces = subnet->getCfgOption()->getOptionSpaceNames();
1414         for (auto option_space : option_spaces) {
1415             OptionContainerPtr options = subnet->getCfgOption()->getAll(option_space);
1416             for (auto desc = options->begin(); desc != options->end(); ++desc) {
1417                 OptionDescriptorPtr desc_copy = OptionDescriptor::create(*desc);
1418                 desc_copy->space_name_ = option_space;
1419                 createUpdateOption6(server_selector, subnet->getID(), desc_copy,
1420                                     true);
1421             }
1422         }
1423 
1424         transaction.commit();
1425     }
1426 
1427     /// @brief Inserts new IPv6 pool to the database.
1428     ///
1429     /// @param server_selector Server selector.
1430     /// @param pool Pointer to the pool to be inserted.
1431     /// @param subnet Pointer to the subnet that this pool belongs to.
createPool6(const ServerSelector & server_selector,const Pool6Ptr & pool,const Subnet6Ptr & subnet)1432     void createPool6(const ServerSelector& server_selector, const Pool6Ptr& pool,
1433                      const Subnet6Ptr& subnet) {
1434         MySqlBindingCollection in_bindings = {
1435             MySqlBinding::createString(pool->getFirstAddress().toText()),
1436             MySqlBinding::createString(pool->getLastAddress().toText()),
1437             MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet->getID())),
1438             MySqlBinding::condCreateString(pool->getClientClass()),
1439             createInputRequiredClassesBinding(pool),
1440             createInputContextBinding(pool),
1441             MySqlBinding::createTimestamp(subnet->getModificationTime())
1442         };
1443 
1444         // Run INSERT.
1445         conn_.insertQuery(INSERT_POOL6, in_bindings);
1446 
1447         uint64_t pool_id = mysql_insert_id(conn_.mysql_);
1448         auto option_spaces = pool->getCfgOption()->getOptionSpaceNames();
1449         for (auto option_space : option_spaces) {
1450             OptionContainerPtr options = pool->getCfgOption()->getAll(option_space);
1451             for (auto desc = options->begin(); desc != options->end(); ++desc) {
1452                 OptionDescriptorPtr desc_copy = OptionDescriptor::create(*desc);
1453                 desc_copy->space_name_ = option_space;
1454                 createUpdateOption6(server_selector, Lease::TYPE_NA,
1455                                     pool_id, desc_copy, true);
1456             }
1457         }
1458     }
1459 
1460     /// @brief Inserts new IPv6 pd pool to the database.
1461     ///
1462     /// @param server_selector Server selector.
1463     /// @param pd_pool Pointer to the pd pool to be inserted.
1464     /// @param subnet Pointer to the subnet that this pd pool belongs to.
createPdPool6(const ServerSelector & server_selector,const Pool6Ptr & pd_pool,const Subnet6Ptr & subnet)1465     void createPdPool6(const ServerSelector& server_selector,
1466                        const Pool6Ptr& pd_pool,
1467                        const Subnet6Ptr& subnet) {
1468         int plen = prefixLengthFromRange(pd_pool->getFirstAddress(),
1469                                          pd_pool->getLastAddress());
1470 
1471         // Extract excluded prefix components.
1472         Optional<std::string> xprefix_txt;
1473         uint8_t xlen = 0;
1474         const Option6PDExcludePtr& xopt = pd_pool->getPrefixExcludeOption();
1475         if (xopt) {
1476             const IOAddress& prefix = pd_pool->getFirstAddress();
1477             const IOAddress& xprefix = xopt->getExcludedPrefix(prefix, pd_pool->getLength());
1478             xprefix_txt = xprefix.toText();
1479             xlen = xopt->getExcludedPrefixLength();
1480         }
1481 
1482         MySqlBindingCollection in_bindings = {
1483             MySqlBinding::createString(pd_pool->getFirstAddress().toText()),
1484             MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>(plen)),
1485             MySqlBinding::createInteger<uint8_t>(pd_pool->getLength()),
1486             MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet->getID())),
1487             MySqlBinding::condCreateString(xprefix_txt),
1488             MySqlBinding::createInteger<uint8_t>(xlen),
1489             MySqlBinding::condCreateString(pd_pool->getClientClass()),
1490             createInputRequiredClassesBinding(pd_pool),
1491             createInputContextBinding(pd_pool),
1492             MySqlBinding::createTimestamp(subnet->getModificationTime())
1493         };
1494 
1495         // Run INSERT.
1496         conn_.insertQuery(INSERT_PD_POOL, in_bindings);
1497 
1498         uint64_t pd_pool_id = mysql_insert_id(conn_.mysql_);
1499         auto option_spaces = pd_pool->getCfgOption()->getOptionSpaceNames();
1500         for (auto option_space : option_spaces) {
1501             OptionContainerPtr options = pd_pool->getCfgOption()->getAll(option_space);
1502             for (auto desc = options->begin(); desc != options->end(); ++desc) {
1503                 OptionDescriptorPtr desc_copy = OptionDescriptor::create(*desc);
1504                 desc_copy->space_name_ = option_space;
1505                 createUpdateOption6(server_selector, Lease::TYPE_PD,
1506                                     pd_pool_id, desc_copy, true);
1507             }
1508         }
1509     }
1510 
1511     /// @brief Sends a query to delete data from a table.
1512     ///
1513     /// If creates a new audit revision for this change if such audit
1514     /// revision doesn't exist yet (using ScopedAuditRevision mechanism).
1515     ///
1516     /// @tparam Args type of the arguments to be passed to one of the existing
1517     /// @c deleteFromTable methods.
1518     /// @param server_selector server selector.
1519     /// @param operation operation which results in calling this function. This is
1520     /// used for logging purposes.
1521     /// @param log_message log message to be associated with the audit revision.
1522     /// @param cascade_delete boolean flag indicating if we're performing
1523     /// cascade delete. If set to true, the audit entries for the child
1524     /// objects (e.g. DHCPoptions) won't be created.
1525     /// @param keys arguments to be passed to one of the existing
1526     /// @c deleteFromTable methods.
1527     ///
1528     /// @return Number of deleted entries.
1529     template<typename... Args>
deleteTransactional(const int index,const db::ServerSelector & server_selector,const std::string & operation,const std::string & log_message,const bool cascade_delete,Args &&...keys)1530     uint64_t deleteTransactional(const int index,
1531                                  const db::ServerSelector& server_selector,
1532                                  const std::string& operation,
1533                                  const std::string& log_message,
1534                                  const bool cascade_delete,
1535                                  Args&&... keys) {
1536 
1537         MySqlTransaction transaction(conn_);
1538 
1539         // Create scoped audit revision. As long as this instance exists
1540         // no new audit revisions are created in any subsequent calls.
1541         ScopedAuditRevision
1542             audit_revision(this,
1543                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
1544                            server_selector, log_message, cascade_delete);
1545 
1546         auto count = deleteFromTable(index, server_selector, operation, keys...);
1547 
1548         transaction.commit();
1549 
1550         return (count);
1551     }
1552 
1553     /// @brief Sends query to delete subnet by id.
1554     ///
1555     /// @param server_selector Server selector.
1556     /// @param subnet_id Identifier of the subnet to be deleted.
1557     /// @return Number of deleted subnets.
deleteSubnet6(const ServerSelector & server_selector,const SubnetID & subnet_id)1558     uint64_t deleteSubnet6(const ServerSelector& server_selector,
1559                            const SubnetID& subnet_id) {
1560         int index = (server_selector.amAny() ?
1561                      MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY :
1562                      MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG);
1563         return (deleteTransactional(index, server_selector,
1564                                     "deleting a subnet", "subnet deleted",
1565                                     true, static_cast<uint32_t>(subnet_id)));
1566     }
1567 
1568     /// @brief Sends query to delete subnet by id.
1569     ///
1570     /// @param server_selector Server selector.
1571     /// @param subnet_prefix Prefix of the subnet to be deleted.
1572     /// @return Number of deleted subnets.
deleteSubnet6(const ServerSelector & server_selector,const std::string & subnet_prefix)1573     uint64_t deleteSubnet6(const ServerSelector& server_selector,
1574                            const std::string& subnet_prefix) {
1575         int index = (server_selector.amAny() ?
1576                      MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY :
1577                      MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG);
1578         return (deleteTransactional(index, server_selector,
1579                                     "deleting a subnet", "subnet deleted",
1580                                     true, subnet_prefix));
1581     }
1582 
1583     /// @brief Deletes pools belonging to a subnet from the database.
1584     ///
1585     /// The query deletes all pools associated with the subnet's
1586     /// identifier or prefix.
1587     /// @param subnet Pointer to the subnet for which pools should be
1588     /// deleted.
deletePools6(const Subnet6Ptr & subnet)1589     uint64_t deletePools6(const Subnet6Ptr& subnet) {
1590         MySqlBindingCollection in_bindings = {
1591             MySqlBinding::createInteger<uint32_t>(subnet->getID()),
1592             MySqlBinding::createString(subnet->toText())
1593         };
1594 
1595         // Run DELETE.
1596         return (conn_.updateDeleteQuery(DELETE_POOLS6, in_bindings));
1597     }
1598 
1599     /// @brief Deletes prefix delegation pools belonging to a subnet from
1600     /// the database.
1601     ///
1602     /// The query deletes all pd pools associated with the subnet's
1603     /// identifier or prefix.
1604     /// @param subnet Pointer to the subnet for which pd pools should be
1605     /// deleted.
deletePdPools6(const Subnet6Ptr & subnet)1606     uint64_t deletePdPools6(const Subnet6Ptr& subnet) {
1607         MySqlBindingCollection in_bindings = {
1608             MySqlBinding::createInteger<uint32_t>(subnet->getID()),
1609             MySqlBinding::createString(subnet->toText())
1610         };
1611 
1612         // Run DELETE.
1613         return (conn_.updateDeleteQuery(DELETE_PD_POOLS, in_bindings));
1614     }
1615 
1616     /// @brief Sends query to the database to retrieve multiple shared
1617     /// networks.
1618     ///
1619     /// Query should order shared networks by id.
1620     ///
1621     /// @param index Index of the query to be used.
1622     /// @param server_selector Server selector.
1623     /// @param in_bindings Input bindings specifying selection criteria. The
1624     /// size of the bindings collection must match the number of placeholders
1625     /// in the prepared statement. The input bindings collection must be empty
1626     /// if the query contains no WHERE clause.
1627     /// @param [out] shared_networks Reference to the container where fetched
1628     /// shared networks will be inserted.
getSharedNetworks6(const StatementIndex & index,const ServerSelector & server_selector,const MySqlBindingCollection & in_bindings,SharedNetwork6Collection & shared_networks)1629     void getSharedNetworks6(const StatementIndex& index,
1630                             const ServerSelector& server_selector,
1631                             const MySqlBindingCollection& in_bindings,
1632                             SharedNetwork6Collection& shared_networks) {
1633         // Create output bindings. The order must match that in the prepared
1634         // statement. Please put comments only at the end of line so
1635         // line counting and indexing match.
1636         // The server tag must be the last field.
1637         MySqlBindingCollection out_bindings = {
1638             MySqlBinding::createInteger<uint64_t>(), // id
1639             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // name
1640             MySqlBinding::createString(CLIENT_CLASS_BUF_LENGTH), // client_class
1641             MySqlBinding::createString(INTERFACE_BUF_LENGTH), // interface
1642             MySqlBinding::createTimestamp(), // modification_ts
1643             MySqlBinding::createInteger<uint32_t>(), // preferred_lifetime
1644             MySqlBinding::createInteger<uint8_t>(), // rapid_commit
1645             MySqlBinding::createInteger<uint32_t>(), // rebind_timer
1646             MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
1647             MySqlBinding::createInteger<uint32_t>(), // renew_timer
1648             MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
1649             MySqlBinding::createInteger<uint8_t>(), // reservations_global
1650             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
1651             MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
1652             MySqlBinding::createInteger<uint64_t>(), // option: option_id
1653             MySqlBinding::createInteger<uint16_t>(), // option: code
1654             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // option: value
1655             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
1656             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
1657             MySqlBinding::createInteger<uint8_t>(), // option: persistent
1658             MySqlBinding::createInteger<uint32_t>(), // option: dhcp6_subnet_id
1659             MySqlBinding::createInteger<uint8_t>(), // option: scope_id
1660             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
1661             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
1662             MySqlBinding::createInteger<uint64_t>(), // option: pool_id
1663             MySqlBinding::createTimestamp(), // option: modification_ts
1664             MySqlBinding::createInteger<uint64_t>(), // option: pd_pool_id
1665             MySqlBinding::createInteger<uint8_t>(), // calculate_tee_times
1666             MySqlBinding::createInteger<float>(), // t1_percent
1667             MySqlBinding::createInteger<float>(), // t2_percent
1668             MySqlBinding::createBlob(INTERFACE_ID_BUF_LENGTH), // interface_id
1669             MySqlBinding::createInteger<uint32_t>(), // min_preferred_lifetime
1670             MySqlBinding::createInteger<uint32_t>(), // max_preferred_lifetime
1671             MySqlBinding::createInteger<uint32_t>(), // min_valid_lifetime
1672             MySqlBinding::createInteger<uint32_t>(), // max_valid_lifetime
1673             MySqlBinding::createInteger<uint8_t>(), // ddns_send_updates
1674             MySqlBinding::createInteger<uint8_t>(), // ddns_override_no_update
1675             MySqlBinding::createInteger<uint8_t>(), // ddns_override_client_update
1676             MySqlBinding::createInteger<uint8_t>(), // ddns_replace_client_name
1677             MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_generated_prefix
1678             MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_qualifying_suffix
1679             MySqlBinding::createInteger<uint8_t>(), // reservations_in_subnet
1680             MySqlBinding::createInteger<uint8_t>(), // reservations_out_of_pool
1681             MySqlBinding::createInteger<float>(), // cache_threshold
1682             MySqlBinding::createInteger<uint32_t>(), // cache_max_age
1683             MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
1684         };
1685 
1686         uint64_t last_network_id = 0;
1687         uint64_t last_option_id = 0;
1688         std::string last_tag;
1689 
1690         conn_.selectQuery(index, in_bindings, out_bindings,
1691                           [this, &shared_networks, &last_network_id, &last_option_id,
1692                            &last_tag]
1693                           (MySqlBindingCollection& out_bindings) {
1694             SharedNetwork6Ptr last_network;
1695             if (!shared_networks.empty()) {
1696                 last_network = *shared_networks.rbegin();
1697             }
1698 
1699             // If this is the first shared network or the shared network id in this
1700             // row points to the next shared network we use the data in the
1701             // row to create the new shared network instance.
1702             if (last_network_id != out_bindings[0]->getInteger<uint64_t>()) {
1703 
1704                 // Reset per shared network component tracking and server tag because
1705                 // we're now starting to process a new shared network.
1706                 last_option_id = 0;
1707                 last_tag.clear();
1708 
1709                 // id at 0.
1710                 last_network_id = out_bindings[0]->getInteger<uint64_t>();
1711 
1712                 // name at 1.
1713                 last_network = SharedNetwork6::create(out_bindings[1]->getString());
1714                 last_network->setId(last_network_id);
1715 
1716                 // client_class at 2.
1717                 if (!out_bindings[2]->amNull()) {
1718                     last_network->allowClientClass(out_bindings[2]->getString());
1719                 }
1720 
1721                 // interface at 3.
1722                 if (!out_bindings[3]->amNull()) {
1723                     last_network->setIface(out_bindings[3]->getString());
1724                 }
1725 
1726                 // modification_ts at 4.
1727                 last_network->setModificationTime(out_bindings[4]->getTimestamp());
1728 
1729                 // preferred_lifetime at 5.
1730                 // min_preferred_lifetime at 31.
1731                 // max_preferred_lifetime at 32.
1732                 if (!out_bindings[5]->amNull()) {
1733                     last_network->setPreferred(createTriplet(out_bindings[5],
1734                                                          out_bindings[31],
1735                                                          out_bindings[32]));
1736                 }
1737 
1738                 // rapid_commit at 6.
1739                 if (!out_bindings[6]->amNull()) {
1740                     last_network->setRapidCommit(out_bindings[6]->getBool());
1741                 }
1742 
1743                 // rebind_timer at 7.
1744                 if (!out_bindings[7]->amNull()) {
1745                     last_network->setT2(createTriplet(out_bindings[7]));
1746                 }
1747 
1748                 // relay at 8.
1749                 ElementPtr relay_element = out_bindings[8]->getJSON();
1750                 if (relay_element) {
1751                     if (relay_element->getType() != Element::list) {
1752                         isc_throw(BadValue, "invalid relay value "
1753                                   << out_bindings[8]->getString());
1754                     }
1755                     for (auto i = 0; i < relay_element->size(); ++i) {
1756                         auto relay_address_element = relay_element->get(i);
1757                         if (relay_address_element->getType() != Element::string) {
1758                             isc_throw(BadValue, "relay address must be a string");
1759                         }
1760                         last_network->addRelayAddress(IOAddress(relay_element->get(i)->stringValue()));
1761                     }
1762                 }
1763 
1764                 // renew_timer at 9.
1765                 if (!out_bindings[9]->amNull()) {
1766                     last_network->setT1(createTriplet(out_bindings[9]));
1767                 }
1768 
1769                 // require_client_classes at 10.
1770                 ElementPtr require_element = out_bindings[10]->getJSON();
1771                 if (require_element) {
1772                     if (require_element->getType() != Element::list) {
1773                         isc_throw(BadValue, "invalid require_client_classes value "
1774                               << out_bindings[10]->getString());
1775                     }
1776                     for (auto i = 0; i < require_element->size(); ++i) {
1777                         auto require_item = require_element->get(i);
1778                         if (require_item->getType() != Element::string) {
1779                             isc_throw(BadValue, "elements of require_client_classes list must"
1780                                       "be valid strings");
1781                         }
1782                         last_network->requireClientClass(require_item->stringValue());
1783                     }
1784                 }
1785 
1786                 // reservations_global at 11.
1787                 if (!out_bindings[11]->amNull()) {
1788                     last_network->setReservationsGlobal(out_bindings[11]->getBool());
1789                 }
1790 
1791                 // user_context at 12.
1792                 ElementPtr user_context = out_bindings[12]->getJSON();
1793                 if (user_context) {
1794                     last_network->setContext(user_context);
1795                 }
1796 
1797                 // valid_lifetime at 13.
1798                 // min_valid_lifetime at 33.
1799                 // max_valid_lifetime at 34.
1800                 if (!out_bindings[13]->amNull()) {
1801                     last_network->setValid(createTriplet(out_bindings[13],
1802                                                          out_bindings[33],
1803                                                          out_bindings[34]));
1804                 }
1805 
1806                 // 14 to 26 are option.
1807 
1808                 // calculate_tee_times at 27.
1809                 if (!out_bindings[27]->amNull()) {
1810                     last_network->setCalculateTeeTimes(out_bindings[27]->getBool());
1811                 }
1812 
1813                 // t1_percent at 28.
1814                 if (!out_bindings[28]->amNull()) {
1815                     last_network->setT1Percent(out_bindings[28]->getFloat());
1816                 }
1817 
1818                 // t2_percent at 29.
1819                 if (!out_bindings[29]->amNull()) {
1820                     last_network->setT2Percent(out_bindings[29]->getFloat());
1821                 }
1822 
1823                 // interface_id at 30.
1824                 if (!out_bindings[30]->amNull()) {
1825                     auto iface_id_data = out_bindings[30]->getBlob();
1826                     if (!iface_id_data.empty()) {
1827                         OptionPtr opt_iface_id(new Option(Option::V6, D6O_INTERFACE_ID,
1828                                                           iface_id_data));
1829                         last_network->setInterfaceId(opt_iface_id);
1830                     }
1831                 }
1832 
1833                 // min_preferred_lifetime at 31.
1834                 // max_preferred_lifetime at 32.
1835                 // min_valid_lifetime at 33.
1836                 // max_valid_lifetime at 34.
1837 
1838                 // ddns_send_updates at 35.
1839                 if (!out_bindings[35]->amNull()) {
1840                     last_network->setDdnsSendUpdates(out_bindings[35]->getBool());
1841                 }
1842 
1843                 // ddns_override_no_update at 36.
1844                 if (!out_bindings[36]->amNull()) {
1845                     last_network->setDdnsOverrideNoUpdate(out_bindings[36]->getBool());
1846                 }
1847 
1848                 // ddns_override_client_update at 37.
1849                 if (!out_bindings[37]->amNull()) {
1850                     last_network->setDdnsOverrideClientUpdate(out_bindings[37]->getBool());
1851                 }
1852 
1853                 // ddns_replace_client_name at 38.
1854                 if (!out_bindings[38]->amNull()) {
1855                     last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
1856                         (out_bindings[38]->getInteger<uint8_t>()));
1857                 }
1858 
1859                 // ddns_generated_prefix at 39.
1860                 if (!out_bindings[39]->amNull()) {
1861                     last_network->setDdnsGeneratedPrefix(out_bindings[39]->getString());
1862                 }
1863 
1864                 // ddns_qualifying_suffix at 40.
1865                 if (!out_bindings[40]->amNull()) {
1866                     last_network->setDdnsQualifyingSuffix(out_bindings[40]->getString());
1867                 }
1868 
1869                 // reservations_in_subnet at 41.
1870                 if (!out_bindings[41]->amNull()) {
1871                     last_network->setReservationsInSubnet(out_bindings[41]->getBool());
1872                 }
1873 
1874                 // reservations_in_subnet at 42.
1875                 if (!out_bindings[42]->amNull()) {
1876                     last_network->setReservationsOutOfPool(out_bindings[42]->getBool());
1877                 }
1878 
1879                 // cache_threshold at 43.
1880                 if (!out_bindings[43]->amNull()) {
1881                     last_network->setCacheThreshold(out_bindings[43]->getFloat());
1882                 }
1883 
1884                 // cache_max_age at 44.
1885                 if (!out_bindings[44]->amNull()) {
1886                     last_network->setCacheMaxAge(out_bindings[44]->getInteger<uint32_t>());
1887                 }
1888 
1889                 // server_tag at 45.
1890 
1891                 // Add the shared network.
1892                 auto ret = shared_networks.push_back(last_network);
1893 
1894                 // shared_networks is a multi index container with an unique
1895                 // index but this index is unique too in the database,
1896                 // so this is for sanity only.
1897                 if (!ret.second) {
1898                     isc_throw(Unexpected, "add shared network failed");
1899                 }
1900             }
1901 
1902             // Parse option from 14 to 26.
1903             if (!out_bindings[14]->amNull() &&
1904                 (last_option_id < out_bindings[14]->getInteger<uint64_t>())) {
1905                 last_option_id = out_bindings[14]->getInteger<uint64_t>();
1906 
1907                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 14);
1908                 if (desc) {
1909                     last_network->getCfgOption()->add(*desc, desc->space_name_);
1910                 }
1911             }
1912 
1913             // Check for new server tags.
1914             if (!out_bindings[45]->amNull() &&
1915                 (last_tag != out_bindings[45]->getString())) {
1916                 last_tag = out_bindings[45]->getString();
1917                 if (!last_tag.empty() && !last_network->hasServerTag(ServerTag(last_tag))) {
1918                     last_network->setServerTag(last_tag);
1919                 }
1920             }
1921         });
1922 
1923         // Now that we're done fetching the whole network, we have to
1924         // check if it has matching server tags and toss it if it
1925         // doesn't. We skip matching the server tags if we're asking
1926         // for ANY shared network.
1927         auto& sn_index = shared_networks.get<SharedNetworkRandomAccessIndexTag>();
1928         tossNonMatchingElements(server_selector, sn_index);
1929     }
1930 
1931     /// @brief Sends query to retrieve single shared network by name.
1932     ///
1933     /// @param server_selector Server selector.
1934     /// @param name Shared network name.
1935     ///
1936     /// @return Pointer to the returned shared network or NULL if such shared
1937     /// network doesn't exist.
getSharedNetwork6(const ServerSelector & server_selector,const std::string & name)1938     SharedNetwork6Ptr getSharedNetwork6(const ServerSelector& server_selector,
1939                                         const std::string& name) {
1940 
1941         if (server_selector.hasMultipleTags()) {
1942             isc_throw(InvalidOperation, "expected one server tag to be specified"
1943                       " while fetching a shared network. Got: "
1944                       << getServerTagsAsText(server_selector));
1945         }
1946 
1947         MySqlBindingCollection in_bindings = { MySqlBinding::createString(name) };
1948 
1949         auto index = GET_SHARED_NETWORK6_NAME_NO_TAG;
1950 
1951         if (server_selector.amUnassigned()) {
1952             index = GET_SHARED_NETWORK6_NAME_UNASSIGNED;
1953 
1954         } else if (server_selector.amAny()) {
1955             index = GET_SHARED_NETWORK6_NAME_ANY;
1956         }
1957 
1958         SharedNetwork6Collection shared_networks;
1959         getSharedNetworks6(index, server_selector, in_bindings, shared_networks);
1960 
1961         return (shared_networks.empty() ? SharedNetwork6Ptr() : *shared_networks.begin());
1962     }
1963 
1964     /// @brief Sends query to retrieve all shared networks.
1965     ///
1966     /// @param server_selector Server selector.
1967     /// @param [out] shared_networks Reference to the shared networks collection
1968     /// structure where shared networks should be inserted.
getAllSharedNetworks6(const ServerSelector & server_selector,SharedNetwork6Collection & shared_networks)1969     void getAllSharedNetworks6(const ServerSelector& server_selector,
1970                                SharedNetwork6Collection& shared_networks) {
1971         if (server_selector.amAny()) {
1972             isc_throw(InvalidOperation, "fetching all shared networks for ANY "
1973                       "server is not supported");
1974         }
1975 
1976         auto index = (server_selector.amUnassigned() ? GET_ALL_SHARED_NETWORKS6_UNASSIGNED :
1977                       GET_ALL_SHARED_NETWORKS6);
1978         MySqlBindingCollection in_bindings;
1979         getSharedNetworks6(index, server_selector, in_bindings, shared_networks);
1980     }
1981 
1982     /// @brief Sends query to retrieve modified shared networks.
1983     ///
1984     /// @param server_selector Server selector.
1985     /// @param modification_ts Lower bound modification timestamp.
1986     /// @param [out] shared_networks Reference to the shared networks collection
1987     /// structure where shared networks should be inserted.
getModifiedSharedNetworks6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_ts,SharedNetwork6Collection & shared_networks)1988     void getModifiedSharedNetworks6(const ServerSelector& server_selector,
1989                                     const boost::posix_time::ptime& modification_ts,
1990                                     SharedNetwork6Collection& shared_networks) {
1991         if (server_selector.amAny()) {
1992             isc_throw(InvalidOperation, "fetching modified shared networks for ANY "
1993                       "server is not supported");
1994         }
1995 
1996         MySqlBindingCollection in_bindings = {
1997             MySqlBinding::createTimestamp(modification_ts)
1998         };
1999 
2000         auto index = (server_selector.amUnassigned() ? GET_MODIFIED_SHARED_NETWORKS6_UNASSIGNED :
2001                       GET_MODIFIED_SHARED_NETWORKS6);
2002         getSharedNetworks6(index, server_selector, in_bindings, shared_networks);
2003     }
2004 
2005     /// @brief Sends query to insert or update shared network.
2006     ///
2007     /// @param server_selector Server selector.
2008     /// @param subnet Pointer to the shared network to be inserted or updated.
createUpdateSharedNetwork6(const ServerSelector & server_selector,const SharedNetwork6Ptr & shared_network)2009     void createUpdateSharedNetwork6(const ServerSelector& server_selector,
2010                                     const SharedNetwork6Ptr& shared_network) {
2011 
2012         if (server_selector.amAny()) {
2013             isc_throw(InvalidOperation, "creating or updating a shared network for ANY"
2014                       " server is not supported");
2015 
2016         } else if (server_selector.amUnassigned()) {
2017             isc_throw(NotImplemented, "managing configuration for no particular server"
2018                       " (unassigned) is unsupported at the moment");
2019         }
2020 
2021         // Create the binding holding interface_id.
2022         MySqlBindingPtr interface_id_binding = MySqlBinding::createNull();
2023         auto opt_iface_id = shared_network->getInterfaceId(Network::Inheritance::NONE);
2024         if (opt_iface_id) {
2025             auto iface_id_data = opt_iface_id->getData();
2026             if (!iface_id_data.empty()) {
2027                 interface_id_binding = MySqlBinding::createBlob(iface_id_data.begin(),
2028                                                                 iface_id_data.end());
2029             }
2030         }
2031 
2032         // Create binding for DDNS replace client name mode.
2033         MySqlBindingPtr ddns_rcn_mode_binding;
2034         auto ddns_rcn_mode = shared_network->getDdnsReplaceClientNameMode(Network::Inheritance::NONE);
2035         if (!ddns_rcn_mode.unspecified()) {
2036             ddns_rcn_mode_binding = MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>
2037                                                                          (ddns_rcn_mode.get()));
2038         } else {
2039             ddns_rcn_mode_binding = MySqlBinding::createNull();
2040         }
2041 
2042         MySqlBindingCollection in_bindings = {
2043             MySqlBinding::createString(shared_network->getName()),
2044             MySqlBinding::condCreateString(shared_network->getClientClass(Network::Inheritance::NONE)),
2045             MySqlBinding::condCreateString(shared_network->getIface(Network::Inheritance::NONE)),
2046             MySqlBinding::createTimestamp(shared_network->getModificationTime()),
2047             createBinding(shared_network->getPreferred(Network::Inheritance::NONE)),
2048             createMinBinding(shared_network->getPreferred(Network::Inheritance::NONE)),
2049             createMaxBinding(shared_network->getPreferred(Network::Inheritance::NONE)),
2050             MySqlBinding::condCreateBool(shared_network->getRapidCommit(Network::Inheritance::NONE)),
2051             createBinding(shared_network->getT2(Network::Inheritance::NONE)),
2052             createInputRelayBinding(shared_network),
2053             createBinding(shared_network->getT1(Network::Inheritance::NONE)),
2054             createInputRequiredClassesBinding(shared_network),
2055             MySqlBinding::condCreateBool(shared_network->getReservationsGlobal(Network::Inheritance::NONE)),
2056             createInputContextBinding(shared_network),
2057             createBinding(shared_network->getValid(Network::Inheritance::NONE)),
2058             createMinBinding(shared_network->getValid(Network::Inheritance::NONE)),
2059             createMaxBinding(shared_network->getValid(Network::Inheritance::NONE)),
2060             MySqlBinding::condCreateBool(shared_network->getCalculateTeeTimes(Network::Inheritance::NONE)),
2061             MySqlBinding::condCreateFloat(shared_network->getT1Percent(Network::Inheritance::NONE)),
2062             MySqlBinding::condCreateFloat(shared_network->getT2Percent(Network::Inheritance::NONE)),
2063             interface_id_binding,
2064             MySqlBinding::condCreateBool(shared_network->getDdnsSendUpdates(Network::Inheritance::NONE)),
2065             MySqlBinding::condCreateBool(shared_network->getDdnsOverrideNoUpdate(Network::Inheritance::NONE)),
2066             MySqlBinding::condCreateBool(shared_network->getDdnsOverrideClientUpdate(Network::Inheritance::NONE)),
2067             ddns_rcn_mode_binding,
2068             MySqlBinding::condCreateString(shared_network->getDdnsGeneratedPrefix(Network::Inheritance::NONE)),
2069             MySqlBinding::condCreateString(shared_network->getDdnsQualifyingSuffix(Network::Inheritance::NONE)),
2070             MySqlBinding::condCreateBool(shared_network->getReservationsInSubnet(Network::Inheritance::NONE)),
2071             MySqlBinding::condCreateBool(shared_network->getReservationsOutOfPool(Network::Inheritance::NONE)),
2072             MySqlBinding::condCreateFloat(shared_network->getCacheThreshold(Network::Inheritance::NONE)),
2073             condCreateInteger<uint32_t>(shared_network->getCacheMaxAge(Network::Inheritance::NONE))
2074         };
2075 
2076         MySqlTransaction transaction(conn_);
2077 
2078         // Create scoped audit revision. As long as this instance exists
2079         // no new audit revisions are created in any subsequent calls.
2080         ScopedAuditRevision
2081             audit_revision(this,
2082                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2083                            server_selector, "shared network set", true);
2084 
2085         try {
2086 
2087             // Try to insert shared network. The shared network name must be unique,
2088             // so if inserting fails with DuplicateEntry exception we'll need to
2089             // update existing shared network entry.
2090             conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6,
2091                               in_bindings);
2092 
2093         } catch (const DuplicateEntry&) {
2094             deleteOptions6(ServerSelector::ANY(), shared_network);
2095 
2096             // Need to add one more binding for WHERE clause.
2097             in_bindings.push_back(MySqlBinding::createString(shared_network->getName()));
2098             conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_SHARED_NETWORK6,
2099                                     in_bindings);
2100 
2101             MySqlBindingCollection in_server_bindings = {
2102                 MySqlBinding::createString(shared_network->getName())
2103             };
2104             conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_SERVER,
2105                                     in_server_bindings);
2106 
2107         }
2108 
2109         attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6_SERVER,
2110                                server_selector,
2111                                MySqlBinding::createString(shared_network->getName()),
2112                                MySqlBinding::createTimestamp(shared_network->getModificationTime()));
2113 
2114         // (Re)create options.
2115         auto option_spaces = shared_network->getCfgOption()->getOptionSpaceNames();
2116         for (auto option_space : option_spaces) {
2117             OptionContainerPtr options = shared_network->getCfgOption()->getAll(option_space);
2118             for (auto desc = options->begin(); desc != options->end(); ++desc) {
2119                 OptionDescriptorPtr desc_copy = OptionDescriptor::create(*desc);
2120                 desc_copy->space_name_ = option_space;
2121                 createUpdateOption6(server_selector, shared_network->getName(),
2122                                     desc_copy, true);
2123             }
2124         }
2125 
2126         transaction.commit();
2127     }
2128 
2129 
2130     /// @brief Sends query to insert DHCP option.
2131     ///
2132     /// This method expects that the server selector contains exactly one
2133     /// server tag.
2134     ///
2135     /// @param server_selector Server selector.
2136     /// @param in_bindings Collection of bindings representing an option.
insertOption6(const ServerSelector & server_selector,const MySqlBindingCollection & in_bindings)2137     void insertOption6(const ServerSelector& server_selector,
2138                        const MySqlBindingCollection& in_bindings) {
2139         conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_OPTION6,
2140                           in_bindings);
2141 
2142         // Fetch primary key value of the inserted option. We will use it in the
2143         // next INSERT statement to associate this option with the server.
2144         auto option_id = mysql_insert_id(conn_.mysql_);
2145 
2146         // Timestamp is expected to be in this input binding.
2147         auto timestamp_binding = in_bindings[11];
2148 
2149         // Associate the option with the servers.
2150         attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_OPTION6_SERVER,
2151                                server_selector,
2152                                MySqlBinding::createInteger<uint64_t>(option_id),
2153                                timestamp_binding);
2154     }
2155 
2156     /// @brief Sends query to insert or update global DHCP option.
2157     ///
2158     /// @param server_selector Server selector.
2159     /// @param option Pointer to the option descriptor encapsulating the option.
createUpdateOption6(const ServerSelector & server_selector,const OptionDescriptorPtr & option)2160     void createUpdateOption6(const ServerSelector& server_selector,
2161                              const OptionDescriptorPtr& option) {
2162 
2163         if (server_selector.amUnassigned()) {
2164             isc_throw(NotImplemented, "managing configuration for no particular server"
2165                       " (unassigned) is unsupported at the moment");
2166         }
2167 
2168         auto tag = getServerTag(server_selector, "creating or updating global option");
2169 
2170         MySqlBindingCollection in_bindings = {
2171             MySqlBinding::createInteger<uint16_t>(option->option_->getType()),
2172             createOptionValueBinding(option),
2173             MySqlBinding::condCreateString(option->formatted_value_),
2174             MySqlBinding::condCreateString(option->space_name_),
2175             MySqlBinding::createBool(option->persistent_),
2176             MySqlBinding::createNull(),
2177             MySqlBinding::createNull(),
2178             MySqlBinding::createInteger<uint8_t>(0),
2179             createInputContextBinding(option),
2180             MySqlBinding::createNull(),
2181             MySqlBinding::createNull(),
2182             MySqlBinding::createTimestamp(option->getModificationTime()),
2183             MySqlBinding::createNull(),
2184             MySqlBinding::createString(tag),
2185             MySqlBinding::createInteger<uint8_t>(option->option_->getType()),
2186             MySqlBinding::condCreateString(option->space_name_)
2187         };
2188 
2189         MySqlTransaction transaction(conn_);
2190 
2191         // Create scoped audit revision. As long as this instance exists
2192         // no new audit revisions are created in any subsequent calls.
2193         ScopedAuditRevision
2194             audit_revision(this,
2195                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2196                            server_selector, "global option set", false);
2197 
2198         if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6,
2199                                     in_bindings) == 0) {
2200             // Remove the 3 bindings used only in case of update.
2201             in_bindings.resize(in_bindings.size() - 3);
2202             insertOption6(server_selector, in_bindings);
2203         }
2204 
2205         transaction.commit();
2206     }
2207 
2208     /// @brief Sends query to insert or update DHCP option in a subnet.
2209     ///
2210     /// @param server_selector Server selector.
2211     /// @param subnet_id Identifier of the subnet the option belongs to.
2212     /// @param option Pointer to the option descriptor encapsulating the option.
2213     /// @param cascade_update Boolean value indicating whether the update is
2214     /// performed as part of the owning element, e.g. subnet.
createUpdateOption6(const ServerSelector & server_selector,const SubnetID & subnet_id,const OptionDescriptorPtr & option,const bool cascade_update)2215     void createUpdateOption6(const ServerSelector& server_selector,
2216                              const SubnetID& subnet_id,
2217                              const OptionDescriptorPtr& option,
2218                              const bool cascade_update) {
2219 
2220         if (server_selector.amUnassigned()) {
2221             isc_throw(NotImplemented, "managing configuration for no particular server"
2222                       " (unassigned) is unsupported at the moment");
2223         }
2224 
2225         MySqlBindingCollection in_bindings = {
2226             MySqlBinding::createInteger<uint16_t>(option->option_->getType()),
2227             createOptionValueBinding(option),
2228             MySqlBinding::condCreateString(option->formatted_value_),
2229             MySqlBinding::condCreateString(option->space_name_),
2230             MySqlBinding::createBool(option->persistent_),
2231             MySqlBinding::createNull(),
2232             MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet_id)),
2233             MySqlBinding::createInteger<uint8_t>(1),
2234             createInputContextBinding(option),
2235             MySqlBinding::createNull(),
2236             MySqlBinding::createNull(),
2237             MySqlBinding::createTimestamp(option->getModificationTime()),
2238             MySqlBinding::createNull(),
2239             MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet_id)),
2240             MySqlBinding::createInteger<uint16_t>(option->option_->getType()),
2241             MySqlBinding::condCreateString(option->space_name_)
2242         };
2243 
2244         boost::scoped_ptr<MySqlTransaction> transaction;
2245         // Only start new transaction if specified to do so. This function may
2246         // be called from within an existing transaction in which case we
2247         // don't start the new one.
2248         if (!cascade_update) {
2249             transaction.reset(new MySqlTransaction(conn_));
2250         }
2251 
2252         // Create scoped audit revision. As long as this instance exists
2253         // no new audit revisions are created in any subsequent calls.
2254         ScopedAuditRevision
2255             audit_revision(this,
2256                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2257                            server_selector, "subnet specific option set",
2258                            cascade_update);
2259 
2260         if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SUBNET_ID,
2261                                     in_bindings) == 0) {
2262             // Remove the 3 bindings used only in case of update.
2263             in_bindings.resize(in_bindings.size() - 3);
2264             insertOption6(server_selector, in_bindings);
2265         }
2266 
2267         if (transaction) {
2268             transaction->commit();
2269         }
2270     }
2271 
2272     /// @brief Sends query to insert or update DHCP option in a pool.
2273     ///
2274     /// @param server_selector Server selector.
2275     /// @param pool_start_address Lower bound address of the pool.
2276     /// @param pool_end_address Upper bound address of the pool.
2277     /// @param option Pointer to the option descriptor encapsulating the option.
createUpdateOption6(const ServerSelector & server_selector,const IOAddress & pool_start_address,const IOAddress & pool_end_address,const OptionDescriptorPtr & option)2278     void createUpdateOption6(const ServerSelector& server_selector,
2279                              const IOAddress& pool_start_address,
2280                              const IOAddress& pool_end_address,
2281                              const OptionDescriptorPtr& option) {
2282         uint64_t pool_id = 0;
2283         Pool6Ptr pool = getPool6(server_selector, pool_start_address, pool_end_address,
2284                                  pool_id);
2285         if (!pool) {
2286             isc_throw(BadValue, "no pool found for range of "
2287                       << pool_start_address << " : "
2288                       << pool_end_address);
2289         }
2290 
2291         createUpdateOption6(server_selector, Lease::TYPE_NA,
2292                             pool_id, option, false);
2293     }
2294 
2295 
2296     /// @brief Sends query to insert or update DHCP option in a pd pool.
2297     ///
2298     /// @param server_selector Server selector.
2299     /// @param pd_pool_prefix Address part of the pd pool prefix.
2300     /// @param pd_pool_prefix_length Length of the pd pool prefix.
2301     /// @param option Pointer to the option descriptor encapsulating the option.
createUpdateOption6(const ServerSelector & server_selector,const asiolink::IOAddress & pd_pool_prefix,const uint8_t pd_pool_prefix_length,const OptionDescriptorPtr & option)2302     void createUpdateOption6(const ServerSelector& server_selector,
2303                              const asiolink::IOAddress& pd_pool_prefix,
2304                              const uint8_t pd_pool_prefix_length,
2305                              const OptionDescriptorPtr& option) {
2306         uint64_t pd_pool_id = 0;
2307         Pool6Ptr pd_pool = getPdPool6(server_selector,
2308                                       pd_pool_prefix,
2309                                       pd_pool_prefix_length,
2310                                       pd_pool_id);
2311         if (!pd_pool) {
2312             isc_throw(BadValue, "no prefix delegation pool found for prefix "
2313                       << "of " << pd_pool_prefix << "/"
2314                       << static_cast<unsigned>(pd_pool_prefix_length));
2315         }
2316 
2317         createUpdateOption6(server_selector, Lease::TYPE_PD,
2318                             pd_pool_id, option, false);
2319     }
2320 
2321 
2322     /// @brief Sends query to insert or update DHCP option in an address
2323     /// or prefix delegation pool.
2324     ///
2325     /// @param selector Server selector.
2326     /// @param pool_type Pool type (Lease::TYPE_NA or Lease::TYPE_PD).
2327     /// @param pool_id Identifier of the address or prefix delegation pool
2328     /// the option belongs to.
2329     /// @param option Pointer to the option descriptor encapsulating the option.
2330     /// @param cascade_update Boolean value indicating whether the update is
2331     /// performed as part of the owning element, e.g. subnet.
createUpdateOption6(const ServerSelector & server_selector,const Lease::Type & pool_type,const uint64_t pool_id,const OptionDescriptorPtr & option,const bool cascade_update)2332     void createUpdateOption6(const ServerSelector& server_selector,
2333                              const Lease::Type& pool_type,
2334                              const uint64_t pool_id,
2335                              const OptionDescriptorPtr& option,
2336                              const bool cascade_update) {
2337 
2338         if (server_selector.amUnassigned()) {
2339             isc_throw(NotImplemented, "managing configuration for no particular server"
2340                       " (unassigned) is unsupported at the moment");
2341         }
2342 
2343         std::string msg = "creating or updating ";
2344         if (pool_type == Lease::TYPE_PD) {
2345             msg += "prefix delegation";
2346         } else {
2347             msg += "address";
2348         }
2349         msg += " pool level option";
2350 
2351         MySqlBindingCollection in_bindings;
2352         // code
2353         in_bindings.push_back(MySqlBinding::createInteger<uint16_t>(option->option_->getType()));
2354         // value
2355         in_bindings.push_back(createOptionValueBinding(option));
2356         // formatted_value
2357         in_bindings.push_back(MySqlBinding::condCreateString(option->formatted_value_));
2358         // space
2359         in_bindings.push_back(MySqlBinding::condCreateString(option->space_name_));
2360         // persistent
2361         in_bindings.push_back(MySqlBinding::createBool(option->persistent_));
2362         // dhcp_client_class
2363         in_bindings.push_back(MySqlBinding::createNull());
2364         // dhcp[46]_subnet_id
2365         in_bindings.push_back(MySqlBinding::createNull());
2366         // scope_id
2367         if (pool_type == Lease::TYPE_NA) {
2368             in_bindings.push_back(MySqlBinding::createInteger<uint8_t>(5));
2369         } else {
2370             in_bindings.push_back(MySqlBinding::createInteger<uint8_t>(6));
2371         }
2372         // user_context
2373         in_bindings.push_back(createInputContextBinding(option));
2374         // shared_network_name
2375         in_bindings.push_back(MySqlBinding::createNull());
2376         // pool_id
2377         if (pool_type == Lease::TYPE_NA) {
2378             in_bindings.push_back(MySqlBinding::createInteger<uint64_t>(pool_id));
2379         } else {
2380             in_bindings.push_back(MySqlBinding::createNull());
2381         }
2382         // modification_ts
2383         in_bindings.push_back(MySqlBinding::createTimestamp(option->getModificationTime()));
2384         // pd_pool_id
2385         if (pool_type == Lease::TYPE_PD) {
2386             in_bindings.push_back(MySqlBinding::createInteger<uint64_t>(pool_id));
2387         } else {
2388             in_bindings.push_back(MySqlBinding::createNull());
2389         }
2390 
2391         // Insert bindings used only during the update.
2392         in_bindings.push_back(MySqlBinding::createInteger<uint64_t>(pool_id));
2393         in_bindings.push_back(MySqlBinding::createInteger<uint16_t>(option->option_->getType()));
2394         in_bindings.push_back(MySqlBinding::condCreateString(option->space_name_));
2395 
2396 
2397         MySqlTransaction transaction(conn_);
2398 
2399         // Create scoped audit revision. As long as this instance exists
2400         // no new audit revisions are created in any subsequent calls.
2401         if (pool_type == Lease::TYPE_PD) {
2402             msg = "prefix delegation";
2403         } else {
2404             msg = "address";
2405         }
2406         msg += " pool specific option set";
2407         ScopedAuditRevision
2408             audit_revision(this,
2409                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2410                            server_selector, msg, cascade_update);
2411 
2412         auto index = (pool_type == Lease::TYPE_NA ?
2413                       MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_POOL_ID :
2414                       MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_PD_POOL_ID);
2415         if (conn_.updateDeleteQuery(index, in_bindings) == 0) {
2416             // Remove the 3 bindings used only in case of update.
2417             in_bindings.resize(in_bindings.size() - 3);
2418             insertOption6(server_selector, in_bindings);
2419         }
2420 
2421         transaction.commit();
2422     }
2423 
2424     /// @brief Sends query to insert or update DHCP option in a shared network.
2425     ///
2426     /// @param selector Server selector.
2427     /// @param shared_network_name Name of the shared network the option
2428     /// belongs to.
2429     /// @param option Pointer to the option descriptor encapsulating the option.
2430     /// @param cascade_update Boolean value indicating whether the update is
2431     /// performed as part of the owning element, e.g. shared network.
createUpdateOption6(const ServerSelector & server_selector,const std::string & shared_network_name,const OptionDescriptorPtr & option,const bool cascade_update)2432     void createUpdateOption6(const ServerSelector& server_selector,
2433                              const std::string& shared_network_name,
2434                              const OptionDescriptorPtr& option,
2435                              const bool cascade_update) {
2436 
2437         if (server_selector.amUnassigned()) {
2438             isc_throw(NotImplemented, "managing configuration for no particular server"
2439                       " (unassigned) is unsupported at the moment");
2440         }
2441 
2442         MySqlBindingCollection in_bindings = {
2443             MySqlBinding::createInteger<uint16_t>(option->option_->getType()),
2444             createOptionValueBinding(option),
2445             MySqlBinding::condCreateString(option->formatted_value_),
2446             MySqlBinding::condCreateString(option->space_name_),
2447             MySqlBinding::createBool(option->persistent_),
2448             MySqlBinding::createNull(),
2449             MySqlBinding::createNull(),
2450             MySqlBinding::createInteger<uint8_t>(4),
2451             createInputContextBinding(option),
2452             MySqlBinding::createString(shared_network_name),
2453             MySqlBinding::createNull(),
2454             MySqlBinding::createTimestamp(option->getModificationTime()),
2455             MySqlBinding::createNull(),
2456             MySqlBinding::createString(shared_network_name),
2457             MySqlBinding::createInteger<uint16_t>(option->option_->getType()),
2458             MySqlBinding::condCreateString(option->space_name_)
2459         };
2460 
2461         boost::scoped_ptr<MySqlTransaction> transaction;
2462         // Only start new transaction if specified to do so. This function may
2463         // be called from within an existing transaction in which case we
2464         // don't start the new one.
2465         if (!cascade_update) {
2466             transaction.reset(new MySqlTransaction(conn_));
2467         }
2468 
2469         // Create scoped audit revision. As long as this instance exists
2470         // no new audit revisions are created in any subsequent calls.
2471         ScopedAuditRevision
2472             audit_revision(this,
2473                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2474                            server_selector, "shared network specific option set",
2475                            cascade_update);
2476 
2477         if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
2478                                     UPDATE_OPTION6_SHARED_NETWORK,
2479                                     in_bindings) == 0) {
2480             // Remove the 3 bindings used only in case of update.
2481             in_bindings.resize(in_bindings.size() - 3);
2482             insertOption6(server_selector, in_bindings);
2483         }
2484 
2485         if (transaction) {
2486             transaction->commit();
2487         }
2488     }
2489 
2490     /// @brief Sends query to insert or update DHCP option in a client class.
2491     ///
2492     /// @param selector Server selector.
2493     /// @param client_class Pointer to the client_class the option belongs to.
2494     /// @param option Pointer to the option descriptor encapsulating the option..
createUpdateOption6(const ServerSelector & server_selector,const ClientClassDefPtr & client_class,const OptionDescriptorPtr & option)2495     void createUpdateOption6(const ServerSelector& server_selector,
2496                              const ClientClassDefPtr& client_class,
2497                              const OptionDescriptorPtr& option) {
2498 
2499         if (server_selector.amUnassigned()) {
2500             isc_throw(NotImplemented, "managing configuration for no particular server"
2501                       " (unassigned) is unsupported at the moment");
2502         }
2503 
2504         MySqlBindingCollection in_bindings = {
2505             MySqlBinding::createInteger<uint16_t>(option->option_->getType()),
2506             createOptionValueBinding(option),
2507             MySqlBinding::condCreateString(option->formatted_value_),
2508             MySqlBinding::condCreateString(option->space_name_),
2509             MySqlBinding::createBool(option->persistent_),
2510             MySqlBinding::createString(client_class->getName()),
2511             MySqlBinding::createNull(),
2512             MySqlBinding::createInteger<uint8_t>(2),
2513             createInputContextBinding(option),
2514             MySqlBinding::createNull(),
2515             MySqlBinding::createNull(),
2516             MySqlBinding::createTimestamp(option->getModificationTime()),
2517             MySqlBinding::createNull(),
2518             MySqlBinding::createString(client_class->getName()),
2519             MySqlBinding::createInteger<uint8_t>(option->option_->getType()),
2520             MySqlBinding::condCreateString(option->space_name_)
2521         };
2522 
2523         // Create scoped audit revision. As long as this instance exists
2524         // no new audit revisions are created in any subsequent calls.
2525         ScopedAuditRevision
2526             audit_revision(this,
2527                            MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2528                            server_selector, "client class specific option set",
2529                            true);
2530 
2531         if (conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::
2532                                     UPDATE_OPTION6_CLIENT_CLASS,
2533                                     in_bindings) == 0) {
2534             // Remove the 3 bindings used only in case of update.
2535             in_bindings.resize(in_bindings.size() - 3);
2536             insertOption6(server_selector, in_bindings);
2537         }
2538     }
2539 
2540     /// @brief Sends query to insert or update option definition.
2541     ///
2542     /// @param server_selector Server selector.
2543     /// @param option_def Pointer to the option definition to be inserted or updated.
createUpdateOptionDef6(const ServerSelector & server_selector,const OptionDefinitionPtr & option_def)2544     void createUpdateOptionDef6(const ServerSelector& server_selector,
2545                                 const OptionDefinitionPtr& option_def) {
2546 
2547         createUpdateOptionDef(server_selector, option_def, DHCP6_OPTION_SPACE,
2548                               MySqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE,
2549                               MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6,
2550                               MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION_DEF6,
2551                               MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2552                               MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_SERVER);
2553     }
2554 
2555     /// @brief Sends query to insert or update option definition
2556     /// for a client class.
2557     ///
2558     /// @param server_selector Server selector.
2559     /// @param option_def Pointer to the option definition to be inserted or updated.
2560     /// @param client_class Client class name.
createUpdateOptionDef6(const ServerSelector & server_selector,const OptionDefinitionPtr & option_def,const std::string & client_class_name)2561     void createUpdateOptionDef6(const ServerSelector& server_selector,
2562                                 const OptionDefinitionPtr& option_def,
2563                                 const std::string& client_class_name) {
2564         createUpdateOptionDef(server_selector, option_def, DHCP6_OPTION_SPACE,
2565                               MySqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE,
2566                               MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_CLIENT_CLASS,
2567                               MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION_DEF6_CLIENT_CLASS,
2568                               MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
2569                               MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_SERVER,
2570                               client_class_name);
2571     }
2572 
2573     /// @brief Sends query to delete option definition by code and
2574     /// option space name.
2575     ///
2576     /// @param server_selector Server selector.
2577     /// @param code Option code.
2578     /// @param name Option name.
2579     /// @return Number of deleted option definitions.
deleteOptionDef6(const ServerSelector & server_selector,const uint16_t code,const std::string & space)2580     uint64_t deleteOptionDef6(const ServerSelector& server_selector,
2581                               const uint16_t code,
2582                               const std::string& space) {
2583 
2584         MySqlBindingCollection in_bindings = {
2585             MySqlBinding::createInteger<uint16_t>(code),
2586             MySqlBinding::createString(space)
2587         };
2588 
2589         // Run DELETE.
2590         return (deleteTransactional(DELETE_OPTION_DEF6_CODE_NAME, server_selector,
2591                                     "deleting option definition",
2592                                     "option definition deleted",
2593                                     false,
2594                                     in_bindings));
2595     }
2596 
2597     /// @brief Sends query to delete option definitions for a client class.
2598     ///
2599     /// @param server_selector Server selector.
2600     /// @param client_class Pointer to the client class for which option
2601     /// definitions should be deleted.
2602     /// @return Number of deleted option definitions.
deleteOptionDefs6(const ServerSelector & server_selector,const ClientClassDefPtr & client_class)2603     uint64_t deleteOptionDefs6(const ServerSelector& server_selector,
2604                                const ClientClassDefPtr& client_class) {
2605         MySqlBindingCollection in_bindings = {
2606             MySqlBinding::createString(client_class->getName())
2607         };
2608 
2609         // Run DELETE.
2610         return (deleteTransactional(DELETE_OPTION_DEFS6_CLIENT_CLASS, server_selector,
2611                                     "deleting option definition for a client class",
2612                                     "option definition deleted",
2613                                     true,
2614                                     in_bindings));
2615     }
2616 
2617     /// @brief Deletes global option.
2618     ///
2619     /// @param server_selector Server selector.
2620     /// @param code Code of the deleted option.
2621     /// @param space Option space of the deleted option.
2622     /// @return Number of deleted options.
deleteOption6(const ServerSelector & server_selector,const uint16_t code,const std::string & space)2623     uint64_t deleteOption6(const ServerSelector& server_selector,
2624                            const uint16_t code,
2625                            const std::string& space) {
2626 
2627         MySqlBindingCollection in_bindings = {
2628             MySqlBinding::createInteger<uint16_t>(code),
2629             MySqlBinding::createString(space)
2630         };
2631 
2632         // Run DELETE.
2633         return (deleteTransactional(DELETE_OPTION6, server_selector,
2634                                     "deleting global option",
2635                                     "global option deleted",
2636                                     false,
2637                                     in_bindings));
2638     }
2639 
2640     /// @brief Deletes subnet level option.
2641     ///
2642     /// @param server_selector Server selector.
2643     /// @param subnet_id Identifier of the subnet to which deleted option
2644     /// belongs.
2645     /// @param code Code of the deleted option.
2646     /// @param space Option space of the deleted option.
2647     /// @return Number of deleted options.
deleteOption6(const ServerSelector & server_selector,const SubnetID & subnet_id,const uint16_t code,const std::string & space)2648     uint64_t deleteOption6(const ServerSelector& server_selector,
2649                            const SubnetID& subnet_id,
2650                            const uint16_t code,
2651                            const std::string& space) {
2652 
2653         MySqlBindingCollection in_bindings = {
2654             MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet_id)),
2655             MySqlBinding::createInteger<uint16_t>(code),
2656             MySqlBinding::createString(space)
2657         };
2658 
2659         // Run DELETE.
2660         return (deleteTransactional(DELETE_OPTION6_SUBNET_ID, server_selector,
2661                                     "deleting option for a subnet",
2662                                     "subnet specific option deleted",
2663                                     false,
2664                                     in_bindings));
2665     }
2666 
2667     /// @brief Deletes pool level option.
2668     ///
2669     /// @param server_selector Server selector.
2670     /// @param pool_start_address Lower bound pool address.
2671     /// @param pool_end_address  Upper bound pool address.
2672     /// @param code Code of the deleted option.
2673     /// @param space Option space of the deleted option.
2674     /// @return Number of deleted options.
deleteOption6(const db::ServerSelector & server_selector,const IOAddress & pool_start_address,const IOAddress & pool_end_address,const uint16_t code,const std::string & space)2675     uint64_t deleteOption6(const db::ServerSelector& server_selector,
2676                            const IOAddress& pool_start_address,
2677                            const IOAddress& pool_end_address,
2678                            const uint16_t code,
2679                            const std::string& space) {
2680 
2681         MySqlBindingCollection in_bindings = {
2682             MySqlBinding::createInteger<uint16_t>(code),
2683             MySqlBinding::createString(space),
2684             MySqlBinding::createString(pool_start_address.toText()),
2685             MySqlBinding::createString(pool_end_address.toText())
2686         };
2687 
2688         // Run DELETE.
2689         return (deleteTransactional(DELETE_OPTION6_POOL_RANGE, server_selector,
2690                                     "deleting option for an address pool",
2691                                     "address pool specific option deleted",
2692                                     false,
2693                                     in_bindings));
2694     }
2695 
2696     /// @brief Deletes pd pool level option.
2697     ///
2698     /// @param server_selector Server selector.
2699     /// @param pd_pool_prefix Address part of the pd pool prefix.
2700     /// @param pd_pool_prefix_length Length of the pd pool prefix.
2701     /// @param code Code of the deleted option.
2702     /// @param space Option space of the deleted option.
2703     /// @return Number of deleted options.
deleteOption6(const db::ServerSelector & server_selector,const asiolink::IOAddress & pd_pool_prefix,const uint8_t pd_pool_prefix_length,const uint16_t code,const std::string & space)2704     uint64_t deleteOption6(const db::ServerSelector& server_selector,
2705                            const asiolink::IOAddress& pd_pool_prefix,
2706                            const uint8_t pd_pool_prefix_length,
2707                            const uint16_t code,
2708                            const std::string& space) {
2709 
2710         MySqlBindingCollection in_bindings = {
2711             MySqlBinding::createInteger<uint16_t>(code),
2712             MySqlBinding::createString(space),
2713             MySqlBinding::createString(pd_pool_prefix.toText()),
2714             MySqlBinding::createInteger<uint8_t>(pd_pool_prefix_length)
2715         };
2716 
2717         // Run DELETE.
2718         return (deleteTransactional(DELETE_OPTION6_PD_POOL, server_selector,
2719                                     "deleting option for a prefix delegation pool",
2720                                     "prefix delegation pool specific option deleted",
2721                                     false,
2722                                     in_bindings));
2723     }
2724 
2725     /// @brief Deletes shared network level option.
2726     ///
2727     /// @param server_selector Server selector.
2728     /// @param shared_network_name Name of the shared network which deleted
2729     /// option belongs to
2730     /// @param code Code of the deleted option.
2731     /// @param space Option space of the deleted option.
2732     /// @return Number of deleted options.
deleteOption6(const db::ServerSelector & server_selector,const std::string & shared_network_name,const uint16_t code,const std::string & space)2733     uint64_t deleteOption6(const db::ServerSelector& server_selector,
2734                            const std::string& shared_network_name,
2735                            const uint16_t code,
2736                            const std::string& space) {
2737 
2738         MySqlBindingCollection in_bindings = {
2739             MySqlBinding::createString(shared_network_name),
2740             MySqlBinding::createInteger<uint16_t>(code),
2741             MySqlBinding::createString(space)
2742         };
2743 
2744         // Run DELETE.
2745         return (deleteTransactional(DELETE_OPTION6_SHARED_NETWORK, server_selector,
2746                                     "deleting option for a shared network",
2747                                     "shared network specific option deleted",
2748                                     false,
2749                                     in_bindings));
2750     }
2751 
2752     /// @brief Deletes options belonging to a subnet from the database.
2753     ///
2754     /// @param server_selector Server selector.
2755     /// @param subnet Pointer to the subnet for which options should be
2756     /// deleted.
2757     /// @return Number of deleted options.
deleteOptions6(const ServerSelector & server_selector,const Subnet6Ptr & subnet)2758     uint64_t deleteOptions6(const ServerSelector& server_selector,
2759                             const Subnet6Ptr& subnet) {
2760 
2761         MySqlBindingCollection in_bindings = {
2762             MySqlBinding::createInteger<uint32_t>(subnet->getID()),
2763             MySqlBinding::createString(subnet->toText())
2764         };
2765 
2766         // Run DELETE.
2767         return (deleteTransactional(DELETE_OPTIONS6_SUBNET_ID_PREFIX, server_selector,
2768                                     "deleting options for a subnet",
2769                                     "subnet specific options deleted",
2770                                     true,
2771                                     in_bindings));
2772     }
2773 
2774     /// @brief Deletes options belonging to a shared network from the database.
2775     ///
2776     /// @param server_selector Server selector.
2777     /// @param subnet Pointer to the subnet for which options should be
2778     /// deleted.
2779     /// @return Number of deleted options.
deleteOptions6(const ServerSelector & server_selector,const SharedNetwork6Ptr & shared_network)2780     uint64_t deleteOptions6(const ServerSelector& server_selector,
2781                             const SharedNetwork6Ptr& shared_network) {
2782 
2783         MySqlBindingCollection in_bindings = {
2784             MySqlBinding::createString(shared_network->getName())
2785         };
2786 
2787         // Run DELETE.
2788         return (deleteTransactional(DELETE_OPTIONS6_SHARED_NETWORK, server_selector,
2789                                     "deleting options for a shared network",
2790                                     "shared network specific options deleted",
2791                                     true,
2792                                     in_bindings));
2793     }
2794 
2795     /// @brief Deletes options belonging to a client class from the database.
2796     ///
2797     /// @param server_selector Server selector.
2798     /// @param client_class Pointer to the client class for which options
2799     /// should be deleted.
2800     /// @return Number of deleted options.
deleteOptions6(const ServerSelector & server_selector,const ClientClassDefPtr & client_class)2801     uint64_t deleteOptions6(const ServerSelector& server_selector,
2802                             const ClientClassDefPtr& client_class) {
2803 
2804         MySqlBindingCollection in_bindings = {
2805             MySqlBinding::createString(client_class->getName())
2806         };
2807 
2808         // Run DELETE.
2809         return (deleteTransactional(DELETE_OPTIONS6_CLIENT_CLASS, server_selector,
2810                                     "deleting options for a client class",
2811                                     "client class specific options deleted",
2812                                     true,
2813                                     in_bindings));
2814     }
2815 
2816     /// @brief Common function to retrieve client classes.
2817     ///
2818     /// @param index Index of the query to be used.
2819     /// @param server_selector Server selector.
2820     /// @param in_bindings Input bindings specifying selection criteria. The
2821     /// size of the bindings collection must match the number of placeholders
2822     /// in the prepared statement. The input bindings collection must be empty
2823     /// if the query contains no WHERE clause.
2824     /// @param [out] client_classes Reference to a container where fetched client
2825     /// classes will be inserted.
getClientClasses6(const StatementIndex & index,const ServerSelector & server_selector,const MySqlBindingCollection & in_bindings,ClientClassDictionary & client_classes)2826     void getClientClasses6(const StatementIndex& index,
2827                            const ServerSelector& server_selector,
2828                            const MySqlBindingCollection& in_bindings,
2829                            ClientClassDictionary& client_classes) {
2830         MySqlBindingCollection out_bindings = {
2831             MySqlBinding::createInteger<uint64_t>(), // id
2832             MySqlBinding::createString(CLIENT_CLASS_NAME_BUF_LENGTH), // name
2833             MySqlBinding::createString(CLIENT_CLASS_TEST_BUF_LENGTH), // test
2834             MySqlBinding::createInteger<uint8_t>(), // required
2835             MySqlBinding::createInteger<uint32_t>(), // valid lifetime
2836             MySqlBinding::createInteger<uint32_t>(), // min valid lifetime
2837             MySqlBinding::createInteger<uint32_t>(), // max valid lifetime
2838             MySqlBinding::createInteger<uint8_t>(), // depend on known directly
2839             MySqlBinding::createInteger<uint8_t>(), // depend on known indirectly
2840             MySqlBinding::createTimestamp(), // modification_ts
2841             MySqlBinding::createInteger<uint64_t>(), // option def: id
2842             MySqlBinding::createInteger<uint16_t>(), // option def: code
2843             MySqlBinding::createString(OPTION_NAME_BUF_LENGTH), // option def: name
2844             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option def: space
2845             MySqlBinding::createInteger<uint8_t>(), // option def: type
2846             MySqlBinding::createTimestamp(), // option def: modification_ts
2847             MySqlBinding::createInteger<uint8_t>(), // option def: array
2848             MySqlBinding::createString(OPTION_ENCAPSULATE_BUF_LENGTH), // option def: encapsulate
2849             MySqlBinding::createString(OPTION_RECORD_TYPES_BUF_LENGTH), // option def: record_types
2850             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option def: user_context
2851             MySqlBinding::createInteger<uint64_t>(), // option: option_id
2852             MySqlBinding::createInteger<uint16_t>(), // option: code
2853             MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH), // option: value
2854             MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
2855             MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
2856             MySqlBinding::createInteger<uint8_t>(), // option: persistent
2857             MySqlBinding::createInteger<uint32_t>(), // option: dhcp6_subnet_id
2858             MySqlBinding::createInteger<uint8_t>(), // option: scope_id
2859             MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
2860             MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // option: shared_network_name
2861             MySqlBinding::createInteger<uint64_t>(), // option: pool_id
2862             MySqlBinding::createTimestamp(), // option: modification_ts
2863             MySqlBinding::createString(SERVER_TAG_BUF_LENGTH),// server tag
2864             MySqlBinding::createInteger<uint32_t>(), // preferred lifetime
2865             MySqlBinding::createInteger<uint32_t>(), // min preferred lifetime
2866             MySqlBinding::createInteger<uint32_t>() // max preferred lifetime
2867         };
2868 
2869         std::list<ClientClassDefPtr> class_list;
2870         uint64_t last_option_id = 0;
2871         uint64_t last_option_def_id = 0;
2872         std::string last_tag;
2873 
2874         conn_.selectQuery(index,
2875                           in_bindings, out_bindings,
2876                           [this, &class_list, &last_option_id, &last_option_def_id, &last_tag]
2877                           (MySqlBindingCollection& out_bindings) {
2878             ClientClassDefPtr last_client_class;
2879             if (!class_list.empty()) {
2880                 last_client_class = *class_list.rbegin();
2881             }
2882 
2883             if (!last_client_class || (last_client_class->getId() != out_bindings[0]->getInteger<uint64_t>())) {
2884 
2885                 last_option_id = 0;
2886                 last_option_def_id = 0;
2887                 last_tag.clear();
2888 
2889                 auto options = boost::make_shared<CfgOption>();
2890                 auto option_defs = boost::make_shared<CfgOptionDef>();
2891                 auto expression = boost::make_shared<Expression>();
2892 
2893                 last_client_class = boost::make_shared<ClientClassDef>(out_bindings[1]->getString(), expression, options);
2894                 last_client_class->setCfgOptionDef(option_defs);
2895 
2896                 // id
2897                 last_client_class->setId(out_bindings[0]->getInteger<uint64_t>());
2898 
2899                 // name
2900                 last_client_class->setName(out_bindings[1]->getString());
2901 
2902                 // test
2903                 if (!out_bindings[2]->amNull()) {
2904                     last_client_class->setTest(out_bindings[2]->getString());
2905                 }
2906 
2907                 // required
2908                 if (!out_bindings[3]->amNull()) {
2909                     last_client_class->setRequired(out_bindings[3]->getBool());
2910                 }
2911 
2912                 // valid lifetime: default, min, max
2913                 last_client_class->setValid(createTriplet(out_bindings[4], out_bindings[5], out_bindings[6]));
2914 
2915                 // depend on known directly or indirectly
2916                 last_client_class->setDependOnKnown(out_bindings[7]->getBool() || out_bindings[8]->getBool());
2917 
2918                 // modification_ts
2919                 last_client_class->setModificationTime(out_bindings[9]->getTimestamp());
2920 
2921                 // preferred lifetime: default, min, max
2922                 last_client_class->setPreferred(createTriplet(out_bindings[33], out_bindings[34], out_bindings[35]));
2923 
2924                 class_list.push_back(last_client_class);
2925             }
2926 
2927             // server tag
2928             if (!out_bindings[32]->amNull() &&
2929                 (last_tag != out_bindings[32]->getString())) {
2930                 last_tag = out_bindings[32]->getString();
2931                 if (!last_tag.empty() && !last_client_class->hasServerTag(ServerTag(last_tag))) {
2932                     last_client_class->setServerTag(last_tag);
2933                 }
2934             }
2935 
2936             // Parse client class specific option definition from 10 to 19.
2937             if (!out_bindings[10]->amNull() &&
2938                 (last_option_def_id < out_bindings[10]->getInteger<uint64_t>())) {
2939                 last_option_def_id = out_bindings[10]->getInteger<uint64_t>();
2940 
2941                 auto def = processOptionDefRow(out_bindings.begin() + 10);
2942                 if (def) {
2943                     last_client_class->getCfgOptionDef()->add(def);
2944                 }
2945             }
2946 
2947             // Parse client class specific option from 20 to 31.
2948             if (!out_bindings[20]->amNull() &&
2949                 (last_option_id < out_bindings[20]->getInteger<uint64_t>())) {
2950                 last_option_id = out_bindings[20]->getInteger<uint64_t>();
2951 
2952                 OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 20);
2953                 if (desc) {
2954                     last_client_class->getCfgOption()->add(*desc, desc->space_name_);
2955                 }
2956             }
2957         });
2958 
2959         tossNonMatchingElements(server_selector, class_list);
2960 
2961         for (auto c : class_list) {
2962             client_classes.addClass(c);
2963         }
2964     }
2965 
2966     /// @brief Sends query to retrieve a client class by name.
2967     ///
2968     /// @param server_selector Server selector.
2969     /// @param name Name of the class to be retrieved.
2970     /// @return Pointer to the client class or null if the class is not found.
getClientClass6(const ServerSelector & server_selector,const std::string & name)2971     ClientClassDefPtr getClientClass6(const ServerSelector& server_selector,
2972                                       const std::string& name) {
2973         MySqlBindingCollection in_bindings = {
2974             MySqlBinding::createString(name)
2975         };
2976         ClientClassDictionary client_classes;
2977         getClientClasses6(MySqlConfigBackendDHCPv6Impl::GET_CLIENT_CLASS6_NAME,
2978                           server_selector, in_bindings, client_classes);
2979         return (client_classes.getClasses()->empty() ? ClientClassDefPtr() :
2980                 (*client_classes.getClasses()->begin()));
2981     }
2982 
2983     /// @brief Sends query to retrieve all client classes.
2984     ///
2985     /// @param server_selector Server selector.
2986     /// @param [out] client_classes Reference to the client classes collection
2987     /// where retrieved classes will be stored.
getAllClientClasses6(const ServerSelector & server_selector,ClientClassDictionary & client_classes)2988     void getAllClientClasses6(const ServerSelector& server_selector,
2989                               ClientClassDictionary& client_classes) {
2990         MySqlBindingCollection in_bindings;
2991         getClientClasses6(server_selector.amUnassigned() ?
2992                           MySqlConfigBackendDHCPv6Impl::GET_ALL_CLIENT_CLASSES6_UNASSIGNED :
2993                           MySqlConfigBackendDHCPv6Impl::GET_ALL_CLIENT_CLASSES6,
2994                           server_selector, in_bindings, client_classes);
2995     }
2996 
2997     /// @brief Sends query to retrieve modified client classes.
2998     ///
2999     /// @param server_selector Server selector.
3000     /// @param modification_ts Lower bound modification timestamp.
3001     /// @param [out] client_classes Reference to the client classes collection
3002     /// where retrieved classes will be stored.
getModifiedClientClasses6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_ts,ClientClassDictionary & client_classes)3003     void getModifiedClientClasses6(const ServerSelector& server_selector,
3004                                    const boost::posix_time::ptime& modification_ts,
3005                                    ClientClassDictionary& client_classes) {
3006         if (server_selector.amAny()) {
3007             isc_throw(InvalidOperation, "fetching modified client classes for ANY "
3008                       "server is not supported");
3009         }
3010 
3011         MySqlBindingCollection in_bindings = {
3012             MySqlBinding::createTimestamp(modification_ts)
3013         };
3014         getClientClasses6(server_selector.amUnassigned() ?
3015                           GET_MODIFIED_CLIENT_CLASSES6_UNASSIGNED :
3016                           GET_MODIFIED_CLIENT_CLASSES6,
3017                           server_selector,
3018                           in_bindings,
3019                           client_classes);
3020     }
3021 
3022     /// @brief Upserts client class.
3023     ///
3024     /// @param server_selector Server selector.
3025     /// @param client_class Pointer to the upserted client class.
3026     /// @param follow_class_name name of the class after which the
3027     /// new or updated class should be positioned. An empty value
3028     /// causes the class to be appended at the end of the class
3029     /// hierarchy.
createUpdateClientClass6(const ServerSelector & server_selector,const ClientClassDefPtr & client_class,const std::string & follow_class_name)3030     void createUpdateClientClass6(const ServerSelector& server_selector,
3031                                   const ClientClassDefPtr& client_class,
3032                                   const std::string& follow_class_name) {
3033         // We need to evaluate class expression to see if it references any
3034         // other classes (dependencies). As part of this evaluation we will
3035         // also check if the client class depends on KNOWN/UNKNOWN built-in
3036         // classes.
3037         std::list<std::string> dependencies;
3038         auto depend_on_known = false;
3039         if (!client_class->getTest().empty()) {
3040             ExpressionPtr expression;
3041             ExpressionParser parser;
3042             // Parse the test expression. The callback function is normally used to
3043             // interrupt config file parsing when one of the classes refers to a
3044             // non-existing client class. It returns false in this case. Here,
3045             // we use the callback to capture client classes referenced by the
3046             // upserted client class and record whether this class depends on
3047             // KNOWN/UNKNOWN built-ins. The callback always returns true to avoid
3048             // reporting the parsing error. The dependency check is performed later
3049             // at the database level.
3050             parser.parse(expression, Element::create(client_class->getTest()), AF_INET6,
3051                          [&dependencies, &depend_on_known](const ClientClass& client_class) -> bool {
3052                 if (isClientClassBuiltIn(client_class)) {
3053                     if ((client_class == "KNOWN") || (client_class == "UNKNOWN")) {
3054                         depend_on_known = true;
3055                     }
3056                 } else {
3057                     dependencies.push_back(client_class);
3058                 }
3059                 return (true);
3060             });
3061         }
3062 
3063 
3064         MySqlBindingCollection in_bindings = {
3065             MySqlBinding::createString(client_class->getName()),
3066             MySqlBinding::createString(client_class->getTest()),
3067             MySqlBinding::createBool(client_class->getRequired()),
3068             MySqlBinding::createInteger<uint32_t>(client_class->getValid()),
3069             MySqlBinding::createInteger<uint32_t>(client_class->getValid().getMin()),
3070             MySqlBinding::createInteger<uint32_t>(client_class->getValid().getMax()),
3071             MySqlBinding::createBool(depend_on_known),
3072             (follow_class_name.empty() ? MySqlBinding::createNull() :
3073              MySqlBinding::createString(follow_class_name)),
3074             MySqlBinding::createTimestamp(client_class->getModificationTime()),
3075             MySqlBinding::createInteger<uint32_t>(client_class->getPreferred()),
3076             MySqlBinding::createInteger<uint32_t>(client_class->getPreferred().getMin()),
3077             MySqlBinding::createInteger<uint32_t>(client_class->getPreferred().getMax()),
3078         };
3079 
3080         MySqlTransaction transaction(conn_);
3081 
3082         ScopedAuditRevision audit_revision(this, MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
3083                                            server_selector, "client class set", true);
3084         // Keeps track of whether the client class is inserted or updated.
3085         auto update = false;
3086         try {
3087             conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_CLIENT_CLASS6, in_bindings);
3088 
3089         } catch (const DuplicateEntry&) {
3090             // Such class already exists.
3091 
3092             // Delete options and option definitions. They will be re-created from the new class
3093             // instance.
3094             deleteOptions6(ServerSelector::ANY(), client_class);
3095             deleteOptionDefs6(ServerSelector::ANY(), client_class);
3096 
3097             // Try to update the class.
3098             in_bindings.push_back(MySqlBinding::createString(client_class->getName()));
3099             if (follow_class_name.empty()) {
3100                 // If position is not specified, leave the class at the same position.
3101                 // Remove the binding which specifies the position and use different
3102                 // query.
3103                 in_bindings.erase(in_bindings.begin() + 7, in_bindings.begin() + 8);
3104                 conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_CLIENT_CLASS6_SAME_POSITION,
3105                                         in_bindings);
3106             } else {
3107                 // Update with specifying the position.
3108                 conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::UPDATE_CLIENT_CLASS6,
3109                                         in_bindings);
3110             }
3111 
3112             // Delete class associations with the servers and dependencies. We will re-create
3113             // them according to the new class specification.
3114             MySqlBindingCollection in_assoc_bindings = {
3115                 MySqlBinding::createString(client_class->getName())
3116             };
3117             conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6_DEPENDENCY,
3118                                     in_assoc_bindings);
3119             conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6_SERVER,
3120                                     in_assoc_bindings);
3121             update = true;
3122         }
3123 
3124         // Associate client class with the servers.
3125         attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_CLIENT_CLASS6_SERVER,
3126                                server_selector,
3127                                MySqlBinding::createString(client_class->getName()),
3128                                MySqlBinding::createTimestamp(client_class->getModificationTime()));
3129 
3130         // Iterate over the captured dependencies and try to insert them into the database.
3131         for (auto dependency : dependencies) {
3132             try {
3133                 MySqlBindingCollection in_dependency_bindings = {
3134                     MySqlBinding::createString(client_class->getName()),
3135                     MySqlBinding::createString(dependency)
3136                 };
3137                 // We deleted earlier dependencies, so we can simply insert new ones.
3138                 conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::INSERT_CLIENT_CLASS6_DEPENDENCY,
3139                                   in_dependency_bindings);
3140             } catch (const std::exception& ex) {
3141                 isc_throw(InvalidOperation, "unmet dependency on client class: " << dependency);
3142             }
3143         }
3144 
3145         // If we performed client class update we also have to verify that its dependency
3146         // on KNOWN/UNKNOWN client classes hasn't changed.
3147         if (update) {
3148             MySqlBindingCollection in_check_bindings;
3149             conn_.insertQuery(MySqlConfigBackendDHCPv6Impl::CHECK_CLIENT_CLASS_KNOWN_DEPENDENCY_CHANGE,
3150                               in_check_bindings);
3151         }
3152 
3153         // (Re)create option definitions.
3154         if (client_class->getCfgOptionDef()) {
3155             auto option_defs = client_class->getCfgOptionDef()->getContainer();
3156             auto option_spaces = option_defs.getOptionSpaceNames();
3157             for (auto option_space : option_spaces) {
3158                 OptionDefContainerPtr defs = option_defs.getItems(option_space);
3159                 for (auto def = defs->begin(); def != defs->end(); ++def) {
3160                     createUpdateOptionDef6(server_selector, *def, client_class->getName());
3161                 }
3162             }
3163         }
3164 
3165         // (Re)create options.
3166         auto option_spaces = client_class->getCfgOption()->getOptionSpaceNames();
3167         for (auto option_space : option_spaces) {
3168             OptionContainerPtr options = client_class->getCfgOption()->getAll(option_space);
3169             for (auto desc = options->begin(); desc != options->end(); ++desc) {
3170                 OptionDescriptorPtr desc_copy = OptionDescriptor::create(*desc);
3171                 desc_copy->space_name_ = option_space;
3172                 createUpdateOption6(server_selector, client_class, desc_copy);
3173             }
3174         }
3175 
3176         // All ok. Commit the transaction.
3177         transaction.commit();
3178     }
3179 
3180     /// @brief Removes client class by name.
3181     ///
3182     /// @param server_selector Server selector.
3183     /// @param name Removed client class name.
3184     /// @return Number of deleted client classes.
deleteClientClass6(const ServerSelector & server_selector,const std::string & name)3185     uint64_t deleteClientClass6(const ServerSelector& server_selector,
3186                                 const std::string& name) {
3187         int index = server_selector.amAny() ?
3188             MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6_ANY :
3189             MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6;
3190 
3191         uint64_t result = deleteTransactional(index, server_selector,
3192                                               "deleting client class",
3193                                               "client class deleted",
3194                                               true,
3195                                               name);
3196         return (result);
3197     }
3198 
3199     /// @brief Removes unassigned global parameters, global options and
3200     /// option definitions.
3201     ///
3202     /// This function is called when one or more servers are deleted and
3203     /// it is likely that there are some orphaned configuration elements
3204     /// left in the database. This method removes those elements.
purgeUnassignedConfig()3205     void purgeUnassignedConfig() {
3206         multipleUpdateDeleteQueries(DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
3207                                     DELETE_ALL_GLOBAL_OPTIONS6_UNASSIGNED,
3208                                     DELETE_ALL_OPTION_DEFS6_UNASSIGNED);
3209     }
3210 
3211     /// @brief Attempts to delete a server having a given tag.
3212     ///
3213     /// @param server_tag Tag of the server to be deleted.
3214     /// @return Number of deleted servers.
3215     /// @throw isc::InvalidOperation when trying to delete the logical
3216     /// server 'all'.
deleteServer6(const data::ServerTag & server_tag)3217     uint64_t deleteServer6(const data::ServerTag& server_tag) {
3218         // It is not allowed to delete 'all' logical server.
3219         if (server_tag.amAll()) {
3220             isc_throw(InvalidOperation, "'all' is a name reserved for the server tag which"
3221                       " associates the configuration elements with all servers connecting"
3222                       " to the database and may not be deleted");
3223         }
3224 
3225         MySqlTransaction transaction(conn_);
3226 
3227         // Create scoped audit revision. As long as this instance exists
3228         // no new audit revisions are created in any subsequent calls.
3229         ScopedAuditRevision
3230             audit_revision(this, MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
3231                            ServerSelector::ALL(), "deleting a server", false);
3232 
3233         // Specify which server should be deleted.
3234         MySqlBindingCollection in_bindings = {
3235             MySqlBinding::createString(server_tag.get())
3236         };
3237 
3238         // Attempt to delete the server.
3239         auto count = conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_SERVER6,
3240                                              in_bindings);
3241 
3242         // If we have deleted any servers we have to remove any dangling global
3243         // parameters, options and option definitions.
3244         if (count > 0) {
3245             purgeUnassignedConfig();
3246         }
3247 
3248         transaction.commit();
3249 
3250         return (count);
3251     }
3252 
3253     /// @brief Attempts to delete all servers.
3254     ///
3255     /// This method deletes all servers added by the user. It does not
3256     /// delete the logical server 'all'.
3257     ///
3258     /// @return Number of deleted servers.
deleteAllServers6()3259     uint64_t deleteAllServers6() {
3260         MySqlTransaction transaction(conn_);
3261 
3262         // Create scoped audit revision. As long as this instance exists
3263         // no new audit revisions are created in any subsequent calls.
3264         ScopedAuditRevision
3265             audit_revision(this, MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
3266                            ServerSelector::ALL(), "deleting all servers",
3267                            false);
3268 
3269         MySqlBindingCollection in_bindings;
3270 
3271         // Attempt to delete the servers.
3272         auto count = conn_.updateDeleteQuery(MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SERVERS6,
3273                                              in_bindings);
3274 
3275         // If we have deleted any servers we have to remove any dangling global
3276         // parameters, options and option definitions.
3277         if (count > 0) {
3278             purgeUnassignedConfig();
3279         }
3280 
3281         transaction.commit();
3282 
3283         return (count);
3284     }
3285 
3286     /// @brief Attempts to reconnect the server to the config DB backend manager.
3287     ///
3288     /// This is a self-rescheduling function that attempts to reconnect to the
3289     /// server's config DB backends after connectivity to one or more have been
3290     /// lost. Upon entry it will attempt to reconnect via
3291     /// @ref ConfigBackendDHCPv6Mgr.addBackend.
3292     /// If this is successful, DHCP servicing is re-enabled and server returns
3293     /// to normal operation.
3294     ///
3295     /// If reconnection fails and the maximum number of retries has not been
3296     /// exhausted, it will schedule a call to itself to occur at the
3297     /// configured retry interval. DHCP service remains disabled.
3298     ///
3299     /// If the maximum number of retries has been exhausted an error is logged
3300     /// and the server shuts down.
3301     ///
3302     /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the
3303     /// configured reconnect parameters.
3304     /// @return true if connection has been recovered, false otherwise.
dbReconnect(ReconnectCtlPtr db_reconnect_ctl)3305     static bool dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
3306         MultiThreadingCriticalSection cs;
3307 
3308         // Invoke application layer connection lost callback.
3309         if (!DatabaseConnection::invokeDbLostCallback(db_reconnect_ctl)) {
3310             return (false);
3311         }
3312 
3313         bool reopened = false;
3314 
3315         const std::string timer_name = db_reconnect_ctl->timerName();
3316 
3317         // At least one connection was lost.
3318         try {
3319             auto srv_cfg = CfgMgr::instance().getCurrentCfg();
3320             auto config_ctl = srv_cfg->getConfigControlInfo();
3321             // Iterate over the configured DBs and instantiate them.
3322             for (auto db : config_ctl->getConfigDatabases()) {
3323                 const std::string& access = db.getAccessString();
3324                 auto parameters = db.getParameters();
3325                 if (ConfigBackendDHCPv6Mgr::instance().delBackend(parameters["type"], access, true)) {
3326                     ConfigBackendDHCPv6Mgr::instance().addBackend(db.getAccessString());
3327                 }
3328             }
3329 
3330             reopened = true;
3331         } catch (const std::exception& ex) {
3332             LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_ATTEMPT_FAILED6)
3333                     .arg(ex.what());
3334         }
3335 
3336         if (reopened) {
3337             // Cancel the timer.
3338             if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
3339                 TimerMgr::instance()->unregisterTimer(timer_name);
3340             }
3341 
3342             // Invoke application layer connection recovered callback.
3343             if (!DatabaseConnection::invokeDbRecoveredCallback(db_reconnect_ctl)) {
3344                 return (false);
3345             }
3346         } else {
3347             if (!db_reconnect_ctl->checkRetries()) {
3348                 // We're out of retries, log it and initiate shutdown.
3349                 LOG_ERROR(mysql_cb_logger, MYSQL_CB_RECONNECT_FAILED6)
3350                         .arg(db_reconnect_ctl->maxRetries());
3351 
3352                 // Cancel the timer.
3353                 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
3354                     TimerMgr::instance()->unregisterTimer(timer_name);
3355                 }
3356 
3357                 // Invoke application layer connection failed callback.
3358                 DatabaseConnection::invokeDbFailedCallback(db_reconnect_ctl);
3359 
3360                 return (false);
3361             }
3362 
3363             LOG_INFO(mysql_cb_logger, MYSQL_CB_RECONNECT_ATTEMPT_SCHEDULE6)
3364                     .arg(db_reconnect_ctl->maxRetries() - db_reconnect_ctl->retriesLeft() + 1)
3365                     .arg(db_reconnect_ctl->maxRetries())
3366                     .arg(db_reconnect_ctl->retryInterval());
3367 
3368             // Start the timer.
3369             if (!TimerMgr::instance()->isTimerRegistered(timer_name)) {
3370                 TimerMgr::instance()->registerTimer(timer_name,
3371                     std::bind(&MySqlConfigBackendDHCPv6Impl::dbReconnect, db_reconnect_ctl),
3372                               db_reconnect_ctl->retryInterval(),
3373                               asiolink::IntervalTimer::ONE_SHOT);
3374             }
3375             TimerMgr::instance()->setup(timer_name);
3376         }
3377 
3378         return (true);
3379     }
3380 
3381 };
3382 
3383 namespace {
3384 
3385 /// @brief Array of tagged statements.
3386 typedef std::array<TaggedStatement, MySqlConfigBackendDHCPv6Impl::NUM_STATEMENTS>
3387 TaggedStatementArray;
3388 
3389 /// @brief Prepared MySQL statements used by the backend to insert and
3390 /// retrieve data from the database.
3391 TaggedStatementArray tagged_statements = { {
3392     { MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
3393       "CALL createAuditRevisionDHCP6(?, ?, ?, ?)"
3394     },
3395 
3396     // Verify that dependency on KNOWN/UNKNOWN class has not changed.
3397     { MySqlConfigBackendDHCPv6Impl::CHECK_CLIENT_CLASS_KNOWN_DEPENDENCY_CHANGE,
3398       "CALL checkDHCPv6ClientClassKnownDependencyChange()"
3399     },
3400 
3401     // Select global parameter by name.
3402     { MySqlConfigBackendDHCPv6Impl::GET_GLOBAL_PARAMETER6,
3403       MYSQL_GET_GLOBAL_PARAMETER(dhcp6, AND g.name = ?)
3404     },
3405 
3406     // Select all global parameters.
3407     { MySqlConfigBackendDHCPv6Impl::GET_ALL_GLOBAL_PARAMETERS6,
3408       MYSQL_GET_GLOBAL_PARAMETER(dhcp6)
3409     },
3410 
3411     // Select modified global parameters.
3412     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_GLOBAL_PARAMETERS6,
3413       MYSQL_GET_GLOBAL_PARAMETER(dhcp6, AND g.modification_ts >= ?)
3414     },
3415 
3416     // Delete all global parameters which are unassigned to any servers.
3417     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
3418       MYSQL_DELETE_GLOBAL_PARAMETER_UNASSIGNED(dhcp6)
3419     },
3420 
3421     // Select subnet by id.
3422     { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_NO_TAG,
3423       MYSQL_GET_SUBNET6_NO_TAG(WHERE s.subnet_id = ?)
3424     },
3425 
3426     // Select subnet by id without specifying server tags.
3427     { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_ANY,
3428       MYSQL_GET_SUBNET6_ANY(WHERE s.subnet_id = ?)
3429     },
3430 
3431     // Select unassigned subnet by id.
3432     { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_ID_UNASSIGNED,
3433       MYSQL_GET_SUBNET6_UNASSIGNED(AND s.subnet_id = ?)
3434     },
3435 
3436     // Select subnet by prefix.
3437     { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_NO_TAG,
3438       MYSQL_GET_SUBNET6_NO_TAG(WHERE s.subnet_prefix = ?)
3439     },
3440 
3441     // Select subnet by prefix without specifying server tags.
3442     { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_ANY,
3443       MYSQL_GET_SUBNET6_ANY(WHERE s.subnet_prefix = ?)
3444     },
3445 
3446     // Select unassigned subnet by prefix.
3447     { MySqlConfigBackendDHCPv6Impl::GET_SUBNET6_PREFIX_UNASSIGNED,
3448       MYSQL_GET_SUBNET6_UNASSIGNED(AND s.subnet_prefix = ?)
3449     },
3450 
3451     // Select all subnets.
3452     { MySqlConfigBackendDHCPv6Impl::GET_ALL_SUBNETS6,
3453       MYSQL_GET_SUBNET6_NO_TAG()
3454     },
3455 
3456     // Select all unassigned subnets.
3457     { MySqlConfigBackendDHCPv6Impl::GET_ALL_SUBNETS6_UNASSIGNED,
3458       MYSQL_GET_SUBNET6_UNASSIGNED()
3459     },
3460 
3461     // Select subnets having modification time later than X.
3462     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_SUBNETS6,
3463       MYSQL_GET_SUBNET6_NO_TAG(WHERE s.modification_ts >= ?)
3464     },
3465 
3466     // Select modified and unassigned subnets.
3467     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_SUBNETS6_UNASSIGNED,
3468       MYSQL_GET_SUBNET6_UNASSIGNED(AND s.modification_ts >= ?)
3469     },
3470 
3471     // Select subnets belonging to a shared network.
3472     { MySqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK_SUBNETS6,
3473       MYSQL_GET_SUBNET6_ANY(WHERE s.shared_network_name = ?)
3474     },
3475 
3476     // Select pool by address range for a server.
3477     { MySqlConfigBackendDHCPv6Impl::GET_POOL6_RANGE,
3478       MYSQL_GET_POOL6_RANGE_WITH_TAG(WHERE (srv.tag = ? OR srv.id = 1) AND p.start_address = ? \
3479                                      AND p.end_address = ?)
3480     },
3481 
3482     // Select pool by address range for any server.
3483     { MySqlConfigBackendDHCPv6Impl::GET_POOL6_RANGE_ANY,
3484       MYSQL_GET_POOL6_RANGE_NO_TAG(WHERE p.start_address = ? AND p.end_address = ?)
3485     },
3486 
3487     // Select prefix delegation pool for a server.
3488     { MySqlConfigBackendDHCPv6Impl::GET_PD_POOL,
3489       MYSQL_GET_PD_POOL_WITH_TAG(WHERE (srv.tag = ? OR srv.id = 1) \
3490                                  AND p.prefix = ? AND p.prefix_length = ?)
3491     },
3492 
3493     // Select prefix delegation pool for any server.
3494     { MySqlConfigBackendDHCPv6Impl::GET_PD_POOL_ANY,
3495       MYSQL_GET_PD_POOL_NO_TAG(WHERE p.prefix = ? AND p.prefix_length = ?)
3496     },
3497 
3498     // Select shared network by name.
3499     { MySqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK6_NAME_NO_TAG,
3500       MYSQL_GET_SHARED_NETWORK6_NO_TAG(WHERE n.name = ?)
3501     },
3502 
3503     // Select shared network by name without specifying server tags.
3504     { MySqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK6_NAME_ANY,
3505       MYSQL_GET_SHARED_NETWORK6_ANY(WHERE n.name = ?)
3506     },
3507 
3508     // Select unassigned shared network by name.
3509     { MySqlConfigBackendDHCPv6Impl::GET_SHARED_NETWORK6_NAME_UNASSIGNED,
3510       MYSQL_GET_SHARED_NETWORK6_UNASSIGNED(AND n.name = ?)
3511     },
3512 
3513     // Select all shared networks.
3514     { MySqlConfigBackendDHCPv6Impl::GET_ALL_SHARED_NETWORKS6,
3515       MYSQL_GET_SHARED_NETWORK6_NO_TAG()
3516     },
3517 
3518     // Select all unassigned shared networks.
3519     { MySqlConfigBackendDHCPv6Impl::GET_ALL_SHARED_NETWORKS6_UNASSIGNED,
3520       MYSQL_GET_SHARED_NETWORK6_UNASSIGNED()
3521     },
3522 
3523     // Select modified shared networks.
3524     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_SHARED_NETWORKS6,
3525       MYSQL_GET_SHARED_NETWORK6_NO_TAG(WHERE n.modification_ts >= ?)
3526     },
3527 
3528     // Select modified and unassigned shared networks.
3529     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_SHARED_NETWORKS6_UNASSIGNED,
3530       MYSQL_GET_SHARED_NETWORK6_UNASSIGNED(AND n.modification_ts >= ?)
3531     },
3532 
3533     // Retrieves option definition by code and space.
3534     { MySqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE,
3535       MYSQL_GET_OPTION_DEF(dhcp6, AND d.code = ? AND d.space = ?)
3536     },
3537 
3538     // Retrieves all option definitions.
3539     { MySqlConfigBackendDHCPv6Impl::GET_ALL_OPTION_DEFS6,
3540       MYSQL_GET_OPTION_DEF(dhcp6)
3541     },
3542 
3543     // Retrieves modified option definitions.
3544     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTION_DEFS6,
3545       MYSQL_GET_OPTION_DEF(dhcp6, AND d.modification_ts >= ?)
3546     },
3547 
3548     // Retrieves global option by code and space.
3549     { MySqlConfigBackendDHCPv6Impl::GET_OPTION6_CODE_SPACE,
3550       MYSQL_GET_OPTION6(AND o.scope_id = 0 AND o.code = ? AND o.space = ?)
3551     },
3552 
3553     // Retrieves all global options.
3554     { MySqlConfigBackendDHCPv6Impl::GET_ALL_OPTIONS6,
3555       MYSQL_GET_OPTION6(AND o.scope_id = 0)
3556     },
3557 
3558     // Retrieves modified options.
3559     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTIONS6,
3560       MYSQL_GET_OPTION6(AND o.scope_id = 0 AND o.modification_ts >= ?)
3561     },
3562 
3563     // Retrieves an option for a given subnet, option code and space.
3564     { MySqlConfigBackendDHCPv6Impl::GET_OPTION6_SUBNET_ID_CODE_SPACE,
3565       MYSQL_GET_OPTION6(AND o.scope_id = 1 AND o.dhcp6_subnet_id = ? AND o.code = ? AND o.space = ?)
3566     },
3567 
3568     // Retrieves an option for a given pool, option code and space.
3569     { MySqlConfigBackendDHCPv6Impl::GET_OPTION6_POOL_ID_CODE_SPACE,
3570       MYSQL_GET_OPTION6(AND o.scope_id = 5 AND o.pool_id = ? AND o.code = ? AND o.space = ?)
3571     },
3572 
3573     // Retrieves an option for a given pd pool, option code and space.
3574     { MySqlConfigBackendDHCPv6Impl::GET_OPTION6_PD_POOL_ID_CODE_SPACE,
3575       MYSQL_GET_OPTION6(AND o.scope_id = 6 AND o.pd_pool_id = ? AND o.code = ? AND o.space = ?)
3576     },
3577 
3578     // Retrieves an option for a given shared network, option code and space.
3579     { MySqlConfigBackendDHCPv6Impl::GET_OPTION6_SHARED_NETWORK_CODE_SPACE,
3580       MYSQL_GET_OPTION6(AND o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?)
3581     },
3582 
3583     // Select a client class by name.
3584     { MySqlConfigBackendDHCPv6Impl::GET_CLIENT_CLASS6_NAME,
3585       MYSQL_GET_CLIENT_CLASS6_WITH_TAG(WHERE c.name = ?)
3586     },
3587 
3588     // Select all client classes.
3589     { MySqlConfigBackendDHCPv6Impl::GET_ALL_CLIENT_CLASSES6,
3590       MYSQL_GET_CLIENT_CLASS6_WITH_TAG()
3591     },
3592 
3593     // Select all unassigned client classes.
3594     { MySqlConfigBackendDHCPv6Impl::GET_ALL_CLIENT_CLASSES6_UNASSIGNED,
3595       MYSQL_GET_CLIENT_CLASS6_UNASSIGNED()
3596     },
3597 
3598     // Select modified client classes.
3599     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_CLIENT_CLASSES6,
3600       MYSQL_GET_CLIENT_CLASS6_WITH_TAG(WHERE c.modification_ts >= ?)
3601     },
3602 
3603     // Select modified client classes.
3604     { MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_CLIENT_CLASSES6_UNASSIGNED,
3605       MYSQL_GET_CLIENT_CLASS6_UNASSIGNED(AND c.modification_ts >= ?)
3606     },
3607 
3608     // Retrieves the most recent audit entries.
3609     { MySqlConfigBackendDHCPv6Impl::GET_AUDIT_ENTRIES6_TIME,
3610       MYSQL_GET_AUDIT_ENTRIES_TIME(dhcp6)
3611     },
3612 
3613     // Retrieves a server by tag.
3614     { MySqlConfigBackendDHCPv6Impl::GET_SERVER6,
3615       MYSQL_GET_SERVER(dhcp6)
3616     },
3617 
3618     // Retrieves all servers.
3619     { MySqlConfigBackendDHCPv6Impl::GET_ALL_SERVERS6,
3620       MYSQL_GET_ALL_SERVERS(dhcp6)
3621     },
3622 
3623     // Insert global parameter.
3624     { MySqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6,
3625       MYSQL_INSERT_GLOBAL_PARAMETER(dhcp6)
3626     },
3627 
3628     // Insert association of the global parameter with a server.
3629     { MySqlConfigBackendDHCPv6Impl::INSERT_GLOBAL_PARAMETER6_SERVER,
3630       MYSQL_INSERT_GLOBAL_PARAMETER_SERVER(dhcp6)
3631     },
3632 
3633     // Insert a subnet.
3634     { MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6,
3635       "INSERT INTO dhcp6_subnet("
3636       "  subnet_id,"
3637       "  subnet_prefix,"
3638       "  client_class,"
3639       "  interface,"
3640       "  modification_ts,"
3641       "  preferred_lifetime,"
3642       "  min_preferred_lifetime,"
3643       "  max_preferred_lifetime,"
3644       "  rapid_commit,"
3645       "  rebind_timer,"
3646       "  relay,"
3647       "  renew_timer,"
3648       "  require_client_classes,"
3649       "  reservations_global,"
3650       "  shared_network_name,"
3651       "  user_context,"
3652       "  valid_lifetime,"
3653       "  min_valid_lifetime,"
3654       "  max_valid_lifetime,"
3655       "  calculate_tee_times,"
3656       "  t1_percent,"
3657       "  t2_percent,"
3658       "  interface_id,"
3659       "  ddns_send_updates,"
3660       "  ddns_override_no_update,"
3661       "  ddns_override_client_update,"
3662       "  ddns_replace_client_name,"
3663       "  ddns_generated_prefix,"
3664       "  ddns_qualifying_suffix,"
3665       "  reservations_in_subnet,"
3666       "  reservations_out_of_pool,"
3667       "  cache_threshold,"
3668       "  cache_max_age"
3669       ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
3670       " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
3671 
3672     // Insert association of the subnet with a server.
3673     { MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6_SERVER,
3674       MYSQL_INSERT_SUBNET_SERVER(dhcp6)
3675     },
3676 
3677     // Insert pool for a subnet.
3678     { MySqlConfigBackendDHCPv6Impl::INSERT_POOL6,
3679       MYSQL_INSERT_POOL(dhcp6)
3680     },
3681 
3682     // Insert pd pool for a subnet.
3683     { MySqlConfigBackendDHCPv6Impl::INSERT_PD_POOL,
3684       MYSQL_INSERT_PD_POOL()
3685     },
3686 
3687     // Insert a shared network.
3688     { MySqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6,
3689       "INSERT INTO dhcp6_shared_network("
3690       "  name,"
3691       "  client_class,"
3692       "  interface,"
3693       "  modification_ts,"
3694       "  preferred_lifetime,"
3695       "  min_preferred_lifetime,"
3696       "  max_preferred_lifetime,"
3697       "  rapid_commit,"
3698       "  rebind_timer,"
3699       "  relay,"
3700       "  renew_timer,"
3701       "  require_client_classes,"
3702       "  reservations_global,"
3703       "  user_context,"
3704       "  valid_lifetime,"
3705       "  min_valid_lifetime,"
3706       "  max_valid_lifetime,"
3707       "  calculate_tee_times,"
3708       "  t1_percent,"
3709       "  t2_percent,"
3710       "  interface_id,"
3711       "  ddns_send_updates,"
3712       "  ddns_override_no_update,"
3713       "  ddns_override_client_update,"
3714       "  ddns_replace_client_name,"
3715       "  ddns_generated_prefix,"
3716       "  ddns_qualifying_suffix,"
3717       "  reservations_in_subnet,"
3718       "  reservations_out_of_pool,"
3719       "  cache_threshold,"
3720       "  cache_max_age"
3721       ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
3722       " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
3723 
3724     // Insert association of the shared network with a server.
3725     { MySqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6_SERVER,
3726       MYSQL_INSERT_SHARED_NETWORK_SERVER(dhcp6)
3727     },
3728 
3729     // Insert option definition.
3730     { MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6,
3731       MYSQL_INSERT_OPTION_DEF(dhcp6)
3732     },
3733 
3734     // Insert option definition for client class.
3735     { MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_CLIENT_CLASS,
3736       MYSQL_INSERT_OPTION_DEF_CLIENT_CLASS(dhcp6)
3737     },
3738 
3739     // Insert association of the option definition with a server.
3740     { MySqlConfigBackendDHCPv6Impl::INSERT_OPTION_DEF6_SERVER,
3741       MYSQL_INSERT_OPTION_DEF_SERVER(dhcp6)
3742     },
3743 
3744     // Insert subnet specific option.
3745     { MySqlConfigBackendDHCPv6Impl::INSERT_OPTION6,
3746       MYSQL_INSERT_OPTION6()
3747     },
3748 
3749     // Insert association of the DHCP option with a server.
3750     { MySqlConfigBackendDHCPv6Impl::INSERT_OPTION6_SERVER,
3751       MYSQL_INSERT_OPTION_SERVER(dhcp6)
3752     },
3753 
3754     // Insert client class.
3755     { MySqlConfigBackendDHCPv6Impl::INSERT_CLIENT_CLASS6,
3756       "INSERT INTO dhcp6_client_class("
3757       "  name,"
3758       "  test,"
3759       "  only_if_required,"
3760       "  valid_lifetime,"
3761       "  min_valid_lifetime,"
3762       "  max_valid_lifetime,"
3763       "  depend_on_known_directly,"
3764       "  follow_class_name,"
3765       "  modification_ts,"
3766       "  preferred_lifetime,"
3767       "  min_preferred_lifetime,"
3768       "  max_preferred_lifetime"
3769       ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
3770     },
3771     // Insert association of a client class with a server.
3772     { MySqlConfigBackendDHCPv6Impl::INSERT_CLIENT_CLASS6_SERVER,
3773       MYSQL_INSERT_CLIENT_CLASS_SERVER(dhcp6)
3774     },
3775     // Insert client class dependency.
3776     { MySqlConfigBackendDHCPv6Impl::INSERT_CLIENT_CLASS6_DEPENDENCY,
3777       MYSQL_INSERT_CLIENT_CLASS_DEPENDENCY(dhcp6)
3778     },
3779 
3780     // Insert server with server tag and description.
3781     { MySqlConfigBackendDHCPv6Impl::INSERT_SERVER6,
3782       MYSQL_INSERT_SERVER(dhcp6)
3783     },
3784 
3785     // Update existing global parameter.
3786     { MySqlConfigBackendDHCPv6Impl::UPDATE_GLOBAL_PARAMETER6,
3787       MYSQL_UPDATE_GLOBAL_PARAMETER(dhcp6)
3788     },
3789 
3790     // Update existing subnet.
3791     { MySqlConfigBackendDHCPv6Impl::UPDATE_SUBNET6,
3792       "UPDATE dhcp6_subnet SET"
3793       "  subnet_id = ?,"
3794       "  subnet_prefix = ?,"
3795       "  client_class = ?,"
3796       "  interface = ?,"
3797       "  modification_ts = ?,"
3798       "  preferred_lifetime = ?,"
3799       "  min_preferred_lifetime = ?,"
3800       "  max_preferred_lifetime = ?,"
3801       "  rapid_commit = ?,"
3802       "  rebind_timer = ?,"
3803       "  relay = ?,"
3804       "  renew_timer = ?,"
3805       "  require_client_classes = ?,"
3806       "  reservations_global = ?,"
3807       "  shared_network_name = ?,"
3808       "  user_context = ?,"
3809       "  valid_lifetime = ?,"
3810       "  min_valid_lifetime = ?,"
3811       "  max_valid_lifetime = ?,"
3812       "  calculate_tee_times = ?,"
3813       "  t1_percent = ?,"
3814       "  t2_percent = ?,"
3815       "  interface_id = ?,"
3816       "  ddns_send_updates = ?,"
3817       "  ddns_override_no_update = ?,"
3818       "  ddns_override_client_update = ?,"
3819       "  ddns_replace_client_name = ?,"
3820       "  ddns_generated_prefix = ?,"
3821       "  ddns_qualifying_suffix = ?,"
3822       "  reservations_in_subnet = ?,"
3823       "  reservations_out_of_pool = ?,"
3824       "  cache_threshold = ?,"
3825       "  cache_max_age = ? "
3826       "WHERE subnet_id = ? OR subnet_prefix = ?" },
3827 
3828     // Update existing shared network.
3829     { MySqlConfigBackendDHCPv6Impl::UPDATE_SHARED_NETWORK6,
3830       "UPDATE dhcp6_shared_network SET"
3831       "  name = ?,"
3832       "  client_class = ?,"
3833       "  interface = ?,"
3834       "  modification_ts = ?,"
3835       "  preferred_lifetime = ?,"
3836       "  min_preferred_lifetime = ?,"
3837       "  max_preferred_lifetime = ?,"
3838       "  rapid_commit = ?,"
3839       "  rebind_timer = ?,"
3840       "  relay = ?,"
3841       "  renew_timer = ?,"
3842       "  require_client_classes = ?,"
3843       "  reservations_global = ?,"
3844       "  user_context = ?,"
3845       "  valid_lifetime = ?,"
3846       "  min_valid_lifetime = ?,"
3847       "  max_valid_lifetime = ?,"
3848       "  calculate_tee_times = ?,"
3849       "  t1_percent = ?,"
3850       "  t2_percent = ?,"
3851       "  interface_id = ?,"
3852       "  ddns_send_updates = ?,"
3853       "  ddns_override_no_update = ?,"
3854       "  ddns_override_client_update = ?,"
3855       "  ddns_replace_client_name = ?,"
3856       "  ddns_generated_prefix = ?,"
3857       "  ddns_qualifying_suffix = ?,"
3858       "  reservations_in_subnet = ?,"
3859       "  reservations_out_of_pool = ?,"
3860       "  cache_threshold = ?,"
3861       "  cache_max_age = ? "
3862       "WHERE name = ?" },
3863 
3864     // Update existing option definition.
3865     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION_DEF6,
3866       MYSQL_UPDATE_OPTION_DEF(dhcp6)
3867     },
3868 
3869     // Update existing option definition.
3870     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION_DEF6_CLIENT_CLASS,
3871       MYSQL_UPDATE_OPTION_DEF_CLIENT_CLASS(dhcp6)
3872     },
3873 
3874     // Update existing global option.
3875     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6,
3876       MYSQL_UPDATE_OPTION6_WITH_TAG(AND o.scope_id = 0 AND o.code = ? AND o.space = ?)
3877     },
3878 
3879     // Update existing subnet level option.
3880     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SUBNET_ID,
3881       MYSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 1 AND o.dhcp6_subnet_id = ? AND o.code = ? AND o.space = ?)
3882     },
3883 
3884     // Update existing pool level option.
3885     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_POOL_ID,
3886       MYSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 5 AND o.pool_id = ? AND o.code = ? AND o.space = ?)
3887     },
3888 
3889     // Update existing pd pool level option.
3890     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_PD_POOL_ID,
3891       MYSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 6 AND o.pd_pool_id = ? AND o.code = ? AND o.space = ?)
3892     },
3893 
3894     // Update existing shared network level option.
3895     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SHARED_NETWORK,
3896       MYSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?)
3897     },
3898 
3899     // Update existing client class level option.
3900     { MySqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_CLIENT_CLASS,
3901       MYSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 2 AND o.dhcp_client_class = ? AND o.code = ? AND o.space = ?)
3902     },
3903 
3904     // Update existing client class with specifying its position.
3905     { MySqlConfigBackendDHCPv6Impl::UPDATE_CLIENT_CLASS6,
3906       MYSQL_UPDATE_CLIENT_CLASS6("follow_class_name = ?,")
3907     },
3908 
3909     // Update existing client class without specifying its position.
3910     { MySqlConfigBackendDHCPv6Impl::UPDATE_CLIENT_CLASS6_SAME_POSITION,
3911       MYSQL_UPDATE_CLIENT_CLASS6("")
3912     },
3913 
3914     // Update existing server, e.g. server description.
3915     { MySqlConfigBackendDHCPv6Impl::UPDATE_SERVER6,
3916       MYSQL_UPDATE_SERVER(dhcp6)
3917     },
3918 
3919     // Delete global parameter by name.
3920     { MySqlConfigBackendDHCPv6Impl::DELETE_GLOBAL_PARAMETER6,
3921       MYSQL_DELETE_GLOBAL_PARAMETER(dhcp6, AND g.name = ?)
3922     },
3923 
3924     // Delete all global parameters.
3925     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_PARAMETERS6,
3926       MYSQL_DELETE_GLOBAL_PARAMETER(dhcp6)
3927     },
3928 
3929     // Delete subnet by id with specifying server tag.
3930     { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG,
3931       MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_id = ?)
3932     },
3933 
3934     // Delete subnet by id without specifying server tag.
3935     { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY,
3936       MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_id = ?)
3937     },
3938 
3939     // Delete subnet by prefix with specifying server tag.
3940     { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG,
3941       MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_prefix = ?)
3942     },
3943 
3944     // Delete subnet by prefix without specifying server tag.
3945     { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY,
3946       MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_prefix = ?)
3947     },
3948 
3949     // Delete all subnets.
3950     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6,
3951       MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6)
3952     },
3953 
3954     // Delete all unassigned subnets.
3955     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_UNASSIGNED,
3956       MYSQL_DELETE_SUBNET_UNASSIGNED(dhcp6)
3957     },
3958 
3959     // Delete all subnets for a shared network.
3960     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
3961       MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.shared_network_name = ?)
3962     },
3963 
3964     // Delete associations of a subnet with server.
3965     { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_SERVER,
3966       MYSQL_DELETE_SUBNET_SERVER(dhcp6),
3967     },
3968 
3969     // Delete pools for a subnet.
3970     { MySqlConfigBackendDHCPv6Impl::DELETE_POOLS6,
3971       MYSQL_DELETE_POOLS(dhcp6)
3972     },
3973 
3974     // Delete pd pools for a subnet.
3975     { MySqlConfigBackendDHCPv6Impl::DELETE_PD_POOLS,
3976       MYSQL_DELETE_PD_POOLS()
3977     },
3978 
3979     // Delete shared network by name with specifying server tag.
3980     { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_WITH_TAG,
3981       MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6, AND n.name = ?)
3982     },
3983 
3984     // Delete shared network by name without specifying server tag.
3985     { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_ANY,
3986       MYSQL_DELETE_SHARED_NETWORK_ANY(dhcp6, WHERE n.name = ?)
3987     },
3988 
3989     // Delete all shared networks.
3990     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6,
3991       MYSQL_DELETE_SHARED_NETWORK_WITH_TAG(dhcp6)
3992     },
3993 
3994     // Delete all unassigned shared networks.
3995     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED,
3996       MYSQL_DELETE_SHARED_NETWORK_UNASSIGNED(dhcp6)
3997     },
3998 
3999     // Delete associations of a shared network with server.
4000     { MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_SERVER,
4001       MYSQL_DELETE_SHARED_NETWORK_SERVER(dhcp6)
4002     },
4003 
4004     // Delete option definition.
4005     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION_DEF6_CODE_NAME,
4006       MYSQL_DELETE_OPTION_DEF(dhcp6, AND code = ? AND space = ?)
4007     },
4008 
4009     // Delete all option definitions.
4010     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTION_DEFS6,
4011       MYSQL_DELETE_OPTION_DEF(dhcp6)
4012     },
4013 
4014     // Delete all option definitions which are assigned to no servers.
4015     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTION_DEFS6_UNASSIGNED,
4016       MYSQL_DELETE_OPTION_DEF_UNASSIGNED(dhcp6)
4017     },
4018 
4019     // Delete client class specific option definitions.
4020     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION_DEFS6_CLIENT_CLASS,
4021       MYSQL_DELETE_OPTION_DEFS_CLIENT_CLASS(dhcp6)
4022     },
4023 
4024     // Delete single global option.
4025     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6,
4026       MYSQL_DELETE_OPTION_WITH_TAG(dhcp6, AND o.scope_id = 0  AND o.code = ? AND o.space = ?)
4027     },
4028 
4029     // Delete all global options which are unassigned to any servers.
4030     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_OPTIONS6_UNASSIGNED,
4031       MYSQL_DELETE_OPTION_UNASSIGNED(dhcp6, AND o.scope_id = 0)
4032     },
4033 
4034     // Delete single option from a subnet.
4035     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6_SUBNET_ID,
4036       MYSQL_DELETE_OPTION_NO_TAG(dhcp6,
4037                           WHERE o.scope_id = 1 AND o.dhcp6_subnet_id = ? AND o.code = ? AND o.space = ?)
4038     },
4039 
4040     // Delete single option from a pool.
4041     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6_POOL_RANGE,
4042       MYSQL_DELETE_OPTION_POOL_RANGE(dhcp6, o.scope_id = 5 AND o.code = ? AND o.space = ?)
4043     },
4044 
4045     // Delete single option from a pd pool.
4046     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6_PD_POOL,
4047       MYSQL_DELETE_OPTION_PD_POOL(o.scope_id = 6 AND o.code = ? AND o.space = ?)
4048     },
4049 
4050     // Delete single option from a shared network.
4051     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTION6_SHARED_NETWORK,
4052       MYSQL_DELETE_OPTION_NO_TAG(dhcp6,
4053                           WHERE o.scope_id = 4 AND o.shared_network_name = ? AND o.code = ? AND o.space = ?)
4054     },
4055 
4056     // Delete options belonging to a subnet.
4057     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTIONS6_SUBNET_ID_PREFIX,
4058       MYSQL_DELETE_OPTION_SUBNET_ID_PREFIX(dhcp6)
4059     },
4060 
4061     // Delete options belonging to a shared_network.
4062     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTIONS6_SHARED_NETWORK,
4063       MYSQL_DELETE_OPTION_NO_TAG(dhcp6, WHERE o.scope_id = 4 AND o.shared_network_name = ?)
4064     },
4065 
4066     // Delete options belonging to a client class.
4067     { MySqlConfigBackendDHCPv6Impl::DELETE_OPTIONS6_CLIENT_CLASS,
4068       MYSQL_DELETE_OPTION_NO_TAG(dhcp6, WHERE o.scope_id = 2 AND o.dhcp_client_class = ?)
4069     },
4070 
4071     // Delete all dependencies of a client class.
4072     { MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6_DEPENDENCY,
4073       MYSQL_DELETE_CLIENT_CLASS_DEPENDENCY(dhcp6)
4074     },
4075 
4076     // Delete associations of a client class with server.
4077     { MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6_SERVER,
4078       MYSQL_DELETE_CLIENT_CLASS_SERVER(dhcp6),
4079     },
4080 
4081     // Delete all client classes.
4082     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_CLIENT_CLASSES6,
4083       MYSQL_DELETE_CLIENT_CLASS_WITH_TAG(dhcp6)
4084     },
4085 
4086     // Delete all unassigned client classes.
4087     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_CLIENT_CLASSES6_UNASSIGNED,
4088       MYSQL_DELETE_CLIENT_CLASS_UNASSIGNED(dhcp6)
4089     },
4090 
4091     // Delete specified client class.
4092     { MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6,
4093       MYSQL_DELETE_CLIENT_CLASS_WITH_TAG(dhcp6, AND name = ?)
4094     },
4095 
4096     // Delete any client class with a given name.
4097     { MySqlConfigBackendDHCPv6Impl::DELETE_CLIENT_CLASS6_ANY,
4098       MYSQL_DELETE_CLIENT_CLASS_ANY(dhcp6, AND name = ?)
4099     },
4100 
4101     // Delete a server by tag.
4102     { MySqlConfigBackendDHCPv6Impl::DELETE_SERVER6,
4103       MYSQL_DELETE_SERVER(dhcp6)
4104     },
4105 
4106     // Deletes all servers except logical server 'all'.
4107     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SERVERS6,
4108       MYSQL_DELETE_ALL_SERVERS(dhcp6)
4109     }
4110 }
4111 };
4112 
4113 } // end anonymous namespace
4114 
MySqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap & parameters)4115 MySqlConfigBackendDHCPv6Impl::MySqlConfigBackendDHCPv6Impl(const DatabaseConnection::ParameterMap& parameters)
4116     : MySqlConfigBackendImpl(parameters, &MySqlConfigBackendDHCPv6Impl::dbReconnect) {
4117     // Prepare query statements. Those are will be only used to retrieve
4118     // information from the database, so they can be used even if the
4119     // database is read only for the current user.
4120     conn_.prepareStatements(tagged_statements.begin(),
4121                             tagged_statements.end());
4122 //                            tagged_statements.begin() + WRITE_STMTS_BEGIN);
4123 
4124     // Create unique timer name per instance.
4125     timer_name_ = "MySqlConfigBackend6[";
4126     timer_name_ += boost::lexical_cast<std::string>(reinterpret_cast<uint64_t>(this));
4127     timer_name_ += "]DbReconnectTimer";
4128 
4129     // Create ReconnectCtl for this connection.
4130     conn_.makeReconnectCtl(timer_name_);
4131 }
4132 
~MySqlConfigBackendDHCPv6Impl()4133 MySqlConfigBackendDHCPv6Impl::~MySqlConfigBackendDHCPv6Impl() {
4134 }
4135 
MySqlConfigBackendDHCPv6(const DatabaseConnection::ParameterMap & parameters)4136 MySqlConfigBackendDHCPv6::MySqlConfigBackendDHCPv6(const DatabaseConnection::ParameterMap& parameters)
4137     : impl_(new MySqlConfigBackendDHCPv6Impl(parameters)), base_impl_(impl_) {
4138 }
4139 
4140 bool
isUnusable()4141 MySqlConfigBackendDHCPv6::isUnusable() {
4142     return (impl_->conn_.isUnusable());
4143 }
4144 
4145 DatabaseConnection::ParameterMap
getParameters() const4146 MySqlConfigBackendDHCPv6::getParameters() const {
4147     return (impl_->getParameters());
4148 }
4149 
4150 Subnet6Ptr
getSubnet6(const ServerSelector & server_selector,const std::string & subnet_prefix) const4151 MySqlConfigBackendDHCPv6::getSubnet6(const ServerSelector& server_selector,
4152                                      const std::string& subnet_prefix) const {
4153     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SUBNET6_BY_PREFIX)
4154         .arg(subnet_prefix);
4155     return (impl_->getSubnet6(server_selector, subnet_prefix));
4156 }
4157 
4158 Subnet6Ptr
getSubnet6(const ServerSelector & server_selector,const SubnetID & subnet_id) const4159 MySqlConfigBackendDHCPv6::getSubnet6(const ServerSelector& server_selector,
4160                                      const SubnetID& subnet_id) const {
4161     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SUBNET6_BY_SUBNET_ID)
4162         .arg(subnet_id);
4163     return (impl_->getSubnet6(server_selector, subnet_id));
4164 }
4165 
4166 Subnet6Collection
getAllSubnets6(const ServerSelector & server_selector) const4167 MySqlConfigBackendDHCPv6::getAllSubnets6(const ServerSelector& server_selector) const {
4168     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SUBNETS6);
4169     Subnet6Collection subnets;
4170     impl_->getAllSubnets6(server_selector, subnets);
4171     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SUBNETS6_RESULT)
4172         .arg(subnets.size());
4173     return (subnets);
4174 }
4175 
4176 Subnet6Collection
getModifiedSubnets6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const4177 MySqlConfigBackendDHCPv6::getModifiedSubnets6(const ServerSelector& server_selector,
4178                                               const boost::posix_time::ptime& modification_time) const {
4179     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_SUBNETS6)
4180         .arg(util::ptimeToText(modification_time));
4181     Subnet6Collection subnets;
4182     impl_->getModifiedSubnets6(server_selector, modification_time, subnets);
4183     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_SUBNETS6_RESULT)
4184         .arg(subnets.size());
4185     return (subnets);
4186 }
4187 
4188 Subnet6Collection
getSharedNetworkSubnets6(const ServerSelector &,const std::string & shared_network_name) const4189 MySqlConfigBackendDHCPv6::getSharedNetworkSubnets6(const ServerSelector& /* server_selector */,
4190                                                    const std::string& shared_network_name) const {
4191     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SHARED_NETWORK_SUBNETS6)
4192         .arg(shared_network_name);
4193     Subnet6Collection subnets;
4194     impl_->getSharedNetworkSubnets6(ServerSelector::ANY(), shared_network_name, subnets);
4195     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SHARED_NETWORK_SUBNETS6_RESULT)
4196         .arg(subnets.size());
4197     return (subnets);
4198 }
4199 
4200 SharedNetwork6Ptr
getSharedNetwork6(const ServerSelector & server_selector,const std::string & name) const4201 MySqlConfigBackendDHCPv6::getSharedNetwork6(const ServerSelector& server_selector,
4202                                             const std::string& name) const {
4203     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SHARED_NETWORK6)
4204         .arg(name);
4205     return (impl_->getSharedNetwork6(server_selector, name));
4206 }
4207 
4208 SharedNetwork6Collection
getAllSharedNetworks6(const ServerSelector & server_selector) const4209 MySqlConfigBackendDHCPv6::getAllSharedNetworks6(const ServerSelector& server_selector) const {
4210     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SHARED_NETWORKS6);
4211     SharedNetwork6Collection shared_networks;
4212     impl_->getAllSharedNetworks6(server_selector, shared_networks);
4213     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SHARED_NETWORKS6_RESULT)
4214         .arg(shared_networks.size());
4215     return (shared_networks);
4216 }
4217 
4218 SharedNetwork6Collection
getModifiedSharedNetworks6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const4219 MySqlConfigBackendDHCPv6::getModifiedSharedNetworks6(const ServerSelector& server_selector,
4220         const boost::posix_time::ptime& modification_time) const {
4221     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_SHARED_NETWORKS6)
4222         .arg(util::ptimeToText(modification_time));
4223     SharedNetwork6Collection shared_networks;
4224     impl_->getModifiedSharedNetworks6(server_selector, modification_time, shared_networks);
4225     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_SHARED_NETWORKS6_RESULT)
4226         .arg(shared_networks.size());
4227     return (shared_networks);
4228 }
4229 
4230 OptionDefinitionPtr
getOptionDef6(const ServerSelector & server_selector,const uint16_t code,const std::string & space) const4231 MySqlConfigBackendDHCPv6::getOptionDef6(const ServerSelector& server_selector,
4232                                         const uint16_t code,
4233                                         const std::string& space) const {
4234     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_OPTION_DEF6)
4235         .arg(code).arg(space);
4236     return (impl_->getOptionDef(MySqlConfigBackendDHCPv6Impl::GET_OPTION_DEF6_CODE_SPACE,
4237                                 server_selector, code, space));
4238 }
4239 
4240 OptionDefContainer
getAllOptionDefs6(const ServerSelector & server_selector) const4241 MySqlConfigBackendDHCPv6::getAllOptionDefs6(const ServerSelector& server_selector) const {
4242     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_OPTION_DEFS6);
4243     OptionDefContainer option_defs;
4244     impl_->getAllOptionDefs(MySqlConfigBackendDHCPv6Impl::GET_ALL_OPTION_DEFS6,
4245                             server_selector, option_defs);
4246     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_OPTION_DEFS6_RESULT)
4247         .arg(option_defs.size());
4248     return (option_defs);
4249 }
4250 
4251 OptionDefContainer
getModifiedOptionDefs6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const4252 MySqlConfigBackendDHCPv6::getModifiedOptionDefs6(const ServerSelector& server_selector,
4253         const boost::posix_time::ptime& modification_time) const {
4254     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_OPTION_DEFS6)
4255         .arg(util::ptimeToText(modification_time));
4256     OptionDefContainer option_defs;
4257     impl_->getModifiedOptionDefs(MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTION_DEFS6,
4258                                  server_selector, modification_time, option_defs);
4259     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_OPTION_DEFS6_RESULT)
4260         .arg(option_defs.size());
4261     return (option_defs);
4262 }
4263 
4264 OptionDescriptorPtr
getOption6(const ServerSelector & server_selector,const uint16_t code,const std::string & space) const4265 MySqlConfigBackendDHCPv6::getOption6(const ServerSelector& server_selector,
4266                                      const uint16_t code,
4267                                      const std::string& space) const {
4268     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_OPTION6)
4269         .arg(code).arg(space);
4270     return (impl_->getOption(MySqlConfigBackendDHCPv6Impl::GET_OPTION6_CODE_SPACE,
4271                              Option::V6, server_selector, code, space));
4272 }
4273 
4274 OptionContainer
getAllOptions6(const ServerSelector & server_selector) const4275 MySqlConfigBackendDHCPv6::getAllOptions6(const ServerSelector& server_selector) const {
4276     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_OPTIONS6);
4277     OptionContainer options = impl_->getAllOptions(MySqlConfigBackendDHCPv6Impl::GET_ALL_OPTIONS6,
4278             Option::V6, server_selector);
4279     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_OPTIONS6_RESULT)
4280         .arg(options.size());
4281     return (options);
4282 }
4283 
4284 OptionContainer
getModifiedOptions6(const ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const4285 MySqlConfigBackendDHCPv6::getModifiedOptions6(const ServerSelector& server_selector,
4286         const boost::posix_time::ptime& modification_time) const {
4287     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_OPTIONS6)
4288         .arg(util::ptimeToText(modification_time));
4289     OptionContainer options = impl_->getModifiedOptions(MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_OPTIONS6,
4290             Option::V6, server_selector, modification_time);
4291     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_OPTIONS6_RESULT)
4292         .arg(options.size());
4293     return (options);
4294 }
4295 
4296 StampedValuePtr
getGlobalParameter6(const ServerSelector & server_selector,const std::string & name) const4297 MySqlConfigBackendDHCPv6::getGlobalParameter6(const ServerSelector& server_selector,
4298                                               const std::string& name) const {
4299     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_GLOBAL_PARAMETER6)
4300         .arg(name);
4301     return (impl_->getGlobalParameter6(server_selector, name));
4302 }
4303 
4304 StampedValueCollection
getAllGlobalParameters6(const ServerSelector & server_selector) const4305 MySqlConfigBackendDHCPv6::getAllGlobalParameters6(const ServerSelector& server_selector) const {
4306     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_GLOBAL_PARAMETERS6);
4307     StampedValueCollection parameters;
4308     auto tags = server_selector.getTags();
4309     for (auto tag : tags) {
4310         MySqlBindingCollection in_bindings = { MySqlBinding::createString(tag.get()) };
4311         impl_->getGlobalParameters(MySqlConfigBackendDHCPv6Impl::GET_ALL_GLOBAL_PARAMETERS6,
4312                                    in_bindings, parameters);
4313     }
4314     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_GLOBAL_PARAMETERS6_RESULT)
4315         .arg(parameters.size());
4316     return (parameters);
4317 }
4318 
4319 StampedValueCollection
getModifiedGlobalParameters6(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const4320 MySqlConfigBackendDHCPv6::getModifiedGlobalParameters6(const db::ServerSelector& server_selector,
4321         const boost::posix_time::ptime& modification_time) const {
4322     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_GLOBAL_PARAMETERS6)
4323         .arg(util::ptimeToText(modification_time));
4324     StampedValueCollection parameters;
4325     auto tags = server_selector.getTags();
4326     for (auto tag : tags) {
4327         MySqlBindingCollection in_bindings = {
4328             MySqlBinding::createString(tag.get()),
4329             MySqlBinding::createTimestamp(modification_time)
4330         };
4331         impl_->getGlobalParameters(MySqlConfigBackendDHCPv6Impl::GET_MODIFIED_GLOBAL_PARAMETERS6,
4332                                    in_bindings, parameters);
4333     }
4334     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_GLOBAL_PARAMETERS6_RESULT)
4335         .arg(parameters.size());
4336     return (parameters);
4337 }
4338 
4339 ClientClassDefPtr
getClientClass6(const db::ServerSelector & server_selector,const std::string & name) const4340 MySqlConfigBackendDHCPv6::getClientClass6(const db::ServerSelector& server_selector,
4341                                           const std::string& name) const {
4342     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_CLIENT_CLASS6)
4343         .arg(name);
4344     return (impl_->getClientClass6(server_selector, name));
4345 }
4346 
4347 ClientClassDictionary
getAllClientClasses6(const db::ServerSelector & server_selector) const4348 MySqlConfigBackendDHCPv6::getAllClientClasses6(const db::ServerSelector& server_selector) const {
4349     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_CLIENT_CLASSES6);
4350     ClientClassDictionary client_classes;
4351     impl_->getAllClientClasses6(server_selector, client_classes);
4352     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_CLIENT_CLASSES6_RESULT)
4353         .arg(client_classes.getClasses()->size());
4354     return (client_classes);
4355 }
4356 
4357 ClientClassDictionary
getModifiedClientClasses6(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time) const4358 MySqlConfigBackendDHCPv6::getModifiedClientClasses6(const db::ServerSelector& server_selector,
4359                                                     const boost::posix_time::ptime& modification_time) const {
4360     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_CLIENT_CLASSES6)
4361         .arg(util::ptimeToText(modification_time));
4362     ClientClassDictionary client_classes;
4363     impl_->getModifiedClientClasses6(server_selector, modification_time, client_classes);
4364     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_MODIFIED_CLIENT_CLASSES6_RESULT)
4365         .arg(client_classes.getClasses()->size());
4366     return (client_classes);
4367 }
4368 
4369 AuditEntryCollection
getRecentAuditEntries(const db::ServerSelector & server_selector,const boost::posix_time::ptime & modification_time,const uint64_t & modification_id) const4370 MySqlConfigBackendDHCPv6::getRecentAuditEntries(const db::ServerSelector& server_selector,
4371         const boost::posix_time::ptime& modification_time,
4372         const uint64_t& modification_id) const {
4373     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6)
4374       .arg(util::ptimeToText(modification_time))
4375       .arg(modification_id);
4376     AuditEntryCollection audit_entries;
4377     impl_->getRecentAuditEntries(MySqlConfigBackendDHCPv6Impl::GET_AUDIT_ENTRIES6_TIME,
4378                                  server_selector, modification_time,
4379                                  modification_id, audit_entries);
4380     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_RECENT_AUDIT_ENTRIES6_RESULT)
4381         .arg(audit_entries.size());
4382     return (audit_entries);
4383 }
4384 
4385 ServerCollection
getAllServers6() const4386 MySqlConfigBackendDHCPv6::getAllServers6() const {
4387     ServerCollection servers;
4388 
4389     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SERVERS6);
4390     impl_->getAllServers(MySqlConfigBackendDHCPv6Impl::GET_ALL_SERVERS6,
4391                          servers);
4392 
4393     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_ALL_SERVERS6_RESULT)
4394         .arg(servers.size());
4395     return (servers);
4396 }
4397 
4398 ServerPtr
getServer6(const data::ServerTag & server_tag) const4399 MySqlConfigBackendDHCPv6::getServer6(const data::ServerTag& server_tag) const {
4400     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_SERVER6)
4401         .arg(server_tag.get());
4402     return (impl_->getServer(MySqlConfigBackendDHCPv6Impl::GET_SERVER6, server_tag));
4403 }
4404 
4405 void
createUpdateSubnet6(const ServerSelector & server_selector,const Subnet6Ptr & subnet)4406 MySqlConfigBackendDHCPv6::createUpdateSubnet6(const ServerSelector& server_selector,
4407                                               const Subnet6Ptr& subnet) {
4408     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SUBNET6)
4409         .arg(subnet);
4410     impl_->createUpdateSubnet6(server_selector, subnet);
4411 }
4412 
4413 void
createUpdateSharedNetwork6(const ServerSelector & server_selector,const SharedNetwork6Ptr & shared_network)4414 MySqlConfigBackendDHCPv6::createUpdateSharedNetwork6(const ServerSelector& server_selector,
4415                                                      const SharedNetwork6Ptr& shared_network) {
4416     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK6)
4417         .arg(shared_network->getName());
4418     impl_->createUpdateSharedNetwork6(server_selector, shared_network);
4419 }
4420 
4421 void
createUpdateOptionDef6(const ServerSelector & server_selector,const OptionDefinitionPtr & option_def)4422 MySqlConfigBackendDHCPv6::createUpdateOptionDef6(const ServerSelector& server_selector,
4423                                                  const OptionDefinitionPtr& option_def) {
4424     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_OPTION_DEF6)
4425         .arg(option_def->getName()).arg(option_def->getCode());
4426     impl_->createUpdateOptionDef6(server_selector, option_def);
4427 }
4428 
4429 void
createUpdateOption6(const ServerSelector & server_selector,const OptionDescriptorPtr & option)4430 MySqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector,
4431                                               const OptionDescriptorPtr& option) {
4432     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_OPTION6);
4433     impl_->createUpdateOption6(server_selector, option);
4434 }
4435 
4436 void
createUpdateOption6(const db::ServerSelector & server_selector,const std::string & shared_network_name,const OptionDescriptorPtr & option)4437 MySqlConfigBackendDHCPv6::createUpdateOption6(const db::ServerSelector& server_selector,
4438                                               const std::string& shared_network_name,
4439                                               const OptionDescriptorPtr& option) {
4440     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SHARED_NETWORK_OPTION6)
4441         .arg(shared_network_name);
4442     impl_->createUpdateOption6(server_selector, shared_network_name, option, false);
4443 }
4444 
4445 void
createUpdateOption6(const ServerSelector & server_selector,const SubnetID & subnet_id,const OptionDescriptorPtr & option)4446 MySqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector,
4447                                               const SubnetID& subnet_id,
4448                                               const OptionDescriptorPtr& option) {
4449     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_BY_SUBNET_ID_OPTION6)
4450         .arg(subnet_id);
4451     impl_->createUpdateOption6(server_selector, subnet_id, option, false);
4452 }
4453 
4454 void
createUpdateOption6(const ServerSelector & server_selector,const asiolink::IOAddress & pool_start_address,const asiolink::IOAddress & pool_end_address,const OptionDescriptorPtr & option)4455 MySqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector,
4456                                               const asiolink::IOAddress& pool_start_address,
4457                                               const asiolink::IOAddress& pool_end_address,
4458                                               const OptionDescriptorPtr& option) {
4459     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_BY_POOL_OPTION6)
4460         .arg(pool_start_address.toText()).arg(pool_end_address.toText());
4461     impl_->createUpdateOption6(server_selector, pool_start_address, pool_end_address,
4462                                option);
4463 }
4464 
4465 void
createUpdateOption6(const ServerSelector & server_selector,const asiolink::IOAddress & pd_pool_prefix,const uint8_t pd_pool_prefix_length,const OptionDescriptorPtr & option)4466 MySqlConfigBackendDHCPv6::createUpdateOption6(const ServerSelector& server_selector,
4467                                               const asiolink::IOAddress& pd_pool_prefix,
4468                                               const uint8_t pd_pool_prefix_length,
4469                                               const OptionDescriptorPtr& option) {
4470     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_BY_PREFIX_OPTION6)
4471         .arg(pd_pool_prefix.toText()).arg(pd_pool_prefix_length);
4472     impl_->createUpdateOption6(server_selector, pd_pool_prefix,
4473                                pd_pool_prefix_length, option);
4474 }
4475 
4476 void
createUpdateGlobalParameter6(const ServerSelector & server_selector,const StampedValuePtr & value)4477 MySqlConfigBackendDHCPv6::createUpdateGlobalParameter6(const ServerSelector& server_selector,
4478                                                        const StampedValuePtr& value) {
4479     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_GLOBAL_PARAMETER6)
4480         .arg(value->getName());
4481     impl_->createUpdateGlobalParameter6(server_selector, value);
4482 }
4483 
4484 void
createUpdateClientClass6(const db::ServerSelector & server_selector,const ClientClassDefPtr & client_class,const std::string & follow_class_name)4485 MySqlConfigBackendDHCPv6::createUpdateClientClass6(const db::ServerSelector& server_selector,
4486                                                    const ClientClassDefPtr& client_class,
4487                                                    const std::string& follow_class_name) {
4488     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_CLIENT_CLASS6)
4489         .arg(client_class->getName());
4490     impl_->createUpdateClientClass6(server_selector, client_class, follow_class_name);
4491 }
4492 
4493 void
createUpdateServer6(const ServerPtr & server)4494 MySqlConfigBackendDHCPv6::createUpdateServer6(const ServerPtr& server) {
4495     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_CREATE_UPDATE_SERVER6)
4496         .arg(server->getServerTagAsText());
4497     impl_->createUpdateServer(MySqlConfigBackendDHCPv6Impl::CREATE_AUDIT_REVISION,
4498                               MySqlConfigBackendDHCPv6Impl::INSERT_SERVER6,
4499                               MySqlConfigBackendDHCPv6Impl::UPDATE_SERVER6,
4500                               server);
4501 }
4502 
4503 uint64_t
deleteSubnet6(const ServerSelector & server_selector,const std::string & subnet_prefix)4504 MySqlConfigBackendDHCPv6::deleteSubnet6(const ServerSelector& server_selector,
4505                                         const std::string& subnet_prefix) {
4506     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET6)
4507         .arg(subnet_prefix);
4508     uint64_t result = impl_->deleteSubnet6(server_selector, subnet_prefix);
4509     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET6_RESULT)
4510         .arg(result);
4511     return (result);
4512 }
4513 
4514 uint64_t
deleteSubnet6(const ServerSelector & server_selector,const SubnetID & subnet_id)4515 MySqlConfigBackendDHCPv6::deleteSubnet6(const ServerSelector& server_selector,
4516                                         const SubnetID& subnet_id) {
4517     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_SUBNET_ID_SUBNET6)
4518         .arg(subnet_id);
4519     uint64_t result = impl_->deleteSubnet6(server_selector, subnet_id);
4520     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_SUBNET_ID_SUBNET6_RESULT)
4521         .arg(result);
4522     return (result);
4523 }
4524 
4525 uint64_t
deleteAllSubnets6(const ServerSelector & server_selector)4526 MySqlConfigBackendDHCPv6::deleteAllSubnets6(const ServerSelector& server_selector) {
4527     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SUBNETS6);
4528 
4529     int index = (server_selector.amUnassigned() ?
4530                  MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_UNASSIGNED :
4531                  MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6);
4532     uint64_t result = impl_->deleteTransactional(index, server_selector, "deleting all subnets",
4533                                                  "deleted all subnets", true);
4534     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SUBNETS6_RESULT)
4535         .arg(result);
4536     return (result);
4537 }
4538 
4539 uint64_t
deleteSharedNetworkSubnets6(const db::ServerSelector & server_selector,const std::string & shared_network_name)4540 MySqlConfigBackendDHCPv6::deleteSharedNetworkSubnets6(const db::ServerSelector& server_selector,
4541                                                       const std::string& shared_network_name) {
4542     if (!server_selector.amAny()) {
4543         isc_throw(InvalidOperation, "deleting all subnets from a shared "
4544                   "network requires using ANY server selector");
4545     }
4546     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK_SUBNETS6)
4547         .arg(shared_network_name);
4548     uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
4549                                                  server_selector,
4550                                                  "deleting all subnets for a shared network",
4551                                                  "deleted all subnets for a shared network",
4552                                                  true, shared_network_name);
4553     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK_SUBNETS6_RESULT)
4554         .arg(result);
4555     return (result);
4556 }
4557 
4558 uint64_t
deleteSharedNetwork6(const ServerSelector & server_selector,const std::string & name)4559 MySqlConfigBackendDHCPv6::deleteSharedNetwork6(const ServerSelector& server_selector,
4560                                                const std::string& name) {
4561     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK6)
4562         .arg(name);
4563     int index = (server_selector.amAny() ?
4564                  MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_ANY :
4565                  MySqlConfigBackendDHCPv6Impl::DELETE_SHARED_NETWORK6_NAME_WITH_TAG);
4566     uint64_t result = impl_->deleteTransactional(index, server_selector,
4567                                                  "deleting a shared network",
4568                                                  "shared network deleted", true, name);
4569     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK6_RESULT)
4570         .arg(result);
4571     return (result);
4572 }
4573 
4574 uint64_t
deleteAllSharedNetworks6(const ServerSelector & server_selector)4575 MySqlConfigBackendDHCPv6::deleteAllSharedNetworks6(const ServerSelector& server_selector) {
4576     if (server_selector.amAny()) {
4577         isc_throw(InvalidOperation, "deleting all shared networks for ANY server is not"
4578                   " supported");
4579     }
4580 
4581     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SHARED_NETWORKS6);
4582 
4583     int index = (server_selector.amUnassigned() ?
4584                  MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6_UNASSIGNED :
4585                  MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SHARED_NETWORKS6);
4586     uint64_t result = impl_->deleteTransactional(index,
4587                                                  server_selector, "deleting all shared networks",
4588                                                  "deleted all shared networks", true);
4589     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SHARED_NETWORKS6_RESULT)
4590         .arg(result);
4591     return (result);
4592 }
4593 
4594 uint64_t
deleteOptionDef6(const ServerSelector & server_selector,const uint16_t code,const std::string & space)4595 MySqlConfigBackendDHCPv6::deleteOptionDef6(const ServerSelector& server_selector,
4596                                            const uint16_t code,
4597                                            const std::string& space) {
4598     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_OPTION_DEF6)
4599         .arg(code).arg(space);
4600     uint64_t result = impl_->deleteOptionDef6(server_selector, code, space);
4601     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_OPTION_DEF6_RESULT)
4602         .arg(result);
4603     return (result);
4604 }
4605 
4606 uint64_t
deleteAllOptionDefs6(const ServerSelector & server_selector)4607 MySqlConfigBackendDHCPv6::deleteAllOptionDefs6(const ServerSelector& server_selector) {
4608     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_OPTION_DEFS6);
4609     uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_ALL_OPTION_DEFS6,
4610                                                  server_selector, "deleting all option definitions",
4611                                                  "deleted all option definitions", true);
4612     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_OPTION_DEFS6_RESULT)
4613         .arg(result);
4614     return (result);
4615 }
4616 
4617 uint64_t
deleteOption6(const ServerSelector & server_selector,const uint16_t code,const std::string & space)4618 MySqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& server_selector,
4619                                         const uint16_t code,
4620                                         const std::string& space) {
4621     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_OPTION6)
4622         .arg(code).arg(space);
4623     uint64_t result = impl_->deleteOption6(server_selector, code, space);
4624     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_OPTION6_RESULT)
4625         .arg(result);
4626     return (result);
4627 }
4628 
4629 uint64_t
deleteOption6(const ServerSelector &,const std::string & shared_network_name,const uint16_t code,const std::string & space)4630 MySqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */,
4631                                         const std::string& shared_network_name,
4632                                         const uint16_t code,
4633                                         const std::string& space) {
4634     /// @todo In the future we might use the server selector to make sure that the
4635     /// option is only deleted if the pool belongs to a given server. For now, we
4636     /// just delete it when there is a match with the parent object.
4637     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK_OPTION6)
4638         .arg(shared_network_name).arg(code).arg(space);
4639     uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), shared_network_name,
4640                                            code, space);
4641     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SHARED_NETWORK_OPTION6_RESULT)
4642         .arg(result);
4643     return (result);
4644 }
4645 
4646 uint64_t
deleteOption6(const ServerSelector &,const SubnetID & subnet_id,const uint16_t code,const std::string & space)4647 MySqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */,
4648                                         const SubnetID& subnet_id,
4649                                         const uint16_t code,
4650                                         const std::string& space) {
4651     /// @todo In the future we might use the server selector to make sure that the
4652     /// option is only deleted if the pool belongs to a given server. For now, we
4653     /// just delete it when there is a match with the parent object.
4654     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_SUBNET_ID_OPTION6)
4655         .arg(subnet_id).arg(code).arg(space);
4656     uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), subnet_id, code, space);
4657     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_SUBNET_ID_OPTION6_RESULT)
4658         .arg(result);
4659     return (result);
4660 }
4661 
4662 uint64_t
deleteOption6(const ServerSelector &,const asiolink::IOAddress & pool_start_address,const asiolink::IOAddress & pool_end_address,const uint16_t code,const std::string & space)4663 MySqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */,
4664                                         const asiolink::IOAddress& pool_start_address,
4665                                         const asiolink::IOAddress& pool_end_address,
4666                                         const uint16_t code,
4667                                         const std::string& space) {
4668     /// @todo In the future we might use the server selector to make sure that the
4669     /// option is only deleted if the pool belongs to a given server. For now, we
4670     /// just delete it when there is a match with the parent object.
4671     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_POOL_OPTION6)
4672         .arg(pool_start_address.toText()).arg(pool_end_address.toText()).arg(code).arg(space);
4673     uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), pool_start_address, pool_end_address,
4674                                            code, space);
4675     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_POOL_OPTION6_RESULT)
4676         .arg(result);
4677     return (result);
4678 }
4679 
4680 uint64_t
deleteOption6(const ServerSelector &,const asiolink::IOAddress & pd_pool_prefix,const uint8_t pd_pool_prefix_length,const uint16_t code,const std::string & space)4681 MySqlConfigBackendDHCPv6::deleteOption6(const ServerSelector& /* server_selector */,
4682                                         const asiolink::IOAddress& pd_pool_prefix,
4683                                         const uint8_t pd_pool_prefix_length,
4684                                         const uint16_t code,
4685                                         const std::string& space) {
4686     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_POOL_PREFIX_OPTION6)
4687         .arg(pd_pool_prefix.toText()).arg(pd_pool_prefix_length).arg(code).arg(space);
4688     uint64_t result = impl_->deleteOption6(ServerSelector::ANY(), pd_pool_prefix,
4689                                            pd_pool_prefix_length, code, space);
4690     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_POOL_PREFIX_OPTION6_RESULT)
4691         .arg(result);
4692     return (result);
4693 }
4694 
4695 uint64_t
deleteGlobalParameter6(const ServerSelector & server_selector,const std::string & name)4696 MySqlConfigBackendDHCPv6::deleteGlobalParameter6(const ServerSelector& server_selector,
4697                                                  const std::string& name) {
4698     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_GLOBAL_PARAMETER6)
4699         .arg(name);
4700     uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_GLOBAL_PARAMETER6,
4701                                                  server_selector, "deleting global parameter",
4702                                                  "global parameter deleted", false, name);
4703     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_GLOBAL_PARAMETER6_RESULT)
4704         .arg(result);
4705     return (result);
4706 }
4707 
4708 uint64_t
deleteAllGlobalParameters6(const ServerSelector & server_selector)4709 MySqlConfigBackendDHCPv6::deleteAllGlobalParameters6(const ServerSelector& server_selector) {
4710     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_GLOBAL_PARAMETERS6);
4711     uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_ALL_GLOBAL_PARAMETERS6,
4712                                                  server_selector, "deleting all global parameters",
4713                                                  "all global parameters deleted", true);
4714     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_GLOBAL_PARAMETERS6_RESULT)
4715         .arg(result);
4716     return (result);
4717 }
4718 
4719 uint64_t
deleteClientClass6(const db::ServerSelector & server_selector,const std::string & name)4720 MySqlConfigBackendDHCPv6::deleteClientClass6(const db::ServerSelector& server_selector,
4721                                              const std::string& name) {
4722     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_CLIENT_CLASS6)
4723         .arg(name);
4724     auto result = impl_->deleteClientClass6(server_selector, name);
4725     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_CLIENT_CLASS6_RESULT)
4726         .arg(result);
4727     return (result);
4728 }
4729 
4730 uint64_t
deleteAllClientClasses6(const db::ServerSelector & server_selector)4731 MySqlConfigBackendDHCPv6::deleteAllClientClasses6(const db::ServerSelector& server_selector) {
4732     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_CLIENT_CLASSES6);
4733 
4734     int index = (server_selector.amUnassigned() ?
4735                  MySqlConfigBackendDHCPv6Impl::DELETE_ALL_CLIENT_CLASSES6_UNASSIGNED :
4736                  MySqlConfigBackendDHCPv6Impl::DELETE_ALL_CLIENT_CLASSES6);
4737     uint64_t result = impl_->deleteTransactional(index, server_selector, "deleting all client classes",
4738                                                  "deleted all client classes", true);
4739     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_CLIENT_CLASSES6_RESULT)
4740         .arg(result);
4741     return (result);
4742 }
4743 
4744 uint64_t
deleteServer6(const ServerTag & server_tag)4745 MySqlConfigBackendDHCPv6::deleteServer6(const ServerTag& server_tag) {
4746     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SERVER6)
4747         .arg(server_tag.get());
4748     uint64_t result = impl_->deleteServer6(server_tag);
4749     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_SERVER6_RESULT)
4750         .arg(result);
4751     return (result);
4752 }
4753 
4754 uint64_t
deleteAllServers6()4755 MySqlConfigBackendDHCPv6::deleteAllServers6() {
4756     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SERVERS6);
4757     uint64_t result = impl_->deleteAllServers6();
4758     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_ALL_SERVERS6_RESULT)
4759         .arg(result);
4760     return (result);
4761 }
4762 
4763 std::string
getType() const4764 MySqlConfigBackendDHCPv6::getType() const {
4765     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_TYPE6);
4766     return (impl_->getType());
4767 }
4768 
4769 std::string
getHost() const4770 MySqlConfigBackendDHCPv6::getHost() const {
4771     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_HOST6);
4772     return (impl_->getHost());
4773 }
4774 
4775 uint16_t
getPort() const4776 MySqlConfigBackendDHCPv6::getPort() const {
4777     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_GET_PORT6);
4778     return (impl_->getPort());
4779 }
4780 
4781 bool
registerBackendType()4782 MySqlConfigBackendDHCPv6::registerBackendType() {
4783     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_REGISTER_BACKEND_TYPE6);
4784     return (
4785         dhcp::ConfigBackendDHCPv6Mgr::instance().registerBackendFactory("mysql",
4786             [](const db::DatabaseConnection::ParameterMap& params) -> dhcp::ConfigBackendDHCPv6Ptr {
4787             return (dhcp::MySqlConfigBackendDHCPv6Ptr(new dhcp::MySqlConfigBackendDHCPv6(params)));
4788         })
4789     );
4790 }
4791 
4792 void
unregisterBackendType()4793 MySqlConfigBackendDHCPv6::unregisterBackendType() {
4794     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_UNREGISTER_BACKEND_TYPE6);
4795     dhcp::ConfigBackendDHCPv6Mgr::instance().unregisterBackendFactory("mysql");
4796 }
4797 
4798 } // end of namespace isc::dhcp
4799 } // end of namespace isc
4800