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