[chmod +x src/share/database/scripts/mysql/upgrade_012_to_013.sh])
AC_CONFIG_FILES([src/share/database/scripts/mysql/upgrade_013_to_014.sh],
[chmod +x src/share/database/scripts/mysql/upgrade_013_to_014.sh])
+AC_CONFIG_FILES([src/share/database/scripts/mysql/upgrade_014_to_015.sh],
+ [chmod +x src/share/database/scripts/mysql/upgrade_014_to_015.sh])
AC_CONFIG_FILES([src/share/database/scripts/mysql/wipe_data.sh],
[chmod +x src/share/database/scripts/mysql/wipe_data.sh])
AC_CONFIG_FILES([src/share/database/scripts/pgsql/Makefile])
[chmod +x src/share/database/scripts/pgsql/upgrade_011_to_012.sh])
AC_CONFIG_FILES([src/share/database/scripts/pgsql/upgrade_012_to_013.sh],
[chmod +x src/share/database/scripts/pgsql/upgrade_012_to_013.sh])
+AC_CONFIG_FILES([src/share/database/scripts/pgsql/upgrade_013_to_014.sh],
+ [chmod +x src/share/database/scripts/pgsql/upgrade_013_to_014.sh])
AC_CONFIG_FILES([src/share/database/scripts/pgsql/wipe_data.sh],
[chmod +x src/share/database/scripts/pgsql/wipe_data.sh])
AC_CONFIG_FILES([src/share/yang/Makefile])
// provided.
"name": "domain-name-servers",
+ // Boolean flag indicating if the given option is never
+ // send in response. The default value of false indicates
+ // that it is sent when it should. When true the option
+ // is not sent despite of any other setting, i.e. it is
+ // a final flag.
+ "never-send": false,
+
// Option space. The default is the "dhcp4" option space which
// groups top level DHCPv4 options.
"space": "dhcp4"
// Option name.
"name": "routers",
+ // Boolean flag indicating if the given option is never
+ // send in response.
+ "never-send": false,
+
// Option space. The default value "dhcp4" designates the
// top level option space.
"space": "dhcp4"
// provided.
"name": "domain-name-servers",
+ // Boolean flag indicating if the given option is never
+ // send in response. The default value of false indicates
+ // that it is sent when it should. When true the option
+ // is not sent despite of any other setting, i.e. it is
+ // a final flag.
+ "never-send": false,
+
// Option space. The default is the "dhcp4" option space which
// groups top level DHCPv4 options.
"space": "dhcp4"
// Option name.
"name": "routers",
+ // Boolean flag indicating if the given option is never
+ // send in response.
+ "never-send": false,
+
// Option space. The default value "dhcp4" designates the
// top level option space.
"space": "dhcp4"
// provided.
"name": "dns-servers",
+ // Boolean flag indicating if the given option is never
+ // send in response. The default value of false indicates
+ // that it is sent when it should. When true the option
+ // is not sent despite of any other setting, i.e. it is
+ // a final flag.
+ "never-send": false,
+
// Option space. The default is the "dhcp6" option space which
// groups top level DHCPv6 options.
"space": "dhcp6"
// Option name.
"name": "preference",
+ // Boolean flag indicating if the given option is never
+ // send in response.
+ "never-send": false,
+
// Option space. The default value "dhcp6" designates the
// top level option space.
"space": "dhcp6"
// provided.
"name": "dns-servers",
+ // Boolean flag indicating if the given option is never
+ // send in response. The default value of false indicates
+ // that it is sent when it should. When true the option
+ // is not sent despite of any other setting, i.e. it is
+ // a final flag.
+ "never-send": false,
+
// Option space. The default is the "dhcp6" option space which
// groups top level DHCPv6 options.
"space": "dhcp6"
// Option name.
"name": "preference",
+ // Boolean flag indicating if the given option is never
+ // send in response.
+ "never-send": false,
+
// Option space. The default value "dhcp6" designates the
// top level option space.
"space": "dhcp6"
always-send is "sticky"), but the value is the subnet one when the client
is localized in the subnet.
+At the opposite of ``always-send`` if the ``never-send`` flag is set to
+``true`` for a particular option the server does not add it to the response.
+The effect is the same as if the client removed the option code in the
+Parameter Request List option Option (or its equivalent for vendor options):
+
+::
+
+ "Dhcp4": {
+ "option-data": [
+ {
+ "name": "domain-name-servers",
+ "data": "192.0.2.1, 192.0.2.2"
+ },
+ ...
+ ],
+ "subnet4": [
+ {
+ "subnet": "192.0.3.0/24",
+ "option-data": [
+ {
+ "name": "domain-name-servers",
+ "never-send": true
+ },
+ ...
+ ],
+ ...
+ },
+ ...
+ ],
+ ...
+ }
+
+The ``domain-name-servers`` option is never added to responses (the
+never-send is "sticky" too). The ``never-send`` is as the precedence
+over ``always-send`` so if both are true the option is not added.
+
+.. note::
+
+ The ``never-send`` is less powerful than the :ref:`hooks-flex-option`,
+ for instance it has no effect on options managed by the server itself.
+ Both ``always-send`` and ``never-send`` has no effect too on options
+ which cannot be requested, for instance from a custom space.
+
The ``name`` parameter specifies the option name. For a list of
currently supported names, see :ref:`dhcp4-std-options-list`
below. The ``code`` parameter specifies the option code, which must
"sticky"), but the value is the subnet one when the client is localized
in the subnet.
+At the opposite of ``always-send`` if the ``never-send`` flag is set to
+``true`` for a particular option the server does not add it to the response.
+The effect is the same as if the client removed the option code in the
+Option Request Option (or its equivalent for vendor options), as in:
+
+::
+
+ "Dhcp6": {
+ "option-data": [
+ {
+ "name": "dns-servers",
+ "data": "2001:db8::cafe, 2001:db8::babe"
+ },
+ ...
+ ],
+ "subnet6": [
+ {
+ "subnet": "2001:db8:1::/64",
+ "option-data": [
+ {
+ "name": "dns-servers",
+ "never-send": true
+ },
+ ...
+ ],
+ ...
+ },
+ ...
+ ],
+ ...
+ }
+
+The ``dns-server`` option is never added to responses (the never-send is
+"sticky" too). The ``never-send`` is as the precedence over ``always-send``
+so if both are true the option is not added.
+
+.. note::
+
+ The ``never-send`` is less powerful than the :ref:`hooks-flex-option`,
+ for instance it has no effect on options managed by the server itself.
+ Both ``always-send`` and ``never-send`` has no effect too on options
+ which cannot be requested, for instance from a custom space.
+
It is possible to override options on a per-subnet basis. If clients
connected to most subnets are expected to get the same values of
a given option, administrators should use global options; it is possible to override
# Verify that the upgraded schema reports the latest version.
version=$("${kea_admin}" db-version mysql -u "${db_user}" -p "${db_password}" -n "${db_name}" -d "${db_scripts_dir}")
- assert_str_eq "14.0" "${version}" "Expected kea-admin to return %s, returned value was %s"
+ assert_str_eq "15.0" "${version}" "Expected kea-admin to return %s, returned value was %s"
# Let's check that the new tables are indeed there.
# Check upgrade from 13.0 to 14.0.
mysql_upgrade_13_to_14_test
+ # Check upgrade from 14.0 to 15.0.
+
+ # table: dhcp4_options new cancelled column.
+ qry="select cancelled from dhcp4_options"
+ run_statement "dhcp4_options" "$qry"
+
+ # table: dhcp6_options new cancelled column.
+ qry="select cancelled from dhcp6_options"
+ run_statement "dhcp6_options" "$qry"
+
# Let's wipe the whole database
mysql_wipe
run_command \
"${kea_admin}" db-version pgsql -u "${db_user}" -p "${db_password}" -n "${db_name}"
version="${OUTPUT}"
- assert_str_eq "13.0" "${version}" "Expected kea-admin to return %s, returned value was %s"
+ assert_str_eq "14.0" "${version}" "Expected kea-admin to return %s, returned value was %s"
# Let's wipe the whole database
pgsql_wipe
done
}
+pgsql_upgrade_13_to_14_test() {
+ # Added cancelled column to dhcp4_options
+ run_command \
+ pgsql_execute "select cancelled from dhcp4_options;"
+ assert_eq 0 "${EXIT_CODE}" "dhcp4_options is missing cancelled column. (expected status code %d, returned %d)"
+
+ # Added cancelled column to dhcp6_options
+ run_command \
+ pgsql_execute "select cancelled from dhcp6_options;"
+ assert_eq 0 "${EXIT_CODE}" "dhcp6_options is missing cancelled column. (expected status code %d, returned %d)"
+}
+
pgsql_upgrade_test() {
test_start "pgsql.upgrade"
# Verify upgraded schema reports the latest version.
version=$("${kea_admin}" db-version pgsql -u "${db_user}" -p "${db_password}" -n "${db_name}" -d "${db_scripts_dir}")
- assert_str_eq "13.0" "${version}" 'Expected kea-admin to return %s, returned value was %s'
+ assert_str_eq "14.0" "${version}" 'Expected kea-admin to return %s, returned value was %s'
# Check 1.0 to 2.0 upgrade
pgsql_upgrade_1_0_to_2_0
# Check 12 to 13 upgrade
pgsql_upgrade_12_to_13_test
+ # Check 13 to 14 upgrade
+ pgsql_upgrade_13_to_14_test
+
# Let's wipe the whole database
pgsql_wipe
}
}
+\"never-send\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::OPTION_DATA:
+ return isc::dhcp::Dhcp4Parser::make_NEVER_SEND(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp4Parser::make_STRING("never-send", driver.loc_);
+ }
+}
+
\"pools\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::SUBNET4:
SPACE "space"
CSV_FORMAT "csv-format"
ALWAYS_SEND "always-send"
+ NEVER_SEND "never-send"
RECORD_TYPES "record-types"
ENCAPSULATE "encapsulate"
ARRAY "array"
| option_data_space
| option_data_csv_format
| option_data_always_send
+ | option_data_never_send
| user_context
| comment
| unknown_map_entry
ctx.stack_.back()->set("always-send", persist);
};
+option_data_never_send: NEVER_SEND COLON BOOLEAN {
+ ctx.unique("never-send", ctx.loc2pos(@1));
+ ElementPtr persist(new BoolElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("never-send", persist);
+};
+
// ---- pools ------------------------------------
// This defines the "pools": [ ... ] entry that may appear in subnet4.
}
}
- // Iterate on the configured option list to add persistent options
+ std::set<uint8_t> cancelled_opts;
+
+ // Iterate on the configured option list to add persistent and
+ // cancelled options.
for (auto const& copts : co_list) {
const OptionContainerPtr& opts = copts->getAll(DHCP4_OPTION_SPACE);
if (!opts) {
continue;
}
- // Get persistent options
- const OptionContainerPersistIndex& idx = opts->get<2>();
- const OptionContainerPersistRange& range = idx.equal_range(true);
- for (OptionContainerPersistIndex::const_iterator desc = range.first;
- desc != range.second; ++desc) {
- // Add the persistent option code to requested options
+ // Get persistent options.
+ const OptionContainerPersistIndex& pidx = opts->get<2>();
+ const OptionContainerPersistRange& prange = pidx.equal_range(true);
+ for (OptionContainerPersistIndex::const_iterator desc = prange.first;
+ desc != prange.second; ++desc) {
+ // Add the persistent option code to requested options.
if (desc->option_) {
- uint16_t code = desc->option_->getType();
+ uint8_t code = static_cast<uint8_t>(desc->option_->getType());
static_cast<void>(requested_opts.insert(code));
}
}
- }
+ // Get cancelled options.
+ const OptionContainerCancelIndex& cidx = opts->get<5>();
+ const OptionContainerCancelRange& crange = cidx.equal_range(true);
+ for (OptionContainerCancelIndex::const_iterator desc = crange.first;
+ desc != crange.second; ++desc) {
+ // Add the cancelled option code to cancelled options.
+ if (desc->option_) {
+ uint8_t code = static_cast<uint8_t>(desc->option_->getType());
+ static_cast<void>(cancelled_opts.insert(code));
+ }
+ }
+ }
// For each requested option code get the first instance of the option
// to be returned to the client.
- for (auto const& opt : requested_opts) {
- // Add nothing when it is already there.
+ for (uint8_t opt : requested_opts) {
+ if (cancelled_opts.count(opt) > 0) {
+ continue;
+ }
// Skip special cases: DHO_VIVSO_SUBOPTIONS.
if (opt == DHO_VIVSO_SUBOPTIONS) {
continue;
}
+ // Add nothing when it is already there.
if (!resp->getOption(opt)) {
// Iterate on the configured option list
for (auto const& copts : co_list) {
// Special cases for vendor class and options which are identified
// by the code/type and the vendor/enterprise id vs. the code/type only.
- if (requested_opts.count(DHO_VIVCO_SUBOPTIONS) > 0) {
+ if ((requested_opts.count(DHO_VIVCO_SUBOPTIONS) > 0) &&
+ (cancelled_opts.count(DHO_VIVCO_SUBOPTIONS) == 0)) {
// Keep vendor ids which are already in the response to insert
// VIVCO options at most once per vendor.
set<uint32_t> vendor_ids;
}
}
- if (requested_opts.count(DHO_VIVSO_SUBOPTIONS) > 0) {
+ if ((requested_opts.count(DHO_VIVSO_SUBOPTIONS) > 0) &&
+ (cancelled_opts.count(DHO_VIVSO_SUBOPTIONS) == 0)) {
// Keep vendor ids which are already in the response to insert
// VIVSO options at most once per vendor.
set<uint32_t> vendor_ids;
}
}
- // Iterate on the configured option list to add persistent options
for (uint32_t vendor_id : vendor_ids) {
+
+ std::set<uint8_t> cancelled_opts;
+
+ // Iterate on the configured option list to add persistent and
+ // cancelled options,
for (auto const& copts : co_list) {
const OptionContainerPtr& opts = copts->getAll(vendor_id);
if (!opts) {
continue;
}
- // Get persistent options
- const OptionContainerPersistIndex& idx = opts->get<2>();
- const OptionContainerPersistRange& range = idx.equal_range(true);
- for (OptionContainerPersistIndex::const_iterator desc = range.first;
- desc != range.second; ++desc) {
- if (!desc->option_) {
- continue;
+
+ // Get persistent options.
+ const OptionContainerPersistIndex& pidx = opts->get<2>();
+ const OptionContainerPersistRange& prange = pidx.equal_range(true);
+ for (OptionContainerPersistIndex::const_iterator desc = prange.first;
+ desc != prange.second; ++desc) {
+ // Add the persistent option code to requested options.
+ if (desc->option_) {
+ uint8_t code = static_cast<uint8_t>(desc->option_->getType());
+ static_cast<void>(requested_opts[vendor_id].insert(code));
+ }
+ }
+
+ // Get cancelled options.
+ const OptionContainerCancelIndex& cidx = opts->get<5>();
+ const OptionContainerCancelRange& crange = cidx.equal_range(true);
+ for (OptionContainerCancelIndex::const_iterator desc = crange.first;
+ desc != crange.second; ++desc) {
+ // Add the cancelled option code to cancelled options.
+ if (desc->option_) {
+ uint8_t code = static_cast<uint8_t>(desc->option_->getType());
+ static_cast<void>(cancelled_opts.insert(code));
}
- // Add the persistent option code to requested options
- uint16_t code = desc->option_->getType();
- static_cast<void>(requested_opts[vendor_id].insert(code));
}
}
continue;
}
- // It's possible that the vendor opts option was inserted already
- // by client class or a hook. If that is so, let's use it.
+
+ // It's possible that vivso was inserted already by client class or
+ // a hook. If that is so, let's use it.
OptionVendorPtr vendor_rsp;
if (vendor_rsps.count(vendor_id) > 0) {
vendor_rsp = vendor_rsps[vendor_id];
bool added = false;
for (uint8_t opt : requested_opts[vendor_id]) {
+ if (cancelled_opts.count(opt) > 0) {
+ continue;
+ }
if (!vendor_rsp->getOption(opt)) {
for (auto const& copts : co_list) {
OptionDescriptor desc = copts->get(vendor_id, opt);
// Add host-name to the first backend.
opt.reset(new OptionDescriptor(
createOption<OptionString>(Option::V4, DHO_HOST_NAME,
- true, false, "new.example.com")));
+ true, false, false,
+ "new.example.com")));
opt->space_name_ = DHCP4_OPTION_SPACE;
db1_->createUpdateOption4(ServerSelector::ALL(), opt);
// Add boot-file-name to the first backend.
opt.reset(new OptionDescriptor(
createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "my-boot-file")));
+ true, false, false,
+ "my-boot-file")));
opt->space_name_ = DHCP4_OPTION_SPACE;
db1_->createUpdateOption4(ServerSelector::ALL(), opt);
// Add boot-file-name to the second backend.
opt.reset(new OptionDescriptor(
createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "your-boot-file")));
+ true, false, false,
+ "your-boot-file")));
opt->space_name_ = DHCP4_OPTION_SPACE;
db2_->createUpdateOption4(ServerSelector::ALL(), opt);
<< subnet_address.toText() << "'. Expected "
" at most one option";
} else if (std::distance(range.first, range.second) == 0) {
- return (OptionDescriptor(OptionPtr(), false));
+ return (OptionDescriptor(OptionPtr(), false, false));
}
return (*range.first);
"}",
// Configuration 3:
+ // - 1 subnet with never-send option
+ // - 2 global options (one forced with always-send)
+ "{"
+ " \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ] }, "
+ " \"rebind-timer\": 2000, "
+ " \"renew-timer\": 1000, "
+ " \"valid-lifetime\": 4000, "
+ " \"subnet4\": [ {"
+ " \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ], "
+ " \"subnet\": \"192.0.2.0/24\","
+ " \"option-data\": ["
+ " {"
+ " \"name\": \"ip-forwarding\", "
+ " \"never-send\": true"
+ " }"
+ " ]"
+ " } ], "
+ " \"option-data\": ["
+ " {"
+ " \"name\": \"default-ip-ttl\", "
+ " \"data\": \"FF\", "
+ " \"csv-format\": false"
+ " }, "
+ " {"
+ " \"name\": \"ip-forwarding\", "
+ " \"data\": \"false\", "
+ " \"always-send\": true"
+ " }"
+ " ]"
+ "}",
+
+ // Configuration 4:
// - one subnet, with one pool
// - user-contexts defined in both subnet and pool
"{"
EXPECT_EQ(12345678, opt32->getValue());
}
-// Checks effect of persistency (aka always-true) flag on the PRL
+// Checks effect of persistency (aka always-send) flag on the PRL.
TEST_F(Dhcpv4SrvTest, prlPersistency) {
IfaceMgrTestConfig test_config(true);
ASSERT_FALSE(response->getOption(DHO_ARP_CACHE_TIMEOUT));
}
+// Checks effect of cancellation (aka never-send) flag.
+TEST_F(Dhcpv4SrvTest, neverSend) {
+ IfaceMgrTestConfig test_config(true);
+
+ ASSERT_NO_THROW(configure(CONFIGS[3]));
+
+ // Create a packet with enough to select the subnet and go through
+ // the DISCOVER processing
+ Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234));
+ query->setRemoteAddr(IOAddress("192.0.2.1"));
+ OptionPtr clientid = generateClientId();
+ query->addOption(clientid);
+ query->setIface("eth1");
+ query->setIndex(ETH1_INDEX);
+
+ // Create and add a PRL option for another option
+ OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
+ DHO_DHCP_PARAMETER_REQUEST_LIST));
+ ASSERT_TRUE(prl);
+ prl->addValue(DHO_ARP_CACHE_TIMEOUT);
+ query->addOption(prl);
+
+ // Create and add a host-name option to the query
+ OptionStringPtr hostname(new OptionString(Option::V4, 12, "foo"));
+ ASSERT_TRUE(hostname);
+ query->addOption(hostname);
+
+ // Let the server process it.
+ Pkt4Ptr response = srv_.processDiscover(query);
+
+ // Processing should not add an ip-forwarding option
+ ASSERT_FALSE(response->getOption(DHO_IP_FORWARDING));
+ // And no default-ip-ttl
+ ASSERT_FALSE(response->getOption(DHO_DEFAULT_IP_TTL));
+ // Nor an arp-cache-timeout
+ ASSERT_FALSE(response->getOption(DHO_ARP_CACHE_TIMEOUT));
+
+ // Reset PRL adding default-ip-ttl
+ query->delOption(DHO_DHCP_PARAMETER_REQUEST_LIST);
+ prl->addValue(DHO_DEFAULT_IP_TTL);
+ query->addOption(prl);
+
+ // Let the server process it again.
+ response = srv_.processDiscover(query);
+
+ // Processing should not add an ip-forwarding option
+ ASSERT_FALSE(response->getOption(DHO_IP_FORWARDING));
+ // And now a default-ip-ttl
+ ASSERT_TRUE(response->getOption(DHO_DEFAULT_IP_TTL));
+ // And still no arp-cache-timeout
+ ASSERT_FALSE(response->getOption(DHO_ARP_CACHE_TIMEOUT));
+}
+
// Checks if relay IP address specified in the relay-info structure in
// subnet4 is being used properly.
TEST_F(Dhcpv4SrvTest, relayOverride) {
// This config has one subnet with user-context with one
// pool (also with context). Make sure the configuration could be accepted.
- EXPECT_NO_THROW(configure(CONFIGS[3]));
+ EXPECT_NO_THROW(configure(CONFIGS[4]));
// Now make sure the data was not lost.
ConstSrvConfigPtr cfg = CfgMgr::instance().getCurrentCfg();
// Add Router option.
Option4AddrLstPtr opt_routers(new Option4AddrLst(DHO_ROUTERS));
opt_routers->setAddress(IOAddress("192.0.2.2"));
- subnet_->getCfgOption()->add(opt_routers, false, DHCP4_OPTION_SPACE);
+ subnet_->getCfgOption()->add(opt_routers, false, false,
+ DHCP4_OPTION_SPACE);
CfgMgr::instance().clear();
CfgMgr::instance().setFamily(AF_INET);
option_dns_servers(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS));
option_dns_servers->addAddress(IOAddress("192.0.2.1"));
option_dns_servers->addAddress(IOAddress("192.0.2.100"));
- ASSERT_NO_THROW(subnet_->getCfgOption()->add(option_dns_servers, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet_->getCfgOption()->add(option_dns_servers, false,
+ false, DHCP4_OPTION_SPACE));
// domain-name
OptionDefinition def("domain-name", DHO_DOMAIN_NAME, DHCP4_OPTION_SPACE,
OPT_FQDN_TYPE);
OptionCustomPtr option_domain_name(new OptionCustom(def, Option::V4));
option_domain_name->writeFqdn("example.com");
- subnet_->getCfgOption()->add(option_domain_name, false, DHCP4_OPTION_SPACE);
+ subnet_->getCfgOption()->add(option_domain_name, false, false,
+ DHCP4_OPTION_SPACE);
// log-servers
Option4AddrLstPtr option_log_servers(new Option4AddrLst(DHO_LOG_SERVERS));
option_log_servers->addAddress(IOAddress("192.0.2.2"));
option_log_servers->addAddress(IOAddress("192.0.2.10"));
- ASSERT_NO_THROW(subnet_->getCfgOption()->add(option_log_servers, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet_->getCfgOption()->add(option_log_servers, false,
+ false, DHCP4_OPTION_SPACE));
// cookie-servers
Option4AddrLstPtr option_cookie_servers(new Option4AddrLst(DHO_COOKIE_SERVERS));
option_cookie_servers->addAddress(IOAddress("192.0.2.1"));
- ASSERT_NO_THROW(subnet_->getCfgOption()->add(option_cookie_servers, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet_->getCfgOption()->add(option_cookie_servers, false,
+ false, DHCP4_OPTION_SPACE));
}
void
// Add server identifier to the pool.
OptionCustomPtr server_id = makeServerIdOption(IOAddress("192.0.2.254"));
CfgOptionPtr cfg_option = pool->getCfgOption();
- cfg_option->add(server_id, false, DHCP4_OPTION_SPACE);
+ cfg_option->add(server_id, false, false, DHCP4_OPTION_SPACE);
subnet2->addPool(pool);
// Add a second pool.
// Add server identifier.
server_id = makeServerIdOption(IOAddress("192.0.3.254"));
cfg_option = subnet3->getCfgOption();
- cfg_option->add(server_id, false, DHCP4_OPTION_SPACE);
+ cfg_option->add(server_id, false, false, DHCP4_OPTION_SPACE);
subnets->add(subnet3);
subnets->add(subnet5);
CfgOptionPtr options(new CfgOption());
- OptionDescriptor desc(false);
+ OptionDescriptor desc(false, false);
desc.option_ = makeServerIdOption(IOAddress("192.0.5.254"));
options->add(desc, DHCP4_OPTION_SPACE);
CfgMgr::instance().getStagingCfg()->getClientClassDictionary()->addClass("foo", ExpressionPtr(), "", true, false, options);
subnets->add(subnet6);
options.reset(new CfgOption());
- OptionDescriptor desc_other(false);
+ OptionDescriptor desc_other(false, false);
desc_other.option_ = makeFqdnListOption();
options->add(desc_other, DHCP4_OPTION_SPACE);
CfgMgr::instance().getStagingCfg()->getClientClassDictionary()->addClass("bar", ExpressionPtr(), "", true, false, options);
// Add server identifier.
server_id = makeServerIdOption(IOAddress("192.0.4.254"));
cfg_option = network1->getCfgOption();
- cfg_option->add(server_id, false, DHCP4_OPTION_SPACE);
+ cfg_option->add(server_id, false, false, DHCP4_OPTION_SPACE);
networks->add(network1);
// Add a global server identifier.
cfg_option = cfg_mgr.getStagingCfg()->getCfgOption();
server_id = makeServerIdOption(IOAddress("10.0.0.254"));
- cfg_option->add(server_id, false, DHCP4_OPTION_SPACE);
+ cfg_option->add(server_id, false, false, DHCP4_OPTION_SPACE);
// Commit the config.
cfg_mgr.commit();
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": false,\n"
" \"data\": \"01\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": false,\n"
" \"data\": \"01\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"192.168.2.1\",\n"
" \"name\": \"foo2\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"base-option\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"192.168.2.1\",\n"
" \"name\": \"foo2\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"AB\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": false,\n"
" \"data\": \"01\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"0102030405060708090A\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"FF\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": false,\n"
" \"data\": \"01\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"01\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"true, 10.0.0.3, 127.0.0.1\",\n"
" \"name\": \"slp-directory-agent\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"false, \",\n"
" \"name\": \"slp-service-scope\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-encapsulated-options-space\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"192.168.2.1\",\n"
" \"name\": \"foo2\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-encapsulated-options-space\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"0104000004D20204C0A80201\",\n"
" \"name\": \"vendor-encapsulated-options\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-encapsulated-options-space\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"192.168.2.1\",\n"
" \"name\": \"foo2\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-encapsulated-options-space\"\n"
" }\n"
" ],\n"
" \"code\": 100,\n"
" \"csv-format\": false,\n"
" \"data\": \"1234\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-1234\"\n"
" },\n"
" {\n"
" \"code\": 100,\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-4491\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"this is a string vendor-opt\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-4491\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"192.0.3.95\",\n"
" \"name\": \"name-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"192.0.3.15\",\n"
" \"name\": \"name-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"32\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"192.0.4.11\",\n"
" \"name\": \"name-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"95\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"123\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"dhcp-message\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\",\n"
" \"user-context\": {\n"
" \"comment\": \"Set option value\"\n"
" \"csv-format\": true,\n"
" \"data\": \"example.com\",\n"
" \"name\": \"domain-name\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\",\n"
" \"user-context\": {\n"
" \"comment\": \"An option in a reservation\"\n"
" \"csv-format\": true,\n"
" \"data\": \"192.0.3.95\",\n"
" \"name\": \"name-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"192.0.3.15\",\n"
" \"name\": \"name-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"32\",\n"
" \"name\": \"default-ip-ttl\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp4\"\n"
" }\n"
" ],\n"
{ 32768, 16384 },
{},
{ DOCSIS3_V4_TFTP_SERVERS, 22 });
+// This test checks if cancelled options are actually never assigned.
+TEST_F(VendorOptsTest, vendorCancelledOptions) {
+ NakedDhcpv4Srv srv(0);
+
+ ConstElementPtr x;
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ " \"option-def\": [ {"
+ " \"space\": \"vendor-4491\","
+ " \"name\": \"foo\","
+ " \"code\": 100,"
+ " \"type\": \"string\""
+ " } ],"
+ " \"option-data\": [ {"
+ " \"name\": \"tftp-servers\","
+ " \"space\": \"vendor-4491\","
+ " \"code\": 2,"
+ " \"data\": \"192.0.2.1, 192.0.2.2\","
+ " \"csv-format\": true,"
+ " \"always-send\": true"
+ " },{"
+ " \"space\": \"vendor-4491\","
+ " \"code\": 100,"
+ " \"csv-format\": true,"
+ " \"data\": \"bar\""
+ " } ],"
+ "\"subnet4\": [ { "
+ " \"pools\": [ { \"pool\": \"192.0.2.0/25\" } ],"
+ " \"subnet\": \"192.0.2.0/24\", "
+ " \"interface\": \"eth0\", "
+ " \"option-data\": [ {"
+ " \"name\": \"tftp-servers\","
+ " \"space\": \"vendor-4491\","
+ " \"code\": 2,"
+ " \"never-send\": true"
+ " } ]"
+ " } ]"
+ "}";
+
+ ConstElementPtr json;
+ ASSERT_NO_THROW(json = parseDHCP4(config));
+
+ EXPECT_NO_THROW(x = configureDhcp4Server(srv, json));
+ ASSERT_TRUE(x);
+ comment_ = parseAnswer(rcode_, x);
+ ASSERT_EQ(0, rcode_) << comment_->str();
+
+ CfgMgr::instance().commit();
+
+ boost::shared_ptr<Pkt4> dis(new Pkt4(DHCPDISCOVER, 1234));
+ // Set the giaddr and hops to non-zero address as if it was relayed.
+ dis->setGiaddr(IOAddress("192.0.2.1"));
+ dis->setHops(1);
+
+ OptionPtr clientid = generateClientId();
+ dis->addOption(clientid);
+ // Set interface. It is required by the server to generate server id.
+ dis->setIface("eth0");
+ dis->setIndex(ETH0_INDEX);
+
+ // Let's add a vendor-option (vendor-id=4491).
+ OptionPtr vendor(new OptionVendor(Option::V4, 4491));
+ dis->addOption(vendor);
+
+ // Pass it to the server and get an advertise
+ Pkt4Ptr offer = srv.processDiscover(dis);
+
+ // check if we get response at all
+ ASSERT_TRUE(offer);
+
+ // There should be no vendor option response.
+ EXPECT_FALSE(offer->getOption(DHO_VIVSO_SUBOPTIONS));
+
+ // Let's add a vendor-option (vendor-id=4491) with a single sub-option.
+ // That suboption has code 1 and is a docsis ORO option.
+ boost::shared_ptr<OptionUint8Array> vendor_oro(new OptionUint8Array(Option::V4,
+ DOCSIS3_V4_ORO));
+ vendor_oro->addValue(DOCSIS3_V4_TFTP_SERVERS); // Request option 2.
+ vendor->addOption(vendor_oro);
+
+ // Need to process DHCPDISCOVER again after requesting new option.
+ offer = srv.processDiscover(dis);
+ ASSERT_TRUE(offer);
+
+ // Again there should be no vendor option response.
+ EXPECT_FALSE(offer->getOption(DHO_VIVSO_SUBOPTIONS));
+
+ // Request option 100.
+ vendor_oro->addValue(100);
+
+ // Try again.
+ offer = srv.processDiscover(dis);
+ ASSERT_TRUE(offer);
+
+ // Check if there is a vendor option response
+ OptionPtr tmp = offer->getOption(DHO_VIVSO_SUBOPTIONS);
+ ASSERT_TRUE(tmp);
+
+ // The response should be OptionVendor object
+ boost::shared_ptr<OptionVendor> vendor_resp =
+ boost::dynamic_pointer_cast<OptionVendor>(tmp);
+ ASSERT_TRUE(vendor_resp);
+
+ // No tftp-servers.
+ EXPECT_FALSE(vendor_resp->getOption(DOCSIS3_V4_TFTP_SERVERS));
+
+ // But an option 100.
+ EXPECT_EQ(1, vendor_resp->getOptions().size());
+ EXPECT_TRUE(vendor_resp->getOption(100));
}
// Test checks whether it is possible to use option definitions defined in
}
}
+\"never-send\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser6Context::OPTION_DATA:
+ return isc::dhcp::Dhcp6Parser::make_NEVER_SEND(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp6Parser::make_STRING("never-send", driver.loc_);
+ }
+}
+
\"pools\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::SUBNET6:
SPACE "space"
CSV_FORMAT "csv-format"
ALWAYS_SEND "always-send"
+ NEVER_SEND "never-send"
RECORD_TYPES "record-types"
ENCAPSULATE "encapsulate"
ARRAY "array"
| option_data_space
| option_data_csv_format
| option_data_always_send
+ | option_data_never_send
| user_context
| comment
| unknown_map_entry
ctx.stack_.back()->set("always-send", persist);
};
+option_data_never_send: NEVER_SEND COLON BOOLEAN {
+ ctx.unique("never-send", ctx.loc2pos(@1));
+ ElementPtr persist(new BoolElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("never-send", persist);
+};
+
// ---- pools ------------------------------------
// This defines the "pools": [ ... ] entry that may appear in subnet6.
}
}
- // Iterate on the configured option list to add persistent options
+ set<uint16_t> cancelled_opts;
+
+ // Iterate on the configured option list to add persistent and
+ // cancelled options.
for (auto const& copts : co_list) {
const OptionContainerPtr& opts = copts->getAll(DHCP6_OPTION_SPACE);
if (!opts) {
continue;
}
- // Get persistent options
- const OptionContainerPersistIndex& idx = opts->get<2>();
- const OptionContainerPersistRange& range = idx.equal_range(true);
- for (OptionContainerPersistIndex::const_iterator desc = range.first;
- desc != range.second; ++desc) {
- // Add the persistent option code to requested options
+ // Get persistent options.
+ const OptionContainerPersistIndex& pidx = opts->get<2>();
+ const OptionContainerPersistRange& prange = pidx.equal_range(true);
+ for (OptionContainerPersistIndex::const_iterator desc = prange.first;
+ desc != prange.second; ++desc) {
+ // Add the persistent option code to requested options.
if (desc->option_) {
uint16_t code = desc->option_->getType();
static_cast<void>(requested_opts.insert(code));
}
}
+ // Get cancelled options.
+ const OptionContainerCancelIndex& cidx = opts->get<5>();
+ const OptionContainerCancelRange& crange = cidx.equal_range(true);
+ for (OptionContainerCancelIndex::const_iterator desc = crange.first;
+ desc != crange.second; ++desc) {
+ // Add the cancelled option code to the cancelled options.
+ if (desc->option_) {
+ uint16_t code = desc->option_->getType();
+ static_cast<void>(cancelled_opts.insert(code));
+ }
+ }
}
// For each requested option code get the first instance of the option
// to be returned to the client.
for (uint16_t opt : requested_opts) {
+ // Skip if cancelled.
+ if (cancelled_opts.count(opt) > 0) {
+ continue;
+ }
// Add nothing when it is already there.
// Skip special cases: D6O_VENDOR_OPTS
if (opt == D6O_VENDOR_OPTS) {
// Special cases for vendor class and options which are identified
// by the code/type and the vendor/enterprise id vs. the code/type only.
- if (requested_opts.count(D6O_VENDOR_CLASS) > 0) {
+ if ((requested_opts.count(D6O_VENDOR_CLASS) > 0) &&
+ (cancelled_opts.count(D6O_VENDOR_CLASS) == 0)) {
+ // Keep vendor ids which are already in the response to insert
+ // D6O_VENDOR_CLASS options at most once per vendor.
set<uint32_t> vendor_ids;
// Get what already exists in the response.
for (auto opt : answer->getOptions(D6O_VENDOR_CLASS)) {
}
}
- if (requested_opts.count(D6O_VENDOR_OPTS) > 0) {
+ if ((requested_opts.count(D6O_VENDOR_OPTS) > 0) &&
+ (cancelled_opts.count(D6O_VENDOR_OPTS) == 0)) {
+ // Keep vendor ids which are already in the response to insert
+ // D6O_VENDOR_OPTS options at most once per vendor.
set<uint32_t> vendor_ids;
// Get what already exists in the response.
for (auto opt : answer->getOptions(D6O_VENDOR_OPTS)) {
}
}
- // Iterate on the configured option list to add persistent options
+ map<uint32_t, set<uint16_t> > cancelled_opts;
+
+ // Iterate on the configured option list to add persistent and
+ // cancelled options.
for (uint32_t vendor_id : vendor_ids) {
for (auto const& copts : co_list) {
const OptionContainerPtr& opts = copts->getAll(vendor_id);
if (!opts) {
continue;
}
- // Get persistent options
- const OptionContainerPersistIndex& idx = opts->get<2>();
- const OptionContainerPersistRange& range = idx.equal_range(true);
- for (OptionContainerPersistIndex::const_iterator desc = range.first;
- desc != range.second; ++desc) {
+ // Get persistent options.
+ const OptionContainerPersistIndex& pidx = opts->get<2>();
+ const OptionContainerPersistRange& prange = pidx.equal_range(true);
+ for (OptionContainerPersistIndex::const_iterator desc = prange.first;
+ desc != prange.second; ++desc) {
if (!desc->option_) {
continue;
}
uint16_t code = desc->option_->getType();
static_cast<void>(requested_opts[vendor_id].insert(code));
}
+ // Get cancelled options.
+ const OptionContainerCancelIndex& cidx = opts->get<5>();
+ const OptionContainerCancelRange& crange = cidx.equal_range(true);
+ for (OptionContainerCancelIndex::const_iterator desc = crange.first;
+ desc != crange.second; ++desc) {
+ if (!desc->option_) {
+ continue;
+ }
+ // Add the cancelled option code to cancelled options
+ uint16_t code = desc->option_->getType();
+ static_cast<void>(cancelled_opts[vendor_id].insert(code));
+ }
}
// If there is nothing to add don't do anything with this vendor.
bool added = false;
for (uint16_t opt : requested_opts[vendor_id]) {
+ if (cancelled_opts[vendor_id].count(opt) > 0) {
+ continue;
+ }
if (!vendor_rsp->getOption(opt)) {
for (auto const& copts : co_list) {
OptionDescriptor desc = copts->get(vendor_id, opt);
"\"option-data\": ["
" { \"name\": \"ipv6-forwarding\", "
" \"data\": \"false\", "
- " \"always-send\": true } ], "
+ " \"always-send\": true, "
+ " \"never-send\": false } ], "
"\"subnet6\": [ "
"{ \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ], "
" \"subnet\": \"2001:db8:1::/48\", "
" \"option-data\": ["
" { \"name\": \"ipv6-forwarding\", "
" \"data\": \"false\", "
- " \"always-send\": false } ] } ] }";
+ " \"always-send\": false, "
+ " \"never-send\": false } ] } ] }";
ASSERT_NO_THROW(configure(config));
// Create a packet with enough to select the subnet and go through
EXPECT_EQ(0, opt->getUint8());
}
+// Checks class never-send options have the priority over everything else.
+TEST_F(ClassifyTest, classNeverSend) {
+ IfaceMgrTestConfig test_config(true);
+
+ NakedDhcpv6Srv srv(0);
+
+ // Subnet sets an ipv6-forwarding option in the response.
+ // The router class matches incoming packets with foo in a host-name
+ // option (code 1234) and sets an ipv6-forwarding option in the response.
+ // Note the cancellation flag follows a "OR" semantic so to set
+ // it to false (or to leave the default) has no effect.
+ std::string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ] }, "
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ "\"valid-lifetime\": 4000, "
+ "\"option-def\": [ "
+ "{ \"name\": \"host-name\","
+ " \"code\": 1234,"
+ " \"type\": \"string\" },"
+ "{ \"name\": \"ipv6-forwarding\","
+ " \"code\": 2345,"
+ " \"type\": \"boolean\" }],"
+ "\"option-data\": ["
+ " { \"name\": \"ipv6-forwarding\", "
+ " \"data\": \"false\", "
+ " \"always-send\": true, "
+ " \"never-send\": false } ], "
+ "\"subnet6\": [ "
+ "{ \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ], "
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"interface\": \"eth1\", "
+ " \"option-data\": ["
+ " { \"name\": \"ipv6-forwarding\", "
+ " \"always-send\": false, "
+ " \"never-send\": true } ] } ] }";
+ ASSERT_NO_THROW(configure(config));
+
+ // Create a packet with enough to select the subnet and go through
+ // the SOLICIT processing
+ Pkt6Ptr query = createSolicit();
+
+ // Do not add an ORO.
+ OptionPtr oro = query->getOption(D6O_ORO);
+ EXPECT_FALSE(oro);
+
+ // Create and add a host-name option to the query
+ OptionStringPtr hostname(new OptionString(Option::V6, 1234, "foo"));
+ ASSERT_TRUE(hostname);
+ query->addOption(hostname);
+
+ // Process the query
+ AllocEngine::ClientContext6 ctx;
+ bool drop = !srv.earlyGHRLookup(query, ctx);
+ ASSERT_FALSE(drop);
+ srv.initContext(query, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv.processSolicit(ctx);
+
+ // Processing should not add an ip-forwarding option
+ EXPECT_FALSE(response->getOption(2345));
+}
+
// Checks if the client-class field is indeed used for subnet selection.
// Note that packet classification is already checked in ClassifyTest
// .*Classification above.
// Add solmax-rt to the first backend.
opt.reset(new OptionDescriptor(
createOption<OptionString>(Option::V6, D6O_BOOTFILE_URL,
- true, false, "updated-boot-file")));
+ true, false, false,
+ "updated-boot-file")));
opt->space_name_ = DHCP6_OPTION_SPACE;
db1_->createUpdateOption6(ServerSelector::ALL(), opt);
// Add solmax-rt to the second backend.
opt.reset(new OptionDescriptor(
createOption<OptionUint32>(Option::V6, D6O_SOL_MAX_RT,
- false, true, 700)));
+ false, false, true, 700)));
opt->space_name_ = DHCP6_OPTION_SPACE;
db2_->createUpdateOption6(ServerSelector::ALL(), opt);
ADD_FAILURE() << "A subnet for the specified address "
<< subnet_address
<< " does not exist in Config Manager";
- return (OptionDescriptor(false));
+ return (OptionDescriptor(false, false));
}
OptionContainerPtr options =
subnet->getCfgOption()->getAll(DHCP6_OPTION_SPACE);
<< subnet_address.toText() << "'. Expected "
" at most one option";
} else if (std::distance(range.first, range.second) == 0) {
- return (OptionDescriptor(OptionPtr(), false));
+ return (OptionDescriptor(OptionPtr(), false, false));
}
return (*range.first);
" \"renew-timer\": 1000, "
" \"valid-lifetime\": 4000, "
" \"subnet6\": [ {"
+ " \"interface\": \"eth0\", "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ], "
" \"subnet\": \"2001:db8:1::/48\""
" } ], "
"}",
// Configuration 3:
+ // - a single subnet with one option cancelled with never-send.
+ // - two global options (one enforced with always-send)
+ "{"
+ " \"interfaces-config\": { \"interfaces\": [ \"*\" ] }, "
+ " \"preferred-lifetime\": 3000, "
+ " \"rebind-timer\": 2000, "
+ " \"renew-timer\": 1000, "
+ " \"valid-lifetime\": 4000, "
+ " \"subnet6\": [ {"
+ " \"interface\": \"eth0\", "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ], "
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"option-data\": ["
+ " {"
+ " \"name\": \"subscriber-id\", "
+ " \"never-send\": true"
+ " } ]"
+ " } ], "
+ " \"option-data\": ["
+ " {"
+ " \"name\": \"dns-servers\", "
+ " \"data\": \"2001:db8:1234:FFFF::1\""
+ " }, "
+ " {"
+ " \"name\": \"subscriber-id\", "
+ " \"data\": \"1234\", "
+ " \"always-send\": true"
+ " }"
+ " ]"
+ "}",
+
+ // Configuration 4:
// - one subnet with one address pool and one prefix pool
// - user-contexts defined in subnet and each pool
"{"
EXPECT_TRUE(adv->getRelayOption(D6O_RELAY_SOURCE_PORT, 0));
}
-// Checks effect of persistency (aka always-true) flag on the ORO
+// Checks effect of persistency (aka always-send) flag on the ORO
TEST_F(Dhcpv6SrvTest, prlPersistency) {
IfaceMgrTestConfig test_config(true);
ASSERT_FALSE(response->getOption(D6O_SNTP_SERVERS));
}
+// Checks effect of cancellation (aka never-send) flag.
+TEST_F(Dhcpv6SrvTest, neverSend) {
+ IfaceMgrTestConfig test_config(true);
+
+ ASSERT_NO_THROW(configure(CONFIGS[3]));
+
+ // Create a packet with enough to select the subnet and go through
+ // the SOLICIT processing
+ Pkt6Ptr sol(new Pkt6(DHCPV6_SOLICIT, 1234));
+ sol->setRemoteAddr(IOAddress("fe80::abcd"));
+ sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
+ sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
+ OptionPtr clientid = generateClientId();
+ sol->addOption(clientid);
+
+ // Create and add an ORO for another option
+ OptionUint16ArrayPtr oro(new OptionUint16Array(Option::V6, D6O_ORO));
+ ASSERT_TRUE(oro);
+ oro->addValue(D6O_SNTP_SERVERS);
+ sol->addOption(oro);
+
+ // Let the server process it and generate a response.
+ AllocEngine::ClientContext6 ctx;
+ bool drop = !srv_.earlyGHRLookup(sol, ctx);
+ ASSERT_FALSE(drop);
+ srv_.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr response = srv_.processSolicit(ctx);
+
+ // The server should not add a subscriber-id option
+ ASSERT_FALSE(response->getOption(D6O_SUBSCRIBER_ID));
+ // And no dns-servers
+ ASSERT_FALSE(response->getOption(D6O_NAME_SERVERS));
+ // Nor a sntp-servers
+ ASSERT_FALSE(response->getOption(D6O_SNTP_SERVERS));
+
+ // Reset ORO adding dns-servers
+ sol->delOption(D6O_ORO);
+ oro->addValue(D6O_NAME_SERVERS);
+ sol->addOption(oro);
+
+ // Let the server process it again. This time the name-servers
+ // option should be present.
+ AllocEngine::ClientContext6 ctx2;
+ drop = !srv_.earlyGHRLookup(sol, ctx2);
+ ASSERT_FALSE(drop);
+ srv_.initContext(sol, ctx2, drop);
+ ASSERT_FALSE(drop);
+ response = srv_.processSolicit(ctx2);
+
+ // Processing should not add a subscriber-id option
+ ASSERT_FALSE(response->getOption(D6O_SUBSCRIBER_ID));
+ // But now a dns-servers
+ ASSERT_TRUE(response->getOption(D6O_NAME_SERVERS));
+ // And still no sntp-servers
+ ASSERT_FALSE(response->getOption(D6O_SNTP_SERVERS));
+
+ // Reset ORO adding subscriber-id
+ sol->delOption(D6O_ORO);
+ OptionUint16ArrayPtr oro2(new OptionUint16Array(Option::V6, D6O_ORO));
+ ASSERT_TRUE(oro2);
+ oro2->addValue(D6O_SUBSCRIBER_ID);
+ sol->addOption(oro2);
+
+ // Let the server process it again.
+ AllocEngine::ClientContext6 ctx3;
+ drop = !srv_.earlyGHRLookup(sol, ctx3);
+ ASSERT_FALSE(drop);
+ srv_.initContext(sol, ctx3, drop);
+ ASSERT_FALSE(drop);
+ response = srv_.processSolicit(ctx3);
+
+ // The subscriber-id option should still not be present.
+ ASSERT_FALSE(response->getOption(D6O_SUBSCRIBER_ID));
+ // And no dns-servers
+ ASSERT_FALSE(response->getOption(D6O_NAME_SERVERS));
+ // Nor a sntp-servers
+ ASSERT_FALSE(response->getOption(D6O_SNTP_SERVERS));
+}
+
// Checks if server is able to handle a relayed traffic from DOCSIS3.0 modems
// @todo Uncomment this test as part of #3180 work.
// Kea code currently fails to handle docsis traffic.
// This config has one subnet with user-context with one
// pool (also with context). Make sure the configuration could be accepted.
- EXPECT_NO_THROW(configure(CONFIGS[3]));
+ EXPECT_NO_THROW(configure(CONFIGS[4]));
// Now make sure the data was not lost.
ConstSrvConfigPtr cfg = CfgMgr::instance().getCurrentCfg();
-// Copyright (C) 2017-2023 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp6/tests/get_config_unittest.h>
#include <testutils/gtest_utils.h>
-#include <testutils/test_to_element.h>
#include <boost/algorithm/string.hpp>
#include <gtest/gtest.h>
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"01\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"01\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"192.168.2.1\",\n"
" \"name\": \"foo2\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"base-option\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"1234\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"192.168.2.1\",\n"
" \"name\": \"foo2\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"0102030405060708090A\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"FFFEFDFCFB\",\n"
" \"name\": \"user-class\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"112233445566\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"AABBCCDDEE\",\n"
" \"name\": \"user-class\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"0102030405060708090A\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"FFFEFDFCFB\",\n"
" \"name\": \"user-class\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"code\": 100,\n"
" \"csv-format\": false,\n"
" \"data\": \"1234\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-1234\"\n"
" },\n"
" {\n"
" \"code\": 100,\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-4491\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"this is a string vendor-opt\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"vendor-4491\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"2001:db8:2::abbc\",\n"
" \"name\": \"dns-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"25\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"2001:db8:2::1111\",\n"
" \"name\": \"dns-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"2001:db8:3::3333\",\n"
" \"name\": \"dns-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"33\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"foo\",\n"
+" \"never-send\": false,\n"
" \"space\": \"isc\"\n"
" }\n"
" ],\n"
" \"csv-format\": false,\n"
" \"data\": \"ABCDEF0105\",\n"
" \"name\": \"subscriber-id\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\",\n"
" \"user-context\": {\n"
" \"comment\": \"Set option value\"\n"
" \"csv-format\": true,\n"
" \"data\": \"example.com\",\n"
" \"name\": \"domain-search\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\",\n"
" \"user-context\": {\n"
" \"comment\": \"An option in a reservation\"\n"
" \"csv-format\": true,\n"
" \"data\": \"2001:db8:2::abbc\",\n"
" \"name\": \"dns-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"25\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
" \"csv-format\": true,\n"
" \"data\": \"2001:db8:2::1111\",\n"
" \"name\": \"dns-servers\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" },\n"
" {\n"
" \"csv-format\": true,\n"
" \"data\": \"11\",\n"
" \"name\": \"preference\",\n"
+" \"never-send\": false,\n"
" \"space\": \"dhcp6\"\n"
" }\n"
" ],\n"
{ DOCSIS3_V6_CONFIG_FILE, 12 });
}
+// This test checks if cancellation (aka never-send) flag unconditionally
+// makes the server to never add the specified option.
+TEST_F(VendorOptsTest, vendorNeverSend) {
+ string config = "{ \"interfaces-config\": {"
+ " \"interfaces\": [ \"*\" ]"
+ "},"
+ "\"preferred-lifetime\": 3000,"
+ "\"rebind-timer\": 2000, "
+ "\"renew-timer\": 1000, "
+ " \"option-def\": [ {"
+ " \"name\": \"config-file\","
+ " \"code\": 33,"
+ " \"type\": \"string\","
+ " \"space\": \"vendor-4491\""
+ " },"
+ " {"
+ " \"name\": \"vendor-name\","
+ " \"code\": 10,"
+ " \"type\": \"string\","
+ " \"space\": \"vendor-4491\""
+ " } ],"
+ " \"option-data\": [ {"
+ " \"name\": \"config-file\","
+ " \"space\": \"vendor-4491\","
+ " \"data\": \"normal_erouter_v6.cm\","
+ " \"always-send\": true"
+ " },"
+ " {"
+ " \"name\": \"vendor-name\","
+ " \"space\": \"vendor-4491\","
+ " \"data\": \"ISC\""
+ " }],"
+ "\"subnet6\": [ { "
+ " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+ " \"subnet\": \"2001:db8:1::/48\", "
+ " \"renew-timer\": 1000, "
+ " \"rebind-timer\": 1000, "
+ " \"preferred-lifetime\": 3000,"
+ " \"valid-lifetime\": 4000,"
+ " \"interface-id\": \"\","
+ " \"interface\": \"eth0\","
+ " \"option-data\": [ {"
+ " \"name\": \"config-file\","
+ " \"space\": \"vendor-4491\","
+ " \"never-send\": true"
+ " } ]"
+ " } ],"
+ "\"valid-lifetime\": 4000 }";
+
+ ASSERT_NO_THROW(configure(config));
+
+ Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
+ sol->setRemoteAddr(IOAddress("fe80::abcd"));
+ sol->setIface("eth0");
+ sol->setIndex(ETH0_INDEX);
+ sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000));
+ OptionPtr clientid = generateClientId();
+ sol->addOption(clientid);
+
+ // Let's add a vendor-option (vendor-id=4491).
+ OptionPtr vendor(new OptionVendor(Option::V6, 4491));
+ sol->addOption(vendor);
+
+ // Pass it to the server and get an advertise
+ AllocEngine::ClientContext6 ctx;
+ bool drop = !srv_.earlyGHRLookup(sol, ctx);
+ ASSERT_FALSE(drop);
+ srv_.initContext(sol, ctx, drop);
+ ASSERT_FALSE(drop);
+ Pkt6Ptr adv = srv_.processSolicit(ctx);
+
+ // check if we get response at all
+ ASSERT_TRUE(adv);
+
+ // There is no vendor option response.
+ EXPECT_FALSE(adv->getOption(D6O_VENDOR_OPTS));
+
+ // Add again an ORO but requesting both 10 and 33.
+ sol->delOption(D6O_VENDOR_OPTS);
+ boost::shared_ptr<OptionUint16Array> vendor_oro2(new OptionUint16Array(Option::V6,
+ DOCSIS3_V6_ORO));
+ vendor_oro2->addValue(DOCSIS3_V6_VENDOR_NAME); // Request option 10
+ vendor_oro2->addValue(DOCSIS3_V6_CONFIG_FILE); // Request option 33
+ OptionPtr vendor3(new OptionVendor(Option::V6, 4491));
+ vendor3->addOption(vendor_oro2);
+ sol->addOption(vendor3);
+
+ // Need to process SOLICIT again after requesting new option.
+ AllocEngine::ClientContext6 ctx3;
+ drop = !srv_.earlyGHRLookup(sol, ctx3);
+ ASSERT_FALSE(drop);
+ srv_.initContext(sol, ctx3, drop);
+ ASSERT_FALSE(drop);
+ adv = srv_.processSolicit(ctx3);
+ ASSERT_TRUE(adv);
+
+ // Check if there is vendor option response
+ OptionPtr tmp = adv->getOption(D6O_VENDOR_OPTS);
+ ASSERT_TRUE(tmp);
+
+ // The response should be OptionVendor object
+ boost::shared_ptr<OptionVendor> vendor_resp =
+ boost::dynamic_pointer_cast<OptionVendor>(tmp);
+ ASSERT_TRUE(vendor_resp);
+
+ // Still no config-file (33) option.
+ EXPECT_FALSE(vendor_resp->getOption(33));
+
+ // But the vendor option response is not empty.
+ const OptionCollection& opts = vendor_resp->getOptions();
+ ASSERT_EQ(1, opts.size());
+ EXPECT_TRUE(vendor_resp->getOption(10));
+}
+
// Test checks whether it is possible to use option definitions defined in
// src/lib/dhcp/docsis3_option_defs.h.
TEST_F(VendorOptsTest, vendorOptionsDocsisDefinitions) {
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pool option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pool option: space
MySqlBinding::createInteger<uint8_t>(), // pool option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // pool option: cancelled
MySqlBinding::createInteger<uint32_t>(), // pool option: dhcp4_subnet_id
MySqlBinding::createInteger<uint8_t>(), // pool option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool option: user_context
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
MySqlBinding::createInteger<uint8_t>(), // option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // option: cancelled
MySqlBinding::createInteger<uint32_t>(), // option: dhcp4_subnet_id
MySqlBinding::createInteger<uint8_t>(), // option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
auto rebind_timer = createTriplet(out_bindings[11]);
// valid_lifetime at 19.
- // min_valid_lifetime at 53.
- // max_valid_lifetime at 54.
+ // min_valid_lifetime at 55.
+ // max_valid_lifetime at 56.
auto valid_lifetime = createTriplet(out_bindings[19],
- out_bindings[53],
- out_bindings[54]);
+ out_bindings[55],
+ out_bindings[56]);
// Create subnet with basic settings.
last_subnet = Subnet4::create(prefix_pair.first, prefix_pair.second,
// valid_lifetime at 19.
- // pool and option from 20 to 48.
+ // pool and option from 20 to 50.
- // calculate_tee_times at 49.
- if (!out_bindings[49]->amNull()) {
- last_subnet->setCalculateTeeTimes(out_bindings[49]->getBool());
+ // calculate_tee_times at 51.
+ if (!out_bindings[51]->amNull()) {
+ last_subnet->setCalculateTeeTimes(out_bindings[51]->getBool());
}
- // t1_percent at 50.
- if (!out_bindings[50]->amNull()) {
- last_subnet->setT1Percent(out_bindings[50]->getFloat());
+ // t1_percent at 52.
+ if (!out_bindings[52]->amNull()) {
+ last_subnet->setT1Percent(out_bindings[52]->getFloat());
}
- // t2_percent at 51.
- if (!out_bindings[51]->amNull()) {
- last_subnet->setT2Percent(out_bindings[51]->getFloat());
+ // t2_percent at 53.
+ if (!out_bindings[53]->amNull()) {
+ last_subnet->setT2Percent(out_bindings[53]->getFloat());
}
- // authoritative at 52.
- if (!out_bindings[52]->amNull()) {
- last_subnet->setAuthoritative(out_bindings[52]->getBool());
+ // authoritative at 54.
+ if (!out_bindings[54]->amNull()) {
+ last_subnet->setAuthoritative(out_bindings[54]->getBool());
}
- // min_valid_lifetime at 53.
- // max_valid_lifetime at 54.
+ // min_valid_lifetime at 55.
+ // max_valid_lifetime at 56.
// pool client_class, require_client_classes and user_context
- // from 55 to 57.
-
- // ddns_send_updates at 58.
- if (!out_bindings[58]->amNull()) {
- last_subnet->setDdnsSendUpdates(out_bindings[58]->getBool());
- }
+ // from 57 to 59.
- // ddns_override_no_update at 59.
- if (!out_bindings[59]->amNull()) {
- last_subnet->setDdnsOverrideNoUpdate(out_bindings[59]->getBool());
- }
-
- // ddns_override_client_update at 60.
+ // ddns_send_updates at 60.
if (!out_bindings[60]->amNull()) {
- last_subnet->setDdnsOverrideClientUpdate(out_bindings[60]->getBool());
+ last_subnet->setDdnsSendUpdates(out_bindings[60]->getBool());
}
- // ddns_replace_client_name at 61.
+ // ddns_override_no_update at 61.
if (!out_bindings[61]->amNull()) {
- last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
- (out_bindings[61]->getInteger<uint8_t>()));
+ last_subnet->setDdnsOverrideNoUpdate(out_bindings[61]->getBool());
}
- // ddns_generated_prefix at 62.
+ // ddns_override_client_update at 62.
if (!out_bindings[62]->amNull()) {
- last_subnet->setDdnsGeneratedPrefix(out_bindings[62]->getString());
+ last_subnet->setDdnsOverrideClientUpdate(out_bindings[62]->getBool());
}
- // ddns_qualifying_suffix at 63.
+ // ddns_replace_client_name at 63.
if (!out_bindings[63]->amNull()) {
- last_subnet->setDdnsQualifyingSuffix(out_bindings[63]->getString());
+ last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
+ (out_bindings[63]->getInteger<uint8_t>()));
}
- // reservations_in_subnet at 64.
+ // ddns_generated_prefix at 64.
if (!out_bindings[64]->amNull()) {
- last_subnet->setReservationsInSubnet(out_bindings[64]->getBool());
+ last_subnet->setDdnsGeneratedPrefix(out_bindings[64]->getString());
}
- // reservations_out_of_pool at 65.
+ // ddns_qualifying_suffix at 65.
if (!out_bindings[65]->amNull()) {
- last_subnet->setReservationsOutOfPool(out_bindings[65]->getBool());
+ last_subnet->setDdnsQualifyingSuffix(out_bindings[65]->getString());
}
- // cache_threshold at 66.
+ // reservations_in_subnet at 66.
if (!out_bindings[66]->amNull()) {
- last_subnet->setCacheThreshold(out_bindings[66]->getFloat());
+ last_subnet->setReservationsInSubnet(out_bindings[66]->getBool());
}
- // cache_max_age at 67.
+ // reservations_out_of_pool at 67.
if (!out_bindings[67]->amNull()) {
- last_subnet->setCacheMaxAge(out_bindings[67]->getInteger<uint32_t>());
+ last_subnet->setReservationsOutOfPool(out_bindings[67]->getBool());
+ }
+
+ // cache_threshold at 68.
+ if (!out_bindings[68]->amNull()) {
+ last_subnet->setCacheThreshold(out_bindings[68]->getFloat());
}
- // server_tag at 68.
+ // cache_max_age at 69.
+ if (!out_bindings[69]->amNull()) {
+ last_subnet->setCacheMaxAge(out_bindings[69]->getInteger<uint32_t>());
+ }
+
+ // server_tag at 70.
// Subnet ready. Add it to the list.
auto ret = subnets.insert(last_subnet);
}
}
- // Check for new server tags at 68.
- if (!out_bindings[68]->amNull() &&
- (last_tag != out_bindings[68]->getString())) {
- last_tag = out_bindings[68]->getString();
+ // Check for new server tags at 70.
+ if (!out_bindings[70]->amNull() &&
+ (last_tag != out_bindings[70]->getString())) {
+ last_tag = out_bindings[70]->getString();
if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
last_subnet->setServerTag(last_tag);
}
last_pool = Pool4::create(IOAddress(out_bindings[21]->getInteger<uint32_t>()),
IOAddress(out_bindings[22]->getInteger<uint32_t>()));
- // pool client_class at 55.
- if (!out_bindings[55]->amNull()) {
- last_pool->allowClientClass(out_bindings[55]->getString());
+ // pool client_class at 57.
+ if (!out_bindings[57]->amNull()) {
+ last_pool->allowClientClass(out_bindings[57]->getString());
}
- // pool require_client_classes at 56.
- ElementPtr require_element = out_bindings[56]->getJSON();
+ // pool require_client_classes at 58.
+ ElementPtr require_element = out_bindings[58]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
isc_throw(BadValue, "invalid pool require_client_classes value "
- << out_bindings[56]->getString());
+ << out_bindings[58]->getString());
}
for (auto i = 0; i < require_element->size(); ++i) {
auto require_item = require_element->get(i);
}
}
- // pool user_context at 57.
- ElementPtr user_context = out_bindings[57]->getJSON();
+ // pool user_context at 59.
+ ElementPtr user_context = out_bindings[59]->getJSON();
if (user_context) {
last_pool->setContext(user_context);
}
last_subnet->addPool(last_pool);
}
- // Parse pool-specific option from 25 to 36.
+ // Parse pool-specific option from 25 to 37.
if (last_pool && !out_bindings[25]->amNull() &&
(last_pool_option_id < out_bindings[25]->getInteger<uint64_t>())) {
last_pool_option_id = out_bindings[25]->getInteger<uint64_t>();
}
}
- // Parse subnet-specific option from 37 to 48.
- if (!out_bindings[37]->amNull() &&
- (last_option_id < out_bindings[37]->getInteger<uint64_t>())) {
- last_option_id = out_bindings[37]->getInteger<uint64_t>();
+ // Parse subnet-specific option from 38 to 50.
+ if (!out_bindings[38]->amNull() &&
+ (last_option_id < out_bindings[38]->getInteger<uint64_t>())) {
+ last_option_id = out_bindings[38]->getInteger<uint64_t>();
- OptionDescriptorPtr desc = processOptionRow(Option::V4, out_bindings.begin() + 37);
+ OptionDescriptorPtr desc = processOptionRow(Option::V4, out_bindings.begin() + 38);
if (desc) {
last_subnet->getCfgOption()->add(*desc, desc->space_name_);
}
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pool option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pool option: space
MySqlBinding::createInteger<uint8_t>(), // pool option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // pool option: cancelled
MySqlBinding::createInteger<uint32_t>(), // pool option: dhcp4_subnet_id
MySqlBinding::createInteger<uint8_t>(), // pool option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool option: user_context
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
MySqlBinding::createInteger<uint8_t>(), // option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // option: cancelled
MySqlBinding::createInteger<uint32_t>(), // option: dhcp4_subnet_id
MySqlBinding::createInteger<uint8_t>(), // option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
}
// valid_lifetime at 12.
- // min_valid_lifetime at 32.
- // max_valid_lifetime at 33.
+ // min_valid_lifetime at 33.
+ // max_valid_lifetime at 34.
if (!out_bindings[12]->amNull()) {
last_network->setValid(createTriplet(out_bindings[12],
- out_bindings[32],
- out_bindings[33]));
+ out_bindings[33],
+ out_bindings[34]));
}
- // option from 13 to 24.
+ // option from 13 to 25.
- // calculate_tee_times at 25.
- if (!out_bindings[25]->amNull()) {
- last_network->setCalculateTeeTimes(out_bindings[25]->getBool());
- }
-
- // t1_percent at 26.
+ // calculate_tee_times at 26.
if (!out_bindings[26]->amNull()) {
- last_network->setT1Percent(out_bindings[26]->getFloat());
+ last_network->setCalculateTeeTimes(out_bindings[26]->getBool());
}
- // t2_percent at 27.
+ // t1_percent at 27.
if (!out_bindings[27]->amNull()) {
- last_network->setT2Percent(out_bindings[27]->getFloat());
+ last_network->setT1Percent(out_bindings[27]->getFloat());
}
- // authoritative at 28.
+ // t2_percent at 28.
if (!out_bindings[28]->amNull()) {
- last_network->setAuthoritative(out_bindings[28]->getBool());
+ last_network->setT2Percent(out_bindings[28]->getFloat());
}
- // boot_file_name at 29.
+ // authoritative at 29.
if (!out_bindings[29]->amNull()) {
- last_network->setFilename(out_bindings[29]->getString());
+ last_network->setAuthoritative(out_bindings[29]->getBool());
}
- // next_server at 30.
+ // boot_file_name at 30.
if (!out_bindings[30]->amNull()) {
- last_network->setSiaddr(IOAddress(out_bindings[30]->getInteger<uint32_t>()));
+ last_network->setFilename(out_bindings[30]->getString());
}
- // server_hostname at 31.
+ // next_server at 31.
if (!out_bindings[31]->amNull()) {
- last_network->setSname(out_bindings[31]->getString());
+ last_network->setSiaddr(IOAddress(out_bindings[31]->getInteger<uint32_t>()));
}
- // min_valid_lifetime at 32.
- // max_valid_lifetime at 33.
-
- // ddns_send_updates at 34.
- if (!out_bindings[34]->amNull()) {
- last_network->setDdnsSendUpdates(out_bindings[34]->getBool());
+ // server_hostname at 32.
+ if (!out_bindings[32]->amNull()) {
+ last_network->setSname(out_bindings[32]->getString());
}
- // ddns_override_no_update at 35.
+ // min_valid_lifetime at 33.
+ // max_valid_lifetime at 34.
+
+ // ddns_send_updates at 35.
if (!out_bindings[35]->amNull()) {
- last_network->setDdnsOverrideNoUpdate(out_bindings[35]->getBool());
+ last_network->setDdnsSendUpdates(out_bindings[35]->getBool());
}
- // ddns_override_client_update at 36.
+ // ddns_override_no_update at 36.
if (!out_bindings[36]->amNull()) {
- last_network->setDdnsOverrideClientUpdate(out_bindings[36]->getBool());
+ last_network->setDdnsOverrideNoUpdate(out_bindings[36]->getBool());
}
- // ddns_replace_client_name at 37.
+ // ddns_override_client_update at 37.
if (!out_bindings[37]->amNull()) {
- last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
- (out_bindings[37]->getInteger<uint8_t>()));
+ last_network->setDdnsOverrideClientUpdate(out_bindings[37]->getBool());
}
- // ddns_generated_prefix at 38.
+ // ddns_replace_client_name at 38.
if (!out_bindings[38]->amNull()) {
- last_network->setDdnsGeneratedPrefix(out_bindings[38]->getString());
+ last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
+ (out_bindings[38]->getInteger<uint8_t>()));
}
- // ddns_qualifying_suffix at 39.
+ // ddns_generated_prefix at 39.
if (!out_bindings[39]->amNull()) {
- last_network->setDdnsQualifyingSuffix(out_bindings[39]->getString());
+ last_network->setDdnsGeneratedPrefix(out_bindings[39]->getString());
}
- // reservations_in_subnet at 40.
+ // ddns_qualifying_suffix at 40.
if (!out_bindings[40]->amNull()) {
- last_network->setReservationsInSubnet(out_bindings[40]->getBool());
+ last_network->setDdnsQualifyingSuffix(out_bindings[40]->getString());
}
// reservations_in_subnet at 41.
if (!out_bindings[41]->amNull()) {
- last_network->setReservationsOutOfPool(out_bindings[41]->getBool());
+ last_network->setReservationsInSubnet(out_bindings[41]->getBool());
}
- // cache_threshold at 42.
+ // reservations_in_subnet at 42.
if (!out_bindings[42]->amNull()) {
- last_network->setCacheThreshold(out_bindings[42]->getFloat());
+ last_network->setReservationsOutOfPool(out_bindings[42]->getBool());
}
- // cache_max_age at 43.
+ // cache_threshold at 43.
if (!out_bindings[43]->amNull()) {
- last_network->setCacheMaxAge(out_bindings[43]->getInteger<uint32_t>());
+ last_network->setCacheThreshold(out_bindings[43]->getFloat());
}
- // server_tag at 44.
+ // cache_max_age at 44.
+ if (!out_bindings[44]->amNull()) {
+ last_network->setCacheMaxAge(out_bindings[44]->getInteger<uint32_t>());
+ }
+
+ // server_tag at 45.
// Add the shared network.
auto ret = shared_networks.push_back(last_network);
}
// Check for new server tags.
- if (!out_bindings[44]->amNull() &&
- (last_tag != out_bindings[44]->getString())) {
- last_tag = out_bindings[44]->getString();
+ if (!out_bindings[45]->amNull() &&
+ (last_tag != out_bindings[45]->getString())) {
+ last_tag = out_bindings[45]->getString();
if (!last_tag.empty() && !last_network->hasServerTag(ServerTag(last_tag))) {
last_network->setServerTag(last_tag);
}
}
- // Parse option from 13 to 24.
+ // Parse option from 13 to 25.
if (!out_bindings[13]->amNull() &&
(last_option_id < out_bindings[13]->getInteger<uint64_t>())) {
last_option_id = out_bindings[13]->getInteger<uint64_t>();
auto option_id = mysql_insert_id(conn_.mysql_);
// Timestamp is expected to be in this input binding.
- auto timestamp_binding = in_bindings[11];
+ auto timestamp_binding = in_bindings[12];
// Associate the option with the servers.
attachElementToServers(MySqlConfigBackendDHCPv4Impl::INSERT_OPTION4_SERVER,
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(0),
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet_id)),
MySqlBinding::createInteger<uint8_t>(1),
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(5),
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(4),
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createString(client_class->getName()),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(2),
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
MySqlBinding::createInteger<uint8_t>(), // option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // option: cancelled
MySqlBinding::createInteger<uint32_t>(), // option: dhcp4_subnet_id
MySqlBinding::createInteger<uint8_t>(), // option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
}
// server tag
- if (!out_bindings[36]->amNull() &&
- (last_tag != out_bindings[36]->getString())) {
- last_tag = out_bindings[36]->getString();
+ if (!out_bindings[37]->amNull() &&
+ (last_tag != out_bindings[37]->getString())) {
+ last_tag = out_bindings[37]->getString();
if (!last_tag.empty() && !last_client_class->hasServerTag(ServerTag(last_tag))) {
last_client_class->setServerTag(last_tag);
}
}
}
- // Parse client class specific option from 24 to 35.
+ // Parse client class specific option from 24 to 36.
if (!out_bindings[24]->amNull() &&
(last_option_id < out_bindings[24]->getInteger<uint64_t>())) {
last_option_id = out_bindings[24]->getInteger<uint64_t>();
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pool option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pool option: space
MySqlBinding::createInteger<uint8_t>(), // pool option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // pool option: cancelled
MySqlBinding::createInteger<uint32_t>(), // pool option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // pool option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool option: user_context
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pd pool option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pd pool option: space
MySqlBinding::createInteger<uint8_t>(), // pd pool option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // pd pool option: cancelled
MySqlBinding::createInteger<uint32_t>(), // pd pool option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // pd pool option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool option: user_context
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
MySqlBinding::createInteger<uint8_t>(), // option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // option: cancelled
MySqlBinding::createInteger<uint32_t>(), // option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
auto prefix_pair = Subnet6::parsePrefix(subnet_prefix);
// preferred_lifetime (5)
- // min_preferred_lifetime (69)
- // max_preferred_lifetime (70)
+ // min_preferred_lifetime (72)
+ // max_preferred_lifetime (73)
auto preferred_lifetime = createTriplet(out_bindings[5],
- out_bindings[69],
- out_bindings[70]);
+ out_bindings[72],
+ out_bindings[73]);
// renew_timer (9)
auto renew_timer = createTriplet(out_bindings[9]);
auto rebind_timer = createTriplet(out_bindings[7]);
// valid_lifetime (14)
- // min_valid_lifetime (71)
- // max_valid_lifetime (72)
+ // min_valid_lifetime (74)
+ // max_valid_lifetime (75)
auto valid_lifetime = createTriplet(out_bindings[14],
- out_bindings[71],
- out_bindings[72]);
+ out_bindings[74],
+ out_bindings[75]);
// Create subnet with basic settings.
last_subnet = Subnet6::create(prefix_pair.first, prefix_pair.second,
// 15 to 19 are pool
// 20 to 25 are pd pool
- // 26 to 38 are pool option
- // 39 to 51 are pd pool option
- // 52 to 64 are option
+ // 26 to 39 are pool option
+ // 40 to 53 are pd pool option
+ // 54 to 67 are option
- // calculate_tee_times (65)
- if (!out_bindings[65]->amNull()) {
- last_subnet->setCalculateTeeTimes(out_bindings[65]->getBool());
+ // calculate_tee_times (68)
+ if (!out_bindings[68]->amNull()) {
+ last_subnet->setCalculateTeeTimes(out_bindings[68]->getBool());
}
- // t1_percent (66)
- if (!out_bindings[66]->amNull()) {
- last_subnet->setT1Percent(out_bindings[66]->getFloat());
+ // t1_percent (69)
+ if (!out_bindings[69]->amNull()) {
+ last_subnet->setT1Percent(out_bindings[69]->getFloat());
}
- // t2_percent (67)
- if (!out_bindings[67]->amNull()) {
- last_subnet->setT2Percent(out_bindings[67]->getFloat());
+ // t2_percent (70)
+ if (!out_bindings[70]->amNull()) {
+ last_subnet->setT2Percent(out_bindings[70]->getFloat());
}
- // interface_id (68)
- if (!out_bindings[68]->amNull()) {
- auto iface_id_data = out_bindings[68]->getBlob();
+ // interface_id (71)
+ if (!out_bindings[71]->amNull()) {
+ auto iface_id_data = out_bindings[71]->getBlob();
if (!iface_id_data.empty()) {
OptionPtr opt_iface_id(new Option(Option::V6, D6O_INTERFACE_ID,
iface_id_data));
}
}
- // 69 and 70 are {min,max}_preferred_lifetime
-
- // 71 and 72 are {min,max}_valid_lifetime
-
- // 73 is pool client_class
- // 74 is pool require_client_classes
- // 75 is pool user_context
- // 76 is pd pool excluded_prefix
- // 77 is pd pool excluded_prefix_length
- // 78 is pd pool client_class
- // 79 is pd pool require_client_classes
- // 80 is pd pool user_context
+ // 72 and 73 are {min,max}_preferred_lifetime
- // ddns_send_updates (81)
- if (!out_bindings[81]->amNull()) {
- last_subnet->setDdnsSendUpdates(out_bindings[81]->getBool());
- }
+ // 74 and 75 are {min,max}_valid_lifetime
- // ddns_override_no_update (82)
- if (!out_bindings[82]->amNull()) {
- last_subnet->setDdnsOverrideNoUpdate(out_bindings[82]->getBool());
- }
+ // 76 is pool client_class
+ // 77 is pool require_client_classes
+ // 78 is pool user_context
+ // 79 is pd pool excluded_prefix
+ // 80 is pd pool excluded_prefix_length
+ // 81 is pd pool client_class
+ // 82 is pd pool require_client_classes
+ // 83 is pd pool user_context
- // ddns_override_client_update (83)
- if (!out_bindings[83]->amNull()) {
- last_subnet->setDdnsOverrideClientUpdate(out_bindings[83]->getBool());
- }
-
- // ddns_replace_client_name (84)
+ // ddns_send_updates (84)
if (!out_bindings[84]->amNull()) {
- last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
- (out_bindings[84]->getInteger<uint8_t>()));
+ last_subnet->setDdnsSendUpdates(out_bindings[84]->getBool());
}
- // ddns_generated_prefix (85)
+ // ddns_override_no_update (85)
if (!out_bindings[85]->amNull()) {
- last_subnet->setDdnsGeneratedPrefix(out_bindings[85]->getString());
+ last_subnet->setDdnsOverrideNoUpdate(out_bindings[85]->getBool());
}
- // ddns_qualifying_suffix (86)
+ // ddns_override_client_update (86)
if (!out_bindings[86]->amNull()) {
- last_subnet->setDdnsQualifyingSuffix(out_bindings[86]->getString());
+ last_subnet->setDdnsOverrideClientUpdate(out_bindings[86]->getBool());
}
- // reservations_in_subnet (87)
+ // ddns_replace_client_name (87)
if (!out_bindings[87]->amNull()) {
- last_subnet->setReservationsInSubnet(out_bindings[87]->getBool());
+ last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
+ (out_bindings[87]->getInteger<uint8_t>()));
}
- // reservations_out_of_pool (88)
+ // ddns_generated_prefix (88)
if (!out_bindings[88]->amNull()) {
- last_subnet->setReservationsOutOfPool(out_bindings[88]->getBool());
+ last_subnet->setDdnsGeneratedPrefix(out_bindings[88]->getString());
}
- // cache_threshold (89)
+ // ddns_qualifying_suffix (89)
if (!out_bindings[89]->amNull()) {
- last_subnet->setCacheThreshold(out_bindings[89]->getFloat());
+ last_subnet->setDdnsQualifyingSuffix(out_bindings[89]->getString());
}
- // cache_max_age (90)
+ // reservations_in_subnet (90)
if (!out_bindings[90]->amNull()) {
- last_subnet->setCacheMaxAge(out_bindings[90]->getInteger<uint32_t>());
+ last_subnet->setReservationsInSubnet(out_bindings[90]->getBool());
+ }
+
+ // reservations_out_of_pool (91)
+ if (!out_bindings[91]->amNull()) {
+ last_subnet->setReservationsOutOfPool(out_bindings[91]->getBool());
+ }
+
+ // cache_threshold (92)
+ if (!out_bindings[92]->amNull()) {
+ last_subnet->setCacheThreshold(out_bindings[92]->getFloat());
}
- // server_tag (91 / last)
+ // cache_max_age (93)
+ if (!out_bindings[93]->amNull()) {
+ last_subnet->setCacheMaxAge(out_bindings[93]->getInteger<uint32_t>());
+ }
+
+ // server_tag (94 / last)
// Subnet ready. Add it to the list.
auto ret = subnets.insert(last_subnet);
}
// Check for new server tags.
- if (!out_bindings[91]->amNull() &&
- (last_tag != out_bindings[91]->getString())) {
- last_tag = out_bindings[91]->getString();
+ if (!out_bindings[94]->amNull() &&
+ (last_tag != out_bindings[94]->getString())) {
+ last_tag = out_bindings[94]->getString();
if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
last_subnet->setServerTag(last_tag);
}
}
- // Pool is between 15 and 19 with extra between 73 and 75
+ // Pool is between 15 and 19 with extra between 76 and 78
// If the row contains information about the pool and it
// appears to be new pool entry (checked by comparing pool
// 18 is pool subnet_id (ignored)
// 19 is pool modification_ts (ignored)
- // pool client_class (73)
- if (!out_bindings[73]->amNull()) {
- last_pool->allowClientClass(out_bindings[73]->getString());
+ // pool client_class (76)
+ if (!out_bindings[76]->amNull()) {
+ last_pool->allowClientClass(out_bindings[76]->getString());
}
- // pool require_client_classes (74)
- ElementPtr require_element = out_bindings[74]->getJSON();
+ // pool require_client_classes (77)
+ ElementPtr require_element = out_bindings[77]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
isc_throw(BadValue, "invalid pool require_client_classes value "
- << out_bindings[74]->getString());
+ << out_bindings[77]->getString());
}
for (auto i = 0; i < require_element->size(); ++i) {
auto require_item = require_element->get(i);
}
}
- // pool user_context (75)
- ElementPtr user_context = out_bindings[75]->getJSON();
+ // pool user_context (78)
+ ElementPtr user_context = out_bindings[78]->getJSON();
if (user_context) {
last_pool->setContext(user_context);
}
last_subnet->addPool(last_pool);
}
- // Pd Pool is between 20 and 25 with extra between 76 and 80
+ // Pd Pool is between 20 and 25 with extra between 79 and 83
// If the row contains information about the pd pool and
// it appears to be new pd pool entry (checked by
// 24 is pd pool subnet_id (ignored)
// 25 is pd pool modification_ts (ignored)
- // excluded_prefix (76) and excluded_prefix_length (77)
+ // excluded_prefix (79) and excluded_prefix_length (80)
IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS();
- if (!out_bindings[76]->amNull()) {
- excluded_prefix = IOAddress(out_bindings[76]->getString());
+ if (!out_bindings[79]->amNull()) {
+ excluded_prefix = IOAddress(out_bindings[79]->getString());
}
last_pd_pool = Pool6::create(IOAddress(out_bindings[21]->getString()),
out_bindings[22]->getInteger<uint8_t>(),
out_bindings[23]->getInteger<uint8_t>(),
excluded_prefix,
- out_bindings[77]->getInteger<uint8_t>());
+ out_bindings[80]->getInteger<uint8_t>());
- // pd pool client_class (78)
- if (!out_bindings[78]->amNull()) {
- last_pd_pool->allowClientClass(out_bindings[78]->getString());
+ // pd pool client_class (81)
+ if (!out_bindings[81]->amNull()) {
+ last_pd_pool->allowClientClass(out_bindings[81]->getString());
}
- // pd pool require_client_classes (79)
- ElementPtr require_element = out_bindings[79]->getJSON();
+ // pd pool require_client_classes (82)
+ ElementPtr require_element = out_bindings[82]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
isc_throw(BadValue, "invalid pd pool require_client_classes value "
- << out_bindings[79]->getString());
+ << out_bindings[82]->getString());
}
for (auto i = 0; i < require_element->size(); ++i) {
auto require_item = require_element->get(i);
}
}
- // pd pool user_context (80)
- ElementPtr user_context = out_bindings[80]->getJSON();
+ // pd pool user_context (83)
+ ElementPtr user_context = out_bindings[83]->getJSON();
if (user_context) {
last_pd_pool->setContext(user_context);
}
last_subnet->addPool(last_pd_pool);
}
- // Parse pool specific option between 26 and 38
+ // Parse pool specific option between 26 and 39
if (last_pool && !out_bindings[26]->amNull() &&
(last_pool_option_id < out_bindings[26]->getInteger<uint64_t>())) {
last_pool_option_id = out_bindings[26]->getInteger<uint64_t>();
}
}
- // Parse pd pool specific option between 39 and 51
- if (last_pd_pool && !out_bindings[39]->amNull() &&
- (last_pd_pool_option_id < out_bindings[39]->getInteger<uint64_t>())) {
- last_pd_pool_option_id = out_bindings[39]->getInteger<uint64_t>();
+ // Parse pd pool specific option between 40 and 53
+ if (last_pd_pool && !out_bindings[40]->amNull() &&
+ (last_pd_pool_option_id < out_bindings[40]->getInteger<uint64_t>())) {
+ last_pd_pool_option_id = out_bindings[40]->getInteger<uint64_t>();
- OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 39);
+ OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 40);
if (desc) {
last_pd_pool->getCfgOption()->add(*desc, desc->space_name_);
}
}
- // Parse subnet specific option between 52 and 64
- if (!out_bindings[52]->amNull() &&
- (last_option_id < out_bindings[52]->getInteger<uint64_t>())) {
- last_option_id = out_bindings[52]->getInteger<uint64_t>();
+ // Parse subnet specific option between 54 and 67
+ if (!out_bindings[54]->amNull() &&
+ (last_option_id < out_bindings[54]->getInteger<uint64_t>())) {
+ last_option_id = out_bindings[54]->getInteger<uint64_t>();
- OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 52);
+ OptionDescriptorPtr desc = processOptionRow(Option::V6, out_bindings.begin() + 54);
if (desc) {
last_subnet->getCfgOption()->add(*desc, desc->space_name_);
}
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pool option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pool option: space
MySqlBinding::createInteger<uint8_t>(), // pool option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // pool option: cancelled
MySqlBinding::createInteger<uint32_t>(), // pool option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // pool option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pool option: user_context
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // pd pool option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // pd pool option: space
MySqlBinding::createInteger<uint8_t>(), // pd pool option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // pd pool option: cancelled
MySqlBinding::createInteger<uint32_t>(), // pd pool option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // pd pool option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // pd pool option: user_context
pd_pool_ids.push_back(last_pd_pool_id);
}
- // Parse pd pool specific option between 11 and 24
+ // Parse pd pool specific option between 11 and 25
if (last_pd_pool && !out_bindings[11]->amNull() &&
(last_pd_pool_option_id < out_bindings[11]->getInteger<uint64_t>())) {
last_pd_pool_option_id = out_bindings[11]->getInteger<uint64_t>();
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
MySqlBinding::createInteger<uint8_t>(), // option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // option: cancelled
MySqlBinding::createInteger<uint32_t>(), // option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
last_network->setModificationTime(out_bindings[4]->getTimestamp());
// preferred_lifetime at 5.
- // min_preferred_lifetime at 31.
- // max_preferred_lifetime at 32.
+ // min_preferred_lifetime at 32.
+ // max_preferred_lifetime at 33.
if (!out_bindings[5]->amNull()) {
last_network->setPreferred(createTriplet(out_bindings[5],
- out_bindings[31],
- out_bindings[32]));
+ out_bindings[32],
+ out_bindings[33]));
}
// rapid_commit at 6.
}
// valid_lifetime at 13.
- // min_valid_lifetime at 33.
- // max_valid_lifetime at 34.
+ // min_valid_lifetime at 34.
+ // max_valid_lifetime at 35.
if (!out_bindings[13]->amNull()) {
last_network->setValid(createTriplet(out_bindings[13],
- out_bindings[33],
- out_bindings[34]));
+ out_bindings[34],
+ out_bindings[35]));
}
- // 14 to 26 are option.
-
- // calculate_tee_times at 27.
- if (!out_bindings[27]->amNull()) {
- last_network->setCalculateTeeTimes(out_bindings[27]->getBool());
- }
+ // 14 to 27 are option.
- // t1_percent at 28.
+ // calculate_tee_times at 28.
if (!out_bindings[28]->amNull()) {
- last_network->setT1Percent(out_bindings[28]->getFloat());
+ last_network->setCalculateTeeTimes(out_bindings[28]->getBool());
}
- // t2_percent at 29.
+ // t1_percent at 29.
if (!out_bindings[29]->amNull()) {
- last_network->setT2Percent(out_bindings[29]->getFloat());
+ last_network->setT1Percent(out_bindings[29]->getFloat());
}
- // interface_id at 30.
+ // t2_percent at 30.
if (!out_bindings[30]->amNull()) {
- auto iface_id_data = out_bindings[30]->getBlob();
+ last_network->setT2Percent(out_bindings[30]->getFloat());
+ }
+
+ // interface_id at 31.
+ if (!out_bindings[31]->amNull()) {
+ auto iface_id_data = out_bindings[31]->getBlob();
if (!iface_id_data.empty()) {
OptionPtr opt_iface_id(new Option(Option::V6, D6O_INTERFACE_ID,
iface_id_data));
}
}
- // min_preferred_lifetime at 31.
- // max_preferred_lifetime at 32.
- // min_valid_lifetime at 33.
- // max_valid_lifetime at 34.
-
- // ddns_send_updates at 35.
- if (!out_bindings[35]->amNull()) {
- last_network->setDdnsSendUpdates(out_bindings[35]->getBool());
- }
+ // min_preferred_lifetime at 32.
+ // max_preferred_lifetime at 33.
+ // min_valid_lifetime at 34.
+ // max_valid_lifetime at 35.
- // ddns_override_no_update at 36.
+ // ddns_send_updates at 36.
if (!out_bindings[36]->amNull()) {
- last_network->setDdnsOverrideNoUpdate(out_bindings[36]->getBool());
+ last_network->setDdnsSendUpdates(out_bindings[36]->getBool());
}
- // ddns_override_client_update at 37.
+ // ddns_override_no_update at 37.
if (!out_bindings[37]->amNull()) {
- last_network->setDdnsOverrideClientUpdate(out_bindings[37]->getBool());
+ last_network->setDdnsOverrideNoUpdate(out_bindings[37]->getBool());
}
- // ddns_replace_client_name at 38.
+ // ddns_override_client_update at 38.
if (!out_bindings[38]->amNull()) {
- last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
- (out_bindings[38]->getInteger<uint8_t>()));
+ last_network->setDdnsOverrideClientUpdate(out_bindings[38]->getBool());
}
- // ddns_generated_prefix at 39.
+ // ddns_replace_client_name at 39.
if (!out_bindings[39]->amNull()) {
- last_network->setDdnsGeneratedPrefix(out_bindings[39]->getString());
+ last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
+ (out_bindings[39]->getInteger<uint8_t>()));
}
- // ddns_qualifying_suffix at 40.
+ // ddns_generated_prefix at 40.
if (!out_bindings[40]->amNull()) {
- last_network->setDdnsQualifyingSuffix(out_bindings[40]->getString());
+ last_network->setDdnsGeneratedPrefix(out_bindings[40]->getString());
}
- // reservations_in_subnet at 41.
+ // ddns_qualifying_suffix at 41.
if (!out_bindings[41]->amNull()) {
- last_network->setReservationsInSubnet(out_bindings[41]->getBool());
+ last_network->setDdnsQualifyingSuffix(out_bindings[41]->getString());
}
// reservations_in_subnet at 42.
if (!out_bindings[42]->amNull()) {
- last_network->setReservationsOutOfPool(out_bindings[42]->getBool());
+ last_network->setReservationsInSubnet(out_bindings[42]->getBool());
}
- // cache_threshold at 43.
+ // reservations_in_subnet at 43.
if (!out_bindings[43]->amNull()) {
- last_network->setCacheThreshold(out_bindings[43]->getFloat());
+ last_network->setReservationsOutOfPool(out_bindings[43]->getBool());
}
- // cache_max_age at 44.
+ // cache_threshold at 44.
if (!out_bindings[44]->amNull()) {
- last_network->setCacheMaxAge(out_bindings[44]->getInteger<uint32_t>());
+ last_network->setCacheThreshold(out_bindings[44]->getFloat());
+ }
+
+ // cache_max_age at 45.
+ if (!out_bindings[45]->amNull()) {
+ last_network->setCacheMaxAge(out_bindings[45]->getInteger<uint32_t>());
}
- // server_tag at 45.
+ // server_tag at 46.
// Add the shared network.
auto ret = shared_networks.push_back(last_network);
}
// Check for new server tags.
- if (!out_bindings[45]->amNull() &&
- (last_tag != out_bindings[45]->getString())) {
- last_tag = out_bindings[45]->getString();
+ if (!out_bindings[46]->amNull() &&
+ (last_tag != out_bindings[46]->getString())) {
+ last_tag = out_bindings[46]->getString();
if (!last_tag.empty() && !last_network->hasServerTag(ServerTag(last_tag))) {
last_network->setServerTag(last_tag);
}
}
- // Parse option from 14 to 26.
+ // Parse option from 14 to 27.
if (!out_bindings[14]->amNull() &&
(last_option_id < out_bindings[14]->getInteger<uint64_t>())) {
last_option_id = out_bindings[14]->getInteger<uint64_t>();
auto option_id = mysql_insert_id(conn_.mysql_);
// Timestamp is expected to be in this input binding.
- auto timestamp_binding = in_bindings[11];
+ auto timestamp_binding = in_bindings[12];
// Associate the option with the servers.
attachElementToServers(MySqlConfigBackendDHCPv6Impl::INSERT_OPTION6_SERVER,
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(0),
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint32_t>(static_cast<uint32_t>(subnet_id)),
MySqlBinding::createInteger<uint8_t>(1),
in_bindings.push_back(MySqlBinding::condCreateString(option->space_name_));
// persistent
in_bindings.push_back(MySqlBinding::createBool(option->persistent_));
+ // cancelled
+ in_bindings.push_back(MySqlBinding::createBool(option->cancelled_));
// dhcp_client_class
in_bindings.push_back(MySqlBinding::createNull());
// dhcp[46]_subnet_id
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createNull(),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(4),
MySqlBinding::condCreateString(option->formatted_value_),
MySqlBinding::condCreateString(option->space_name_),
MySqlBinding::createBool(option->persistent_),
+ MySqlBinding::createBool(option->cancelled_),
MySqlBinding::createString(client_class->getName()),
MySqlBinding::createNull(),
MySqlBinding::createInteger<uint8_t>(2),
MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH), // option: formatted_value
MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH), // option: space
MySqlBinding::createInteger<uint8_t>(), // option: persistent
+ MySqlBinding::createInteger<uint8_t>(), // option: cancelled
MySqlBinding::createInteger<uint32_t>(), // option: dhcp6_subnet_id
MySqlBinding::createInteger<uint8_t>(), // option: scope_id
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // option: user_context
}
// preferred lifetime: default, min, max
- last_client_class->setPreferred(createTriplet(out_bindings[34],
- out_bindings[35],
- out_bindings[36]));
+ last_client_class->setPreferred(createTriplet(out_bindings[35],
+ out_bindings[36],
+ out_bindings[37]));
class_list.push_back(last_client_class);
}
// server tag
- if (!out_bindings[33]->amNull() &&
- (last_tag != out_bindings[33]->getString())) {
- last_tag = out_bindings[33]->getString();
+ if (!out_bindings[34]->amNull() &&
+ (last_tag != out_bindings[34]->getString())) {
+ last_tag = out_bindings[34]->getString();
if (!last_tag.empty() && !last_client_class->hasServerTag(ServerTag(last_tag))) {
last_client_class->setServerTag(last_tag);
}
}
}
- // Parse client class specific option from 21 to 32.
+ // Parse client class specific option from 21 to 33.
if (!out_bindings[21]->amNull() &&
(last_option_id < out_bindings[21]->getInteger<uint64_t>())) {
last_option_id = out_bindings[21]->getInteger<uint64_t>();
}
// value
out_bindings.push_back(MySqlBinding::createBlob(OPTION_VALUE_BUF_LENGTH));
- // forma\tted_value
+ // formatted_value
out_bindings.push_back(MySqlBinding::createString(FORMATTED_OPTION_VALUE_BUF_LENGTH));
// space
out_bindings.push_back(MySqlBinding::createString(OPTION_SPACE_BUF_LENGTH));
// persistent
out_bindings.push_back(MySqlBinding::createInteger<uint8_t>());
+ // cancelled
+ out_bindings.push_back(MySqlBinding::createInteger<uint8_t>());
// dhcp[46]_subnet_id
out_bindings.push_back(MySqlBinding::createInteger<uint32_t>());
// scope_id
OptionDescriptorPtr desc = processOptionRow(universe, out_bindings.begin());
if (desc) {
// server_tag for the global option
- ServerTag last_option_server_tag(out_bindings[12]->getString());
+ ServerTag last_option_server_tag(out_bindings[13]->getString());
desc->setServerTag(last_option_server_tag.get());
// If we're fetching options for a given server (explicit server
// Check if the option is persistent.
bool persistent = static_cast<bool>((*(first_binding + 5))->getIntegerOrDefault<uint8_t>(0));
+ // Check if the option is cancelled.
+ bool cancelled = static_cast<bool>((*(first_binding + 6))->getIntegerOrDefault<uint8_t>(0));
+
// Create option descriptor which encapsulates our option and adds
// additional information, i.e. whether the option is persistent,
// its option space and timestamp.
- OptionDescriptorPtr desc = OptionDescriptor::create(option, persistent, formatted_value);
+ OptionDescriptorPtr desc = OptionDescriptor::create(option,
+ persistent,
+ cancelled,
+ formatted_value);
desc->space_name_ = space;
- desc->setModificationTime((*(first_binding + 11))->getTimestamp());
+ desc->setModificationTime((*(first_binding + 12))->getTimestamp());
// Set database id for the option.
if (!(*first_binding)->amNull()) {
/// - formatted_value,
/// - space,
/// - persistent,
+ /// - cancelled,
/// - dhcp4_subnet_id/dhcp6_subnet_id,
/// - scope_id,
/// - user_context,
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp4_subnet_id," \
" x.scope_id," \
" x.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp4_subnet_id," \
" o.scope_id," \
" o.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" y.formatted_value," \
" y.space," \
" y.persistent," \
+ " y.cancelled," \
" y.dhcp6_subnet_id," \
" y.scope_id," \
" y.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp6_subnet_id," \
" o.scope_id," \
" o.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp4_subnet_id," \
" x.scope_id," \
" x.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp4_subnet_id," \
" o.scope_id," \
" o.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp6_subnet_id," \
" o.scope_id," \
" o.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o." #table_prefix "_subnet_id," \
" o.scope_id," \
" o.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp4_subnet_id," \
" x.scope_id," \
" x.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" formatted_value," \
" space," \
" persistent," \
+ " cancelled," \
" dhcp_client_class," \
" " #table_prefix "_subnet_id," \
" scope_id," \
" pool_id," \
" modification_ts" \
pd_pool_id \
- ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" last ")"
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" last ")"
#define MYSQL_INSERT_OPTION4() \
MYSQL_INSERT_OPTION_COMMON(dhcp4, "", "")
" o.formatted_value = ?," \
" o.space = ?," \
" o.persistent = ?," \
+ " o.cancelled = ?," \
" o.dhcp_client_class = ?," \
" o." #table_prefix "_subnet_id = ?," \
" o.scope_id = ?," \
auto rebind_timer = worker.getTriplet(11);
// valid_lifetime at 19.
- // min_valid_lifetime at 53.
- // max_valid_lifetime at 54.
- auto valid_lifetime = worker.getTriplet(19, 53, 54);
+ // min_valid_lifetime at 55.
+ // max_valid_lifetime at 56.
+ auto valid_lifetime = worker.getTriplet(19, 55, 56);
// Create subnet with basic settings.
last_subnet = Subnet4::create(prefix_pair.first, prefix_pair.second,
// valid_lifetime at 19 (fetched before subnet create).
- // pool and option from 20 to 48.
+ // pool and options from 20 to 50.
- // calculate_tee_times at 49.
- if (!worker.isColumnNull(49)) {
- last_subnet->setCalculateTeeTimes(worker.getBool(49));
+ // calculate_tee_times at 51.
+ if (!worker.isColumnNull(51)) {
+ last_subnet->setCalculateTeeTimes(worker.getBool(51));
}
- // t1_percent at 50.
- if (!worker.isColumnNull(50)) {
- last_subnet->setT1Percent(worker.getDouble(50));
+ // t1_percent at 52.
+ if (!worker.isColumnNull(52)) {
+ last_subnet->setT1Percent(worker.getDouble(52));
}
- // t2_percent at 51.
- if (!worker.isColumnNull(51)) {
- last_subnet->setT2Percent(worker.getDouble(51));
+ // t2_percent at 53.
+ if (!worker.isColumnNull(53)) {
+ last_subnet->setT2Percent(worker.getDouble(53));
}
- // authoritative at 52.
- if (!worker.isColumnNull(52)) {
- last_subnet->setAuthoritative(worker.getBool(52));
+ // authoritative at 54.
+ if (!worker.isColumnNull(54)) {
+ last_subnet->setAuthoritative(worker.getBool(54));
}
- // min_valid_lifetime at 53 (fetched as part of triplet).
- // max_valid_lifetime at 54 (fetched as part of triplet).
+ // min_valid_lifetime at 55 (fetched as part of triplet).
+ // max_valid_lifetime at 56 (fetched as part of triplet).
// pool client_class, require_client_classes and user_context
- // from 55 to 57.
-
- // ddns_send_updates at 58.
- if (!worker.isColumnNull(58)) {
- last_subnet->setDdnsSendUpdates(worker.getBool(58));
- }
+ // from 57 to 59.
- // ddns_override_no_update at 59.
- if (!worker.isColumnNull(59)) {
- last_subnet->setDdnsOverrideNoUpdate(worker.getBool(59));
- }
-
- // ddns_override_client_update at 60.
+ // ddns_send_updates at 60.
if (!worker.isColumnNull(60)) {
- last_subnet->setDdnsOverrideClientUpdate(worker.getBool(60));
+ last_subnet->setDdnsSendUpdates(worker.getBool(60));
}
- // ddns_replace_client_name at 61.
+ // ddns_override_no_update at 61.
if (!worker.isColumnNull(61)) {
- last_subnet->setDdnsReplaceClientNameMode(
- static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(61)));
+ last_subnet->setDdnsOverrideNoUpdate(worker.getBool(61));
}
- // ddns_generated_prefix at 62.
+ // ddns_override_client_update at 62.
if (!worker.isColumnNull(62)) {
- last_subnet->setDdnsGeneratedPrefix(worker.getString(62));
+ last_subnet->setDdnsOverrideClientUpdate(worker.getBool(62));
}
- // ddns_qualifying_suffix at 63.
+ // ddns_replace_client_name at 63.
if (!worker.isColumnNull(63)) {
- last_subnet->setDdnsQualifyingSuffix(worker.getString(63));
+ last_subnet->setDdnsReplaceClientNameMode(
+ static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(63)));
}
- // reservations_in_subnet at 64.
+ // ddns_generated_prefix at 64.
if (!worker.isColumnNull(64)) {
- last_subnet->setReservationsInSubnet(worker.getBool(64));
+ last_subnet->setDdnsGeneratedPrefix(worker.getString(64));
}
- // reservations_out_of_pool at 65.
+ // ddns_qualifying_suffix at 65.
if (!worker.isColumnNull(65)) {
- last_subnet->setReservationsOutOfPool(worker.getBool(65));
+ last_subnet->setDdnsQualifyingSuffix(worker.getString(65));
}
- // cache_threshold at 66.
+ // reservations_in_subnet at 66.
if (!worker.isColumnNull(66)) {
- last_subnet->setCacheThreshold(worker.getDouble(66));
+ last_subnet->setReservationsInSubnet(worker.getBool(66));
}
- // cache_max_age at 67.
+ // reservations_out_of_pool at 67.
if (!worker.isColumnNull(67)) {
- last_subnet->setCacheMaxAge(worker.getInt(67));
+ last_subnet->setReservationsOutOfPool(worker.getBool(67));
+ }
+
+ // cache_threshold at 68.
+ if (!worker.isColumnNull(68)) {
+ last_subnet->setCacheThreshold(worker.getDouble(68));
+ }
+
+ // cache_max_age at 69.
+ if (!worker.isColumnNull(69)) {
+ last_subnet->setCacheMaxAge(worker.getInt(69));
}
- // server_tag at 68.
+ // server_tag at 70.
// Subnet ready. Add it to the list.
auto ret = subnets.insert(last_subnet);
}
}
- // Check for new server tags at 68.
- if (!worker.isColumnNull(68)) {
- std::string new_tag = worker.getString(68);
+ // Check for new server tags at 70.
+ if (!worker.isColumnNull(70)) {
+ std::string new_tag = worker.getString(70);
if (last_tag != new_tag) {
if (!new_tag.empty() && !last_subnet->hasServerTag(ServerTag(new_tag))) {
last_subnet->setServerTag(new_tag);
last_pool = Pool4::create(IOAddress(worker.getInet4(21)),
IOAddress(worker.getInet4(22)));
- // pool client_class at 55.
- if (!worker.isColumnNull(55)) {
- last_pool->allowClientClass(worker.getString(55));
+ // pool client_class at 57.
+ if (!worker.isColumnNull(57)) {
+ last_pool->allowClientClass(worker.getString(57));
}
- // pool require_client_classes at 56.
- setRequiredClasses(worker, 56, [&last_pool](const std::string& class_name) {
+ // pool require_client_classes at 58.
+ setRequiredClasses(worker, 58, [&last_pool](const std::string& class_name) {
last_pool->requireClientClass(class_name);
});
- // pool user_context at 57.
- if (!worker.isColumnNull(57)) {
- ElementPtr user_context = worker.getJSON(57);
+ // pool user_context at 59.
+ if (!worker.isColumnNull(59)) {
+ ElementPtr user_context = worker.getJSON(59);
if (user_context) {
last_pool->setContext(user_context);
}
last_subnet->addPool(last_pool);
}
- // Parse pool-specific option from 25 to 36.
+ // Parse pool-specific option from 25 to 37.
if (last_pool && !worker.isColumnNull(25) &&
(last_pool_option_id < worker.getBigInt(25))) {
last_pool_option_id = worker.getBigInt(25);
}
}
- // Parse subnet-specific option from 37 to 48.
- if (!worker.isColumnNull(37) &&
- (last_option_id < worker.getBigInt(37))) {
- last_option_id = worker.getBigInt(37);
+ // Parse subnet-specific option from 38 to 50.
+ if (!worker.isColumnNull(38) &&
+ (last_option_id < worker.getBigInt(38))) {
+ last_option_id = worker.getBigInt(38);
- OptionDescriptorPtr desc = processOptionRow(Option::V4, worker, 37);
+ OptionDescriptorPtr desc = processOptionRow(Option::V4, worker, 38);
if (desc) {
last_subnet->getCfgOption()->add(*desc, desc->space_name_);
}
}
// valid_lifetime at 12.
- // min_valid_lifetime at 32.
- // max_valid_lifetime at 33.
+ // min_valid_lifetime at 33.
+ // max_valid_lifetime at 34.
if (!worker.isColumnNull(12)) {
- last_network->setValid(worker.getTriplet(12, 32, 33));
+ last_network->setValid(worker.getTriplet(12, 33, 34));
}
- // option from 13 to 24.
-
- // calculate_tee_times at 25.
- if (!worker.isColumnNull(25)) {
- last_network->setCalculateTeeTimes(worker.getBool(25));
- }
+ // option from 13 to 25.
- // t1_percent at 26.
+ // calculate_tee_times at 26.
if (!worker.isColumnNull(26)) {
- last_network->setT1Percent(worker.getDouble(26));
+ last_network->setCalculateTeeTimes(worker.getBool(26));
}
- // t2_percent at 27.
+ // t1_percent at 27.
if (!worker.isColumnNull(27)) {
- last_network->setT2Percent(worker.getDouble(27));
+ last_network->setT1Percent(worker.getDouble(27));
}
- // authoritative at 28.
+ // t2_percent at 28.
if (!worker.isColumnNull(28)) {
- last_network->setAuthoritative(worker.getBool(28));
+ last_network->setT2Percent(worker.getDouble(28));
}
- // boot_file_name at 29.
+ // authoritative at 29.
if (!worker.isColumnNull(29)) {
- last_network->setFilename(worker.getString(29));
+ last_network->setAuthoritative(worker.getBool(29));
}
- // next_server at 30.
+ // boot_file_name at 30.
if (!worker.isColumnNull(30)) {
- last_network->setSiaddr(worker.getInet4(30));
+ last_network->setFilename(worker.getString(30));
}
- // server_hostname at 31.
+ // next_server at 31.
if (!worker.isColumnNull(31)) {
- last_network->setSname(worker.getString(31));
+ last_network->setSiaddr(worker.getInet4(31));
}
- // min_valid_lifetime at 32.
- // max_valid_lifetime at 33.
-
- // ddns_send_updates at 34.
- if (!worker.isColumnNull(34)) {
- last_network->setDdnsSendUpdates(worker.getBool(34));
+ // server_hostname at 32.
+ if (!worker.isColumnNull(32)) {
+ last_network->setSname(worker.getString(32));
}
- // ddns_override_no_update at 35.
+ // min_valid_lifetime at 33.
+ // max_valid_lifetime at 34.
+
+ // ddns_send_updates at 35.
if (!worker.isColumnNull(35)) {
- last_network->setDdnsOverrideNoUpdate(worker.getBool(35));
+ last_network->setDdnsSendUpdates(worker.getBool(35));
}
- // ddns_override_client_update at 36.
+ // ddns_override_no_update at 36.
if (!worker.isColumnNull(36)) {
- last_network->setDdnsOverrideClientUpdate(worker.getBool(36));
+ last_network->setDdnsOverrideNoUpdate(worker.getBool(36));
}
- // ddns_replace_client_name at 37.
+ // ddns_override_client_update at 37.
if (!worker.isColumnNull(37)) {
- last_network->setDdnsReplaceClientNameMode(
- static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(37)));
+ last_network->setDdnsOverrideClientUpdate(worker.getBool(37));
}
- // ddns_generated_prefix at 38.
+ // ddns_replace_client_name at 38.
if (!worker.isColumnNull(38)) {
- last_network->setDdnsGeneratedPrefix(worker.getString(38));
+ last_network->setDdnsReplaceClientNameMode(
+ static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(38)));
}
- // ddns_qualifying_suffix at 39.
+ // ddns_generated_prefix at 39.
if (!worker.isColumnNull(39)) {
- last_network->setDdnsQualifyingSuffix(worker.getString(39));
+ last_network->setDdnsGeneratedPrefix(worker.getString(39));
}
- // reservations_in_subnet at 40.
+ // ddns_qualifying_suffix at 40.
if (!worker.isColumnNull(40)) {
- last_network->setReservationsInSubnet(worker.getBool(40));
+ last_network->setDdnsQualifyingSuffix(worker.getString(40));
}
// reservations_in_subnet at 41.
if (!worker.isColumnNull(41)) {
- last_network->setReservationsOutOfPool(worker.getBool(41));
+ last_network->setReservationsInSubnet(worker.getBool(41));
}
- // cache_threshold at 42.
+ // reservations_in_subnet at 42.
if (!worker.isColumnNull(42)) {
- last_network->setCacheThreshold(worker.getDouble(42));
+ last_network->setReservationsOutOfPool(worker.getBool(42));
}
- // cache_max_age at 43.
+ // cache_threshold at 43.
if (!worker.isColumnNull(43)) {
- last_network->setCacheMaxAge(worker.getInt(43));
+ last_network->setCacheThreshold(worker.getDouble(43));
}
- // server_tag at 44.
+ // cache_max_age at 44.
+ if (!worker.isColumnNull(44)) {
+ last_network->setCacheMaxAge(worker.getInt(44));
+ }
+
+ // server_tag at 45.
// Add the shared network.
auto ret = shared_networks.push_back(last_network);
}
// Check for new server tags.
- if (!worker.isColumnNull(44)) {
- std::string new_tag = worker.getString(44);
+ if (!worker.isColumnNull(45)) {
+ std::string new_tag = worker.getString(45);
if (last_tag != new_tag) {
if (!new_tag.empty() && !last_network->hasServerTag(ServerTag(new_tag))) {
last_network->setServerTag(new_tag);
}
}
- // Parse network-specific option from 13 to 24.
+ // Parse network-specific option from 13 to 25.
if (!worker.isColumnNull(13) &&
(last_option_id < worker.getBigInt(13))) {
last_option_id = worker.getBigInt(13);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.addNull();
in_bindings.add(0);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.add(subnet_id);
in_bindings.add(1);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.addNull();
in_bindings.add(5);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.addNull();
in_bindings.add(4);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.add(class_name);
in_bindings.addNull();
in_bindings.add(2);
class_list.push_back(last_client_class);
}
- // Check for new server tags at 36.
- if (!worker.isColumnNull(36)) {
- std::string new_tag = worker.getString(36);
+ // Check for new server tags at 37.
+ if (!worker.isColumnNull(37)) {
+ std::string new_tag = worker.getString(37);
if (last_tag != new_tag) {
if (!new_tag.empty() && !last_client_class->hasServerTag(ServerTag(new_tag))) {
last_client_class->setServerTag(new_tag);
}
}
- // Parse client class specific option from 24 to 35.
+ // Parse client class specific option from 24 to 36.
if (!worker.isColumnNull(24) &&
(last_option_id < worker.getBigInt(24))) {
last_option_id = worker.getBigInt(24);
// Insert subnet specific option.
{
// PgSqlConfigBackendDHCPv4Impl::INSERT_OPTION4,
- 12,
+ 13,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp4_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP // 12 modification_ts
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp4_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP // 13 modification_ts
},
"INSERT_OPTION4",
PGSQL_INSERT_OPTION4()
// Update existing global option.
{
// PgSqlConfigBackendDHCPv4Impl::UPDATE_OPTION4,
- 15,
+ 16,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp4_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_VARCHAR, // 13 server_tag
- OID_INT2, // 14 code (of option to update)
- OID_VARCHAR, // 15 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp4_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_VARCHAR, // 14 server_tag
+ OID_INT2, // 15 code (of option to update)
+ OID_VARCHAR, // 16 space (of option to update)
},
"UPDATE_OPTION4",
- PGSQL_UPDATE_OPTION4_WITH_TAG(AND o.scope_id = 0 AND o.code = $14 AND o.space = $15)
+ PGSQL_UPDATE_OPTION4_WITH_TAG(AND o.scope_id = 0 AND o.code = $15 AND o.space = $16)
},
// Update existing subnet level option.
{
// PgSqlConfigBackendDHCPv4Impl::UPDATE_OPTION4_SUBNET_ID,
- 15,
+ 16,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp4_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 subnet_id (of option to update)
- OID_INT2, // 14 code (of option to update)
- OID_VARCHAR // 15 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp4_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 subnet_id (of option to update)
+ OID_INT2, // 15 code (of option to update)
+ OID_VARCHAR // 16 space (of option to update)
},
"UPDATE_OPTION4_SUBNET_ID",
- PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 1 AND o.dhcp4_subnet_id = $13 AND o.code = $14 AND o.space = $15)
+ PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 1 AND o.dhcp4_subnet_id = $14 AND o.code = $15 AND o.space = $16)
},
// Update existing pool level option.
{
// PgSqlConfigBackendDHCPv4Impl::UPDATE_OPTION4_POOL_ID,
- 15,
+ 16,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp4_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pool_id (of option to update)
- OID_INT2, // 14 code (of option to update)
- OID_VARCHAR // 15 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp4_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pool_id (of option to update)
+ OID_INT2, // 15 code (of option to update)
+ OID_VARCHAR // 16 space (of option to update)
},
"UPDATE_OPTION4_POOL_ID",
- PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 5 AND o.pool_id = $13 AND o.code = $14 AND o.space = $15)
+ PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 5 AND o.pool_id = $14 AND o.code = $15 AND o.space = $16)
},
// Update existing shared network level option.
{
// PgSqlConfigBackendDHCPv4Impl::UPDATE_OPTION4_SHARED_NETWORK,
- 15,
+ 16,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp4_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_VARCHAR, // 13 shared_network_name (of option to update)
- OID_INT2, // 14 code (of option to update)
- OID_VARCHAR // 15 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp4_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_VARCHAR, // 14 shared_network_name (of option to update)
+ OID_INT2, // 15 code (of option to update)
+ OID_VARCHAR // 16 space (of option to update)
},
"UPDATE_OPTION4_SHARED_NETWORK",
- PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 4 AND o.shared_network_name = $13 AND o.code = $14 AND o.space = $15)
+ PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 4 AND o.shared_network_name = $14 AND o.code = $15 AND o.space = $16)
},
// Update existing client class level option.
{
// PgSqlConfigBackendDHCPv4Impl::UPDATE_OPTION4_CLIENT_CLASS,
- 15,
+ 16,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp4_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_VARCHAR, // 13 dhcp_client_class (of option to update)
- OID_INT2, // 14 code (of option to update)
- OID_VARCHAR, // 15 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp4_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_VARCHAR, // 14 dhcp_client_class (of option to update)
+ OID_INT2, // 15 code (of option to update)
+ OID_VARCHAR, // 16 space (of option to update)
},
"UPDATE_OPTION4_CLIENT_CLASS",
- PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 2 AND o.dhcp_client_class = $13 AND o.code = $14 AND o.space = $15)
+ PGSQL_UPDATE_OPTION4_NO_TAG(o.scope_id = 2 AND o.dhcp_client_class = $14 AND o.code = $15 AND o.space = $16)
},
// Update existing client class with specifying its position.
auto prefix_pair = Subnet6::parsePrefix(subnet_prefix);
// preferred_lifetime (5)
- // min_preferred_lifetime (69)
- // max_preferred_lifetime (70)
- auto preferred_lifetime = worker.getTriplet(5, 69, 70);
+ // min_preferred_lifetime (72)
+ // max_preferred_lifetime (73)
+ auto preferred_lifetime = worker.getTriplet(5, 72, 73);
// renew_timer at 9.
auto renew_timer = worker.getTriplet(9);
auto rebind_timer = worker.getTriplet(7);
// valid_lifetime at 14.
- // min_valid_lifetime at 71.
- // max_valid_lifetime at 72.
- auto valid_lifetime = worker.getTriplet(14, 71, 72);
+ // min_valid_lifetime at 74.
+ // max_valid_lifetime at 75.
+ auto valid_lifetime = worker.getTriplet(14, 74, 75);
// Create subnet with basic settings.
last_subnet = Subnet6::create(prefix_pair.first, prefix_pair.second,
// 15 to 19 are pool
// 20 to 25 are pd pool
- // 26 to 38 are pool option
- // 39 to 51 are pd pool option
- // 52 to 64 are option
+ // 26 to 39 are pool option
+ // 40 to 53 are pd pool option
+ // 54 to 67 are option
- // calculate_tee_times at 65.
- if (!worker.isColumnNull(65)) {
- last_subnet->setCalculateTeeTimes(worker.getBool(65));
+ // calculate_tee_times at 68.
+ if (!worker.isColumnNull(68)) {
+ last_subnet->setCalculateTeeTimes(worker.getBool(68));
}
- // t1_percent at 66.
- if (!worker.isColumnNull(66)) {
- last_subnet->setT1Percent(worker.getDouble(66));
+ // t1_percent at 69.
+ if (!worker.isColumnNull(69)) {
+ last_subnet->setT1Percent(worker.getDouble(69));
}
- // t2_percent at 67.
- if (!worker.isColumnNull(67)) {
- last_subnet->setT2Percent(worker.getDouble(67));
+ // t2_percent at 70.
+ if (!worker.isColumnNull(70)) {
+ last_subnet->setT2Percent(worker.getDouble(70));
}
- // interface_id at 68.
- setInterfaceId(*last_subnet, worker, 68);
+ // interface_id at 71.
+ setInterfaceId(*last_subnet, worker, 71);
- // 69 and 70 are {min,max}_preferred_lifetime
+ // 72 and 73 are {min,max}_preferred_lifetime
- // 71 and 72 are {min,max}_valid_lifetime
+ // 74 and 75 are {min,max}_valid_lifetime
- // 73 is pool client_class
- // 74 is pool require_client_classes
- // 75 is pool user_context
- // 76 is pd pool excluded_prefix
- // 77 is pd pool excluded_prefix_length
- // 78 is pd pool client_class
- // 79 is pd pool require_client_classes
- // 80 is pd pool user_context
+ // 76 is pool client_class
+ // 77 is pool require_client_classes
+ // 78 is pool user_context
+ // 79 is pd pool excluded_prefix
+ // 80 is pd pool excluded_prefix_length
+ // 81 is pd pool client_class
+ // 82 is pd pool require_client_classes
+ // 83 is pd pool user_context
- // ddns_send_updates at 81.
- if (!worker.isColumnNull(81)) {
- last_subnet->setDdnsSendUpdates(worker.getBool(81));
- }
-
- // ddns_override_no_update at 82.
- if (!worker.isColumnNull(82)) {
- last_subnet->setDdnsOverrideNoUpdate(worker.getBool(82));
- }
-
- // ddns_override_client_update at 83.
- if (!worker.isColumnNull(83)) {
- last_subnet->setDdnsOverrideClientUpdate(worker.getBool(83));
- }
-
- // ddns_replace_client_name at 84.
+ // ddns_send_updates at 84.
if (!worker.isColumnNull(84)) {
- last_subnet->setDdnsReplaceClientNameMode(
- static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(84)));
+ last_subnet->setDdnsSendUpdates(worker.getBool(84));
}
- // ddns_generated_prefix at 85.
+ // ddns_override_no_update at 85.
if (!worker.isColumnNull(85)) {
- last_subnet->setDdnsGeneratedPrefix(worker.getString(85));
+ last_subnet->setDdnsOverrideNoUpdate(worker.getBool(85));
}
- // ddns_qualifying_suffix at 86.
+ // ddns_override_client_update at 86.
if (!worker.isColumnNull(86)) {
- last_subnet->setDdnsQualifyingSuffix(worker.getString(86));
+ last_subnet->setDdnsOverrideClientUpdate(worker.getBool(86));
}
- // reservations_in_subnet at 87.
+ // ddns_replace_client_name at 87.
if (!worker.isColumnNull(87)) {
- last_subnet->setReservationsInSubnet(worker.getBool(87));
+ last_subnet->setDdnsReplaceClientNameMode(
+ static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(87)));
}
- // reservations_out_of_pool at 88.
+ // ddns_generated_prefix at 88.
if (!worker.isColumnNull(88)) {
- last_subnet->setReservationsOutOfPool(worker.getBool(88));
+ last_subnet->setDdnsGeneratedPrefix(worker.getString(88));
}
- // cache_threshold at 89.
+ // ddns_qualifying_suffix at 89.
if (!worker.isColumnNull(89)) {
- last_subnet->setCacheThreshold(worker.getDouble(89));
+ last_subnet->setDdnsQualifyingSuffix(worker.getString(89));
}
- // cache_max_age at 90.
+ // reservations_in_subnet at 90.
if (!worker.isColumnNull(90)) {
- last_subnet->setCacheMaxAge(worker.getInt(90));
+ last_subnet->setReservationsInSubnet(worker.getBool(90));
}
- // server_tag at 91.
+ // reservations_out_of_pool at 91.
+ if (!worker.isColumnNull(91)) {
+ last_subnet->setReservationsOutOfPool(worker.getBool(91));
+ }
+
+ // cache_threshold at 92.
+ if (!worker.isColumnNull(92)) {
+ last_subnet->setCacheThreshold(worker.getDouble(92));
+ }
+
+ // cache_max_age at 93.
+ if (!worker.isColumnNull(93)) {
+ last_subnet->setCacheMaxAge(worker.getInt(93));
+ }
+
+ // server_tag at 94.
// Subnet ready. Add it to the list.
auto ret = subnets.insert(last_subnet);
}
}
- // Check for new server tags at 91.
- if (!worker.isColumnNull(91)) {
- std::string new_tag = worker.getString(91);
+ // Check for new server tags at 94.
+ if (!worker.isColumnNull(94)) {
+ std::string new_tag = worker.getString(94);
if (last_tag != new_tag) {
if (!new_tag.empty() && !last_subnet->hasServerTag(ServerTag(new_tag))) {
last_subnet->setServerTag(new_tag);
}
}
- // Pool is between 15 and 19 with extra between 73 and 75
+ // Pool is between 15 and 19 with extra between 76 and 78
// If the row contains information about the pool and it
// appears to be new pool entry (checked by comparing pool
// pool subnet_id at 18 (ignored)
// pool modification_ts at 19 (ignored)
- // pool client_class at 73.
- if (!worker.isColumnNull(73)) {
- last_pool->allowClientClass(worker.getString(73));
+ // pool client_class at 76.
+ if (!worker.isColumnNull(76)) {
+ last_pool->allowClientClass(worker.getString(76));
}
- // pool require_client_classes at 74.
- setRequiredClasses(worker, 74, [&last_pool](const std::string& class_name) {
+ // pool require_client_classes at 77.
+ setRequiredClasses(worker, 77, [&last_pool](const std::string& class_name) {
last_pool->requireClientClass(class_name);
});
- // pool user_context at 75.
- if (!worker.isColumnNull(75)) {
- ElementPtr user_context = worker.getJSON(75);
+ // pool user_context at 78.
+ if (!worker.isColumnNull(78)) {
+ ElementPtr user_context = worker.getJSON(78);
if (user_context) {
last_pool->setContext(user_context);
}
last_subnet->addPool(last_pool);
}
- // Pd Pool is between 20 and 25 with extra between 76 and 80
+ // Pd Pool is between 20 and 25 with extra between 79 and 83
// If the row contains information about the pd pool and
// it appears to be new pd pool entry (checked by
// 24 is pd pool subnet_id (ignored)
// 25 is pd pool modification_ts (ignored)
- // excluded_prefix (76) and excluded_prefix_length (77)
+ // excluded_prefix (79) and excluded_prefix_length (80)
IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS();
- if (!worker.isColumnNull(76)) {
- excluded_prefix = worker.getInet6(76);
+ if (!worker.isColumnNull(79)) {
+ excluded_prefix = worker.getInet6(79);
}
last_pd_pool_id = worker.getBigInt(20);
static_cast<uint8_t>(worker.getSmallInt(22)),
static_cast<uint8_t>(worker.getSmallInt(23)),
excluded_prefix,
- static_cast<uint8_t>(worker.getSmallInt(77)));
+ static_cast<uint8_t>(worker.getSmallInt(80)));
- // pd pool client_class (78)
- if (!worker.isColumnNull(78)) {
- last_pd_pool->allowClientClass(worker.getString(78));
+ // pd pool client_class (81)
+ if (!worker.isColumnNull(81)) {
+ last_pd_pool->allowClientClass(worker.getString(81));
}
- // pd pool require_client_classes at 79.
- setRequiredClasses(worker, 79, [&last_pd_pool](const std::string& class_name) {
+ // pd pool require_client_classes at 82.
+ setRequiredClasses(worker, 82, [&last_pd_pool](const std::string& class_name) {
last_pd_pool->requireClientClass(class_name);
});
- // pd pool user_context at 80.
- if (!worker.isColumnNull(80)) {
- ElementPtr user_context = worker.getJSON(80);
+ // pd pool user_context at 83.
+ if (!worker.isColumnNull(83)) {
+ ElementPtr user_context = worker.getJSON(83);
if (user_context) {
last_pd_pool->setContext(user_context);
}
last_subnet->addPool(last_pd_pool);
}
- // Parse pool-specific option from 26 to 38.
+ // Parse pool-specific option from 26 to 39.
if (last_pool && !worker.isColumnNull(26) &&
(last_pool_option_id < worker.getBigInt(26))) {
last_pool_option_id = worker.getBigInt(26);
}
}
- // Parse pd pool-specific option from 39 to 51.
- if (last_pd_pool && !worker.isColumnNull(39) &&
- (last_pd_pool_option_id < worker.getBigInt(39))) {
- last_pd_pool_option_id = worker.getBigInt(39);
+ // Parse pd pool-specific option from 40 to 53.
+ if (last_pd_pool && !worker.isColumnNull(40) &&
+ (last_pd_pool_option_id < worker.getBigInt(40))) {
+ last_pd_pool_option_id = worker.getBigInt(40);
- OptionDescriptorPtr desc = processOptionRow(Option::V6, worker, 39);
+ OptionDescriptorPtr desc = processOptionRow(Option::V6, worker, 40);
if (desc) {
last_pd_pool->getCfgOption()->add(*desc, desc->space_name_);
}
}
- // Parse subnet-specific option from 52 to 64.
- if (!worker.isColumnNull(52) &&
- (last_option_id < worker.getBigInt(52))) {
- last_option_id = worker.getBigInt(52);
+ // Parse subnet-specific option from 54 to 67.
+ if (!worker.isColumnNull(54) &&
+ (last_option_id < worker.getBigInt(54))) {
+ last_option_id = worker.getBigInt(54);
- OptionDescriptorPtr desc = processOptionRow(Option::V6, worker, 52);
+ OptionDescriptorPtr desc = processOptionRow(Option::V6, worker, 54);
if (desc) {
last_subnet->getCfgOption()->add(*desc, desc->space_name_);
}
pd_pool_ids.push_back(last_pd_pool_id);
}
- // Parse pd pool specific option between 11 and 24.
+ // Parse pd pool specific option between 11 and 25.
if (last_pd_pool && !worker.isColumnNull(11) &&
(last_pd_pool_option_id < worker.getBigInt(11))) {
last_pd_pool_option_id = worker.getBigInt(11);
last_network->setModificationTime(worker.getTimestamp(4));
// preferred_lifetime (5)
- // min_preferred_lifetime (31)
- // max_preferred_lifetime (32)
- last_network->setPreferred(worker.getTriplet(5, 31, 32));
+ // min_preferred_lifetime (32)
+ // max_preferred_lifetime (33)
+ last_network->setPreferred(worker.getTriplet(5, 32, 33));
// rapid_commit at 6.
if (!worker.isColumnNull(6)) {
}
// valid_lifetime at 13.
- // min_valid_lifetime at 33.
- // max_valid_lifetime at 34.
+ // min_valid_lifetime at 34.
+ // max_valid_lifetime at 35.
if (!worker.isColumnNull(13)) {
- last_network->setValid(worker.getTriplet(13, 33, 34));
+ last_network->setValid(worker.getTriplet(13, 34, 35));
}
- // option from 14 to 26.
-
- // calculate_tee_times at 27.
- if (!worker.isColumnNull(27)) {
- last_network->setCalculateTeeTimes(worker.getBool(27));
- }
+ // option from 14 to 27.
- // t1_percent at 28.
+ // calculate_tee_times at 28.
if (!worker.isColumnNull(28)) {
- last_network->setT1Percent(worker.getDouble(28));
+ last_network->setCalculateTeeTimes(worker.getBool(28));
}
- // t2_percent at 29.
+ // t1_percent at 29.
if (!worker.isColumnNull(29)) {
- last_network->setT2Percent(worker.getDouble(29));
+ last_network->setT1Percent(worker.getDouble(29));
}
- // interface_id at 30.
- setInterfaceId(*last_network, worker, 30);
+ // t2_percent at 30.
+ if (!worker.isColumnNull(30)) {
+ last_network->setT2Percent(worker.getDouble(30));
+ }
- // min_preferred_lifetime at 31.
- // max_preferred_lifetime at 32.
- // min_valid_lifetime at 33.
- // max_valid_lifetime at 34.
+ // interface_id at 31.
+ setInterfaceId(*last_network, worker, 31);
- // ddns_send_updates at 35.
- if (!worker.isColumnNull(35)) {
- last_network->setDdnsSendUpdates(worker.getBool(35));
- }
+ // min_preferred_lifetime at 32.
+ // max_preferred_lifetime at 33.
+ // min_valid_lifetime at 34.
+ // max_valid_lifetime at 35.
- // ddns_override_no_update at 36.
+ // ddns_send_updates at 36.
if (!worker.isColumnNull(36)) {
- last_network->setDdnsOverrideNoUpdate(worker.getBool(36));
+ last_network->setDdnsSendUpdates(worker.getBool(36));
}
- // ddns_override_client_update at 37.
+ // ddns_override_no_update at 37.
if (!worker.isColumnNull(37)) {
- last_network->setDdnsOverrideClientUpdate(worker.getBool(37));
+ last_network->setDdnsOverrideNoUpdate(worker.getBool(37));
}
- // ddns_replace_client_name at 38.
+ // ddns_override_client_update at 38.
if (!worker.isColumnNull(38)) {
- last_network->setDdnsReplaceClientNameMode(
- static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(38)));
+ last_network->setDdnsOverrideClientUpdate(worker.getBool(38));
}
- // ddns_generated_prefix at 39.
+ // ddns_replace_client_name at 39.
if (!worker.isColumnNull(39)) {
- last_network->setDdnsGeneratedPrefix(worker.getString(39));
+ last_network->setDdnsReplaceClientNameMode(
+ static_cast<D2ClientConfig::ReplaceClientNameMode>(worker.getSmallInt(39)));
}
- // ddns_qualifying_suffix at 40.
+ // ddns_generated_prefix at 40.
if (!worker.isColumnNull(40)) {
- last_network->setDdnsQualifyingSuffix(worker.getString(40));
+ last_network->setDdnsGeneratedPrefix(worker.getString(40));
}
- // reservations_in_subnet at 41.
+ // ddns_qualifying_suffix at 41.
if (!worker.isColumnNull(41)) {
- last_network->setReservationsInSubnet(worker.getBool(41));
+ last_network->setDdnsQualifyingSuffix(worker.getString(41));
}
// reservations_in_subnet at 42.
if (!worker.isColumnNull(42)) {
- last_network->setReservationsOutOfPool(worker.getBool(42));
+ last_network->setReservationsInSubnet(worker.getBool(42));
}
- // cache_threshold at 43.
+ // reservations_in_subnet at 43.
if (!worker.isColumnNull(43)) {
- last_network->setCacheThreshold(worker.getDouble(43));
+ last_network->setReservationsOutOfPool(worker.getBool(43));
}
- // cache_max_age at 44.
+ // cache_threshold at 44.
if (!worker.isColumnNull(44)) {
- last_network->setCacheMaxAge(worker.getInt(44));
+ last_network->setCacheThreshold(worker.getDouble(44));
+ }
+
+ // cache_max_age at 45.
+ if (!worker.isColumnNull(45)) {
+ last_network->setCacheMaxAge(worker.getInt(45));
}
- // server_tag at 45.
+ // server_tag at 46.
// Add the shared network.
auto ret = shared_networks.push_back(last_network);
}
// Check for new server tags.
- if (!worker.isColumnNull(45)) {
- std::string new_tag = worker.getString(45);
+ if (!worker.isColumnNull(46)) {
+ std::string new_tag = worker.getString(46);
if (last_tag != new_tag) {
if (!new_tag.empty() && !last_network->hasServerTag(ServerTag(new_tag))) {
last_network->setServerTag(new_tag);
}
}
- // Parse network-specific option from 14 to 26.
+ // Parse network-specific option from 14 to 27.
if (!worker.isColumnNull(14) &&
(last_option_id < worker.getBigInt(14))) {
last_option_id = worker.getBigInt(14);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.addNull();
in_bindings.add(0);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.add(subnet_id);
in_bindings.add(1);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.addNull();
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.addNull();
in_bindings.addNull();
in_bindings.add(4);
in_bindings.addOptional(option->formatted_value_);
in_bindings.addOptional(option->space_name_);
in_bindings.add(option->persistent_);
+ in_bindings.add(option->cancelled_);
in_bindings.add(class_name);
in_bindings.addNull();
in_bindings.add(2);
}
// class specific option definition from 11 to 20.
- // class specific option from 21 to 32.
+ // class specific option from 21 to 33.
// preferred lifetime: default, min, max
- last_client_class->setPreferred(worker.getTriplet(34, 35, 36));
+ last_client_class->setPreferred(worker.getTriplet(35, 36, 37));
class_list.push_back(last_client_class);
}
- // Check for new server tags at 33.
- if (!worker.isColumnNull(33)) {
- std::string new_tag = worker.getString(33);
+ // Check for new server tags at 34.
+ if (!worker.isColumnNull(34)) {
+ std::string new_tag = worker.getString(34);
if (last_tag != new_tag) {
if (!new_tag.empty() && !last_client_class->hasServerTag(ServerTag(new_tag))) {
last_client_class->setServerTag(new_tag);
}
}
- // Parse client class specific option from 21 to 32.
+ // Parse client class specific option from 21 to 33.
if (!worker.isColumnNull(21) &&
(last_option_id < worker.getBigInt(21))) {
last_option_id = worker.getBigInt(21);
// Insert subnet specific option.
{
// PgSqlConfigBackendDHCPv6Impl::INSERT_OPTION6,
- 13,
+ 14,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8 // 13 pd_pool_id
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8 // 14 pd_pool_id
},
"INSERT_OPTION6",
PGSQL_INSERT_OPTION6()
// Update existing global option.
{
// PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6,
- 16,
+ 17,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pd_pool_id
- OID_VARCHAR, // 14 server_tag
- OID_INT2, // 15 code (of option to update)
- OID_VARCHAR, // 16 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pd_pool_id
+ OID_VARCHAR, // 15 server_tag
+ OID_INT2, // 16 code (of option to update)
+ OID_VARCHAR, // 17 space (of option to update)
},
"UPDATE_OPTION6",
- PGSQL_UPDATE_OPTION6_WITH_TAG(AND o.scope_id = 0 AND o.code = $15 AND o.space = $16)
+ PGSQL_UPDATE_OPTION6_WITH_TAG(AND o.scope_id = 0 AND o.code = $16 AND o.space = $17)
},
// Update existing subnet level option.
{
// PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SUBNET_ID,
- 16,
+ 17,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pd_pool_id
- OID_INT8, // 14 subnet_id (of option to update)
- OID_INT2, // 15 code (of option to update)
- OID_VARCHAR // 16 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pd_pool_id
+ OID_INT8, // 15 subnet_id (of option to update)
+ OID_INT2, // 16 code (of option to update)
+ OID_VARCHAR // 17 space (of option to update)
},
"UPDATE_OPTION6_SUBNET_ID",
- PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 1 AND o.dhcp6_subnet_id = $14 AND o.code = $15 AND o.space = $16)
+ PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 1 AND o.dhcp6_subnet_id = $15 AND o.code = $16 AND o.space = $17)
},
// Update existing pool level option.
{
// PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_POOL_ID,
- 16,
+ 17,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pd_pool_id
- OID_INT8, // 14 pool_id (of option to update)
- OID_INT2, // 15 code (of option to update)
- OID_VARCHAR // 16 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pd_pool_id
+ OID_INT8, // 15 pool_id (of option to update)
+ OID_INT2, // 16 code (of option to update)
+ OID_VARCHAR // 17 space (of option to update)
},
"UPDATE_OPTION6_POOL_ID",
- PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 5 AND o.pool_id = $14 AND o.code = $15 AND o.space = $16)
+ PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 5 AND o.pool_id = $15 AND o.code = $16 AND o.space = $17)
},
// Update existing pd pool level option.
{
// PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_PD_POOL_ID,
- 16,
+ 17,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pd_pool_id
- OID_INT8, // 14 pd_pool_id (of option to update)
- OID_INT2, // 15 code (of option to update)
- OID_VARCHAR // 16 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pd_pool_id
+ OID_INT8, // 15 pd_pool_id (of option to update)
+ OID_INT2, // 16 code (of option to update)
+ OID_VARCHAR // 17 space (of option to update)
},
"UPDATE_OPTION6_PD_POOL_ID",
- PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 6 AND o.pd_pool_id = $14 AND o.code = $15 AND o.space = $16)
+ PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 6 AND o.pd_pool_id = $15 AND o.code = $16 AND o.space = $17)
},
// Update existing shared network level option.
{
// PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_SHARED_NETWORK,
- 16,
+ 17,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pd_pool_id
- OID_VARCHAR, // 14 shared_network_name (of option to update)
- OID_INT2, // 15 code (of option to update)
- OID_VARCHAR // 16 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pd_pool_id
+ OID_VARCHAR, // 15 shared_network_name (of option to update)
+ OID_INT2, // 16 code (of option to update)
+ OID_VARCHAR // 17 space (of option to update)
},
"UPDATE_OPTION6_SHARED_NETWORK",
- PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 4 AND o.shared_network_name = $14 AND o.code = $15 AND o.space = $16)
+ PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 4 AND o.shared_network_name = $15 AND o.code = $16 AND o.space = $17)
},
// Update existing client class level option.
{
// PgSqlConfigBackendDHCPv6Impl::UPDATE_OPTION6_CLIENT_CLASS,
- 16,
+ 17,
{
OID_INT2, // 1 code
OID_BYTEA, // 2 value
OID_TEXT, // 3 formatted_value
OID_VARCHAR, // 4 space
OID_BOOL, // 5 persistent
- OID_VARCHAR, // 6 dhcp_client_class
- OID_INT8, // 7 dhcp6_subnet_id
- OID_INT2, // 8 scope_id
- OID_TEXT, // 9 user_context
- OID_VARCHAR, // 10 shared_network_name
- OID_INT8, // 11 pool_id
- OID_TIMESTAMP, // 12 modification_ts
- OID_INT8, // 13 pd_pool_id
- OID_VARCHAR, // 14 client_class (of option to update)
- OID_INT2, // 15 code (of option to update)
- OID_VARCHAR // 16 space (of option to update)
+ OID_BOOL, // 6 cancelled
+ OID_VARCHAR, // 7 dhcp_client_class
+ OID_INT8, // 8 dhcp6_subnet_id
+ OID_INT2, // 9 scope_id
+ OID_TEXT, // 10 user_context
+ OID_VARCHAR, // 11 shared_network_name
+ OID_INT8, // 12 pool_id
+ OID_TIMESTAMP, // 13 modification_ts
+ OID_INT8, // 14 pd_pool_id
+ OID_VARCHAR, // 15 client_class (of option to update)
+ OID_INT2, // 16 code (of option to update)
+ OID_VARCHAR // 17 space (of option to update)
},
"UPDATE_OPTION6_CLIENT_CLASS",
- PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 2 AND o.dhcp_client_class = $14 AND o.code = $15 AND o.space = $16)
+ PGSQL_UPDATE_OPTION6_NO_TAG(o.scope_id = 2 AND o.dhcp_client_class = $15 AND o.code = $16 AND o.space = $17)
},
// Update existing client class with specifying its position.
OptionDescriptorPtr desc = processOptionRow(universe, worker, 0);
if (desc) {
// server_tag for the global option
- ServerTag last_option_server_tag(worker.getString(12));
+ ServerTag last_option_server_tag(worker.getString(13));
desc->setServerTag(last_option_server_tag.get());
// If we're fetching options for a given server (explicit server
OptionDescriptorPtr
PgSqlConfigBackendImpl::processOptionRow(const Option::Universe& universe,
- PgSqlResultRowWorker& worker, size_t first_col) {
+ PgSqlResultRowWorker& worker,
+ size_t first_col) {
// Some of the options have standard or custom definitions.
// Depending whether the option has a definition or not a different
// C++ class may be used to represent the option. Therefore, the
persistent = worker.getBool(first_col + 5);
}
+ // Check if the option is cancelled.
+ bool cancelled = false;
+ if (!worker.isColumnNull(first_col + 6)) {
+ cancelled = worker.getBool(first_col + 6);
+ }
+
// Create option descriptor which encapsulates our option and adds
// additional information, i.e. whether the option is persistent,
// its option space and timestamp.
- OptionDescriptorPtr desc = OptionDescriptor::create(option, persistent, formatted_value);
+ OptionDescriptorPtr desc = OptionDescriptor::create(option,
+ persistent,
+ cancelled,
+ formatted_value);
desc->space_name_ = space;
- desc->setModificationTime(worker.getTimestamp(first_col + 11));
+ desc->setModificationTime(worker.getTimestamp(first_col + 12));
// Set database id for the option.
// @todo Can this actually ever be null and if it is, isn't that an error?
/// - formatted_value,
/// - space,
/// - persistent,
+ /// - cancelled,
/// - dhcp4_subnet_id/dhcp6_subnet_id,
/// - scope_id,
/// - user_context,
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp4_subnet_id," \
" x.scope_id," \
" x.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp4_subnet_id," \
" o.scope_id," \
" o.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" y.formatted_value," \
" y.space," \
" y.persistent," \
+ " y.cancelled," \
" y.dhcp6_subnet_id," \
" y.scope_id," \
" y.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp6_subnet_id," \
" o.scope_id," \
" o.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp4_subnet_id," \
" x.scope_id," \
" x.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp4_subnet_id," \
" o.scope_id," \
" o.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o.dhcp6_subnet_id," \
" o.scope_id," \
" o.user_context," \
" o.formatted_value," \
" o.space," \
" o.persistent," \
+ " o.cancelled," \
" o." #table_prefix "_subnet_id," \
" o.scope_id," \
" o.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp4_subnet_id," \
" x.scope_id," \
" x.user_context," \
" x.formatted_value," \
" x.space," \
" x.persistent," \
+ " x.cancelled," \
" x.dhcp6_subnet_id," \
" x.scope_id," \
" x.user_context," \
" formatted_value," \
" space," \
" persistent," \
+ " cancelled," \
" dhcp_client_class," \
" " #table_prefix "_subnet_id," \
" scope_id," \
" pool_id," \
" modification_ts" \
pd_pool_id \
- ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, cast($9 as json), $10, $11, $12" last ")"
+ ") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, cast($10 as json), $11, $12, $13" last ")"
#define PGSQL_INSERT_OPTION4() \
PGSQL_INSERT_OPTION_COMMON(dhcp4, "", "")
#define PGSQL_INSERT_OPTION6() \
- PGSQL_INSERT_OPTION_COMMON(dhcp6, ", pd_pool_id ", ", $13")
+ PGSQL_INSERT_OPTION_COMMON(dhcp6, ", pd_pool_id ", ", $14")
#endif
#ifndef PGSQL_INSERT_OPTION_SERVER
" formatted_value = $3," \
" space = $4," \
" persistent = $5," \
- " dhcp_client_class = $6," \
- " " #table_prefix "_subnet_id = $7," \
- " scope_id = $8," \
- " user_context = cast($9 as json)," \
- " shared_network_name = $10," \
- " pool_id = $11," \
- " modification_ts = $12 " \
+ " cancelled = $6," \
+ " dhcp_client_class = $7," \
+ " " #table_prefix "_subnet_id = $8," \
+ " scope_id = $9," \
+ " user_context = cast($10 as json)," \
+ " shared_network_name = $11," \
+ " pool_id = $12," \
+ " modification_ts = $13 " \
pd_pool_id \
"WHERE " #__VA_ARGS__
PGSQL_UPDATE_OPTION_NO_TAG(dhcp4, "", __VA_ARGS__)
#define PGSQL_UPDATE_OPTION6_NO_TAG(...) \
- PGSQL_UPDATE_OPTION_NO_TAG(dhcp6, ", pd_pool_id = $13 ", __VA_ARGS__)
+ PGSQL_UPDATE_OPTION_NO_TAG(dhcp6, ", pd_pool_id = $14 ", __VA_ARGS__)
#endif
#ifndef PGSQL_UPDATE_OPTION_WITH_TAG
" formatted_value = $3," \
" space = $4," \
" persistent = $5," \
- " dhcp_client_class = $6," \
- " " #table_prefix "_subnet_id = $7," \
- " scope_id = $8," \
- " user_context = cast($9 as json)," \
- " shared_network_name = $10," \
- " pool_id = $11," \
- " modification_ts = $12 " \
+ " cancelled = $6," \
+ " dhcp_client_class = $7," \
+ " " #table_prefix "_subnet_id = $8," \
+ " scope_id = $9," \
+ " user_context = cast($10 as json)," \
+ " shared_network_name = $11," \
+ " pool_id = $12," \
+ " modification_ts = $13 " \
pd_pool_id \
"FROM " #table_prefix "_options_server as a, " \
" " #table_prefix "_server as s " \
#__VA_ARGS__
#define PGSQL_UPDATE_OPTION4_WITH_TAG(...) \
- PGSQL_UPDATE_OPTION_WITH_TAG(dhcp4, "", AND s.tag = $13 __VA_ARGS__)
+ PGSQL_UPDATE_OPTION_WITH_TAG(dhcp4, "", AND s.tag = $14 __VA_ARGS__)
#define PGSQL_UPDATE_OPTION6_WITH_TAG(...) \
PGSQL_UPDATE_OPTION_WITH_TAG(dhcp6, \
- ", pd_pool_id = $13 ", AND s.tag = $14 __VA_ARGS__)
+ ", pd_pool_id = $14 ", AND s.tag = $15 __VA_ARGS__)
#endif
#ifndef PGSQL_UPDATE_CLIENT_CLASS4
namespace dhcp {
OptionDescriptorPtr
-OptionDescriptor::create(const OptionPtr& opt, bool persist,
+OptionDescriptor::create(const OptionPtr& opt, bool persist, bool cancel,
const std::string& formatted_value,
ConstElementPtr user_context) {
- return (boost::make_shared<OptionDescriptor>(opt, persist, formatted_value,
+ return (boost::make_shared<OptionDescriptor>(opt, persist, cancel,
+ formatted_value,
user_context));
}
OptionDescriptorPtr
-OptionDescriptor::create(bool persist) {
- return (boost::make_shared<OptionDescriptor>(persist));
+OptionDescriptor::create(bool persist, bool cancel) {
+ return (boost::make_shared<OptionDescriptor>(persist, cancel));
}
OptionDescriptorPtr
bool
OptionDescriptor::equals(const OptionDescriptor& other) const {
return ((persistent_ == other.persistent_) &&
+ (cancelled_ == other.cancelled_) &&
(formatted_value_ == other.formatted_value_) &&
(space_name_ == other.space_name_) &&
option_->equals(other.option_));
}
void
-CfgOption::add(const OptionPtr& option, const bool persistent,
+CfgOption::add(const OptionPtr& option,
+ const bool persistent,
+ const bool cancelled,
const std::string& option_space,
const uint64_t id) {
- OptionDescriptor desc(option, persistent);
+ OptionDescriptor desc(option, persistent, cancelled);
if (id > 0) {
desc.setId(id);
}
map->set("csv-format", Element::create(true));
map->set("data", Element::create(opt.formatted_value_));
} else {
- map->set("csv-format", Element::create(false));
std::vector<uint8_t> bin = opt.option_->toBinary();
- std::string repr = util::encode::encodeHex(bin);
- map->set("data", Element::create(repr));
+ if (!opt.cancelled_ || !bin.empty()) {
+ map->set("csv-format", Element::create(false));
+ std::string repr = util::encode::encodeHex(bin);
+ map->set("data", Element::create(repr));
+ }
}
// Set the persistency flag
map->set("always-send", Element::create(opt.persistent_));
-
+ // Set the cancelled flag.
+ map->set("never-send", Element::create(opt.cancelled_));
// Include metadata if requested.
if (include_metadata) {
map->set("metadata", opt.getMetadata());
map->set("csv-format", Element::create(true));
map->set("data", Element::create(opt.formatted_value_));
} else {
- map->set("csv-format", Element::create(false));
std::vector<uint8_t> bin = opt.option_->toBinary();
- std::string repr = util::encode::encodeHex(bin);
- map->set("data", Element::create(repr));
+ if (!opt.cancelled_ || !bin.empty()) {
+ map->set("csv-format", Element::create(false));
+ std::string repr = util::encode::encodeHex(bin);
+ map->set("data", Element::create(repr));
+ }
}
// Set the persistency flag
map->set("always-send", Element::create(opt.persistent_));
+ // Set the cancellation flag
+ map->set("never-send", Element::create(opt.cancelled_));
// Push on the list
result->add(map);
}
/// Option descriptor holds instance of an option and additional information
/// for this option. This information comprises whether this option is sent
/// to DHCP client only on request (persistent = false) or always
-/// (persistent = true).
+/// (persistent = true), or must never send (cancelled = true).
class OptionDescriptor : public data::StampedElement, public data::UserContext {
public:
/// @brief Option instance.
/// sent to the client when requested using ORO or PRL option.
bool persistent_;
+ /// @brief Cancelled flag.
+ ///
+ /// If true, option is never sent to the client. If false, option is
+ /// sent when it should.
+ /// @note: When true the action of this flag is final i.e. it can't be
+ /// overridden at a more specific level and has precedence over persist.
+ bool cancelled_;
+
/// @brief Option value in textual (CSV) format.
///
/// This field is used to convey option value in human readable format,
///
/// @param opt option instance.
/// @param persist if true, option is always sent.
+ /// @param cancel if true, option is never sent.
/// @param formatted_value option value in the textual format (optional).
/// @param user_context user context (optional).
- OptionDescriptor(const OptionPtr& opt, bool persist,
+ OptionDescriptor(const OptionPtr& opt, bool persist, bool cancel,
const std::string& formatted_value = "",
data::ConstElementPtr user_context = data::ConstElementPtr())
: data::StampedElement(), option_(opt), persistent_(persist),
- formatted_value_(formatted_value),
+ cancelled_(cancel), formatted_value_(formatted_value),
space_name_() {
setContext(user_context);
};
/// @brief Constructor.
///
/// @param persist if true option is always sent.
- OptionDescriptor(bool persist)
+ /// @param cancel if true, option is never sent.
+ OptionDescriptor(bool persist, bool cancel)
: data::StampedElement(), option_(OptionPtr()), persistent_(persist),
- formatted_value_(), space_name_() {};
+ cancelled_(cancel), formatted_value_(), space_name_() {};
/// @brief Copy constructor.
///
: data::StampedElement(desc),
option_(desc.option_),
persistent_(desc.persistent_),
+ cancelled_(desc.cancelled_),
formatted_value_(desc.formatted_value_),
space_name_(desc.space_name_) {
setContext(desc.getContext());
data::StampedElement::operator=(other);
option_ = other.option_;
persistent_ = other.persistent_;
+ cancelled_ = other.cancelled_;
formatted_value_ = other.formatted_value_;
space_name_ = other.space_name_;
setContext(other.getContext());
///
/// @param opt option instance.
/// @param persist if true, option is always sent.
+ /// @param cancel if true, option is never sent.
/// @param formatted_value option value in the textual format (optional).
/// @param user_context user context (optional).
///
/// @return Pointer to the @c OptionDescriptor instance.
static OptionDescriptorPtr create(const OptionPtr& opt,
bool persist,
+ bool cancel,
const std::string& formatted_value = "",
data::ConstElementPtr user_context =
data::ConstElementPtr());
/// @brief Factory function creating an instance of the @c OptionDescriptor.
///
/// @param persist if true option is always sent.
+ /// @param cancel if true, option is never sent.
///
/// @return Pointer to the @c OptionDescriptor instance.
- static OptionDescriptorPtr create(bool persist);
+ static OptionDescriptorPtr create(bool persist, bool cancel);
/// @brief Factory function creating an instance of the @c OptionDescriptor.
///
/// - persistency flag index: used to search option descriptors with
/// 'persistent' flag set to true.
///
-/// This container is the equivalent of three separate STL containers:
+/// This container is the equivalent of four separate STL containers:
/// - std::list of all options,
/// - std::multimap of options with option code used as a multimap key,
/// - std::multimap of option descriptors with option persistency flag
/// used as a multimap key.
-/// The major advantage of this container over 3 separate STL containers
+/// - std::multimap of option descriptors with option cancellation flag
+/// used as a multimap key.
+/// The major advantage of this container over 4 separate STL containers
/// is automatic synchronization of all indexes when elements are added,
/// removed or modified in the container. With separate containers,
/// the synchronization would have to be guaranteed by the Subnet class
boost::multi_index::tag<OptionIdIndexTag>,
boost::multi_index::const_mem_fun<data::BaseStampedElement, uint64_t,
&data::BaseStampedElement::getId>
+ >,
+ // Start definition of index #5.
+ // Use 'cancelled' struct member as a key.
+ boost::multi_index::hashed_non_unique<
+ boost::multi_index::member<
+ OptionDescriptor,
+ bool,
+ &OptionDescriptor::cancelled_
+ >
>
>
> OptionContainer;
/// the beginning of the range, the second element represents the end.
typedef std::pair<OptionContainerPersistIndex::const_iterator,
OptionContainerPersistIndex::const_iterator> OptionContainerPersistRange;
+/// Type of the index #5 - option cancellation flag.
+typedef OptionContainer::nth_index<5>::type OptionContainerCancelIndex;
+/// Pair of iterators to represent the range of options having the
+/// same cancellation flag. The first element in this pair represents
+/// the beginning of the range, the second element represents the end.
+typedef std::pair<OptionContainerCancelIndex::const_iterator,
+ OptionContainerCancelIndex::const_iterator> OptionContainerCancelRange;
/// @brief Represents option data configuration for the DHCP server.
///
/// @param option Pointer to the option being added.
/// @param persistent Boolean value which specifies if the option should
/// be sent to the client regardless if requested (true), or nor (false)
+ /// @param cancelled Boolean value which specifies if the option must
+ /// never be sent to the client.
/// @param option_space Option space name.
/// @param id Optional database id to be associated with the option.
///
/// @throw isc::BadValue if the option space is invalid.
void add(const OptionPtr& option, const bool persistent,
- const std::string& option_space,
+ const bool cancelled, const std::string& option_space,
const uint64_t id = 0);
/// @brief A variant of the @ref CfgOption::add method which takes option
// Check for presence of options.
OptionContainerPtr options = getAll(key);
if (!options || options->empty()) {
- return (OptionDescriptor(false));
+ return (OptionDescriptor(false, false));
}
// Some options present, locate the one we are interested in.
const OptionContainerTypeIndex& idx = options->get<1>();
OptionContainerTypeIndex::const_iterator od_itr = idx.find(option_code);
if (od_itr == idx.end()) {
- return (OptionDescriptor(false));
+ return (OptionDescriptor(false, false));
}
return (*od_itr);
private:
/// @brief Number of columns holding DHCPv4 or DHCPv6 option information.
- static const size_t OPTION_COLUMNS = 7;
+ static const size_t OPTION_COLUMNS = 8;
/// @brief Receives DHCPv4 or DHCPv6 options information from the
/// dhcp4_options or dhcp6_options tables respectively.
const size_t start_column)
: universe_(universe), start_column_(start_column), option_id_(0),
code_(0), value_length_(0), formatted_value_length_(0),
- space_length_(0), persistent_(false), user_context_length_(0),
+ space_length_(0), persistent_(false), cancelled_(false),
+ user_context_length_(0),
option_id_null_(MLM_FALSE), code_null_(MLM_FALSE),
value_null_(MLM_FALSE), formatted_value_null_(MLM_FALSE),
space_null_(MLM_FALSE), user_context_null_(MLM_FALSE),
formatted_value_index_(start_column_ + 3),
space_index_(start_column_ + 4),
persistent_index_(start_column_ + 5),
- user_context_index_(start_column_ + 6),
+ cancelled_index_(start_column_ + 6),
+ user_context_index_(start_column_ + 7),
most_recent_option_id_(0) {
memset(value_, 0, sizeof(value_));
}
}
- OptionDescriptor desc(option, persistent_, formatted_value);
+ OptionDescriptor desc(option, persistent_, cancelled_,
+ formatted_value);
// Set the user context if there is one into the option descriptor.
if (!user_context.empty()) {
columns[formatted_value_index_] = "formatted_value";
columns[space_index_] = "space";
columns[persistent_index_] = "persistent";
+ columns[cancelled_index_] = "cancelled";
columns[user_context_index_] = "user_context";
}
option_id_ = 0;
code_ = 0;
persistent_ = false;
+ cancelled_ = false;
option_id_null_ = MLM_FALSE;
code_null_ = MLM_FALSE;
value_null_ = MLM_FALSE;
bind[persistent_index_].buffer = reinterpret_cast<char*>(&persistent_);
bind[persistent_index_].is_unsigned = MLM_TRUE;
+ // cancelled : TINYINT(1) NOT NULL DEFAULT 0
+ bind[cancelled_index_].buffer_type = MYSQL_TYPE_TINY;
+ bind[cancelled_index_].buffer = reinterpret_cast<char*>(&cancelled_);
+ bind[cancelled_index_].is_unsigned = MLM_TRUE;
+
// user_context : TEXT NULL
user_context_length_ = sizeof(user_context_);
bind[user_context_index_].buffer_type = MYSQL_TYPE_STRING;
/// requested.
bool persistent_;
+ /// @brief Flag indicating if option must be never sent.
+ bool cancelled_;
+
/// @brief Buffer holding textual user context of an option.
char user_context_[USER_CONTEXT_MAX_LEN];
/// @brief Persistent
size_t persistent_index_;
+
+ /// @brief Cancelled
+ size_t cancelled_index_;
//@}
/// @brief User context
private:
/// @brief Number of columns in the tables holding options.
- static const size_t OPTION_COLUMNS = 10;
+ static const size_t OPTION_COLUMNS = 11;
public:
/// @brief Constructor.
MySqlOptionExchange()
: type_(0), value_len_(0), formatted_value_len_(0), space_(),
- space_len_(0), persistent_(false), user_context_(),
- user_context_len_(0), subnet_id_(SUBNET_ID_UNUSED),
+ space_len_(0), persistent_(false), cancelled_(false),
+ user_context_(), user_context_len_(0), subnet_id_(SUBNET_ID_UNUSED),
host_id_(0), option_() {
- BOOST_STATIC_ASSERT(9 < OPTION_COLUMNS);
+ BOOST_STATIC_ASSERT(10 < OPTION_COLUMNS);
}
/// @brief Creates binding array to insert option data into database.
bind_[5].buffer = reinterpret_cast<char*>(&persistent_);
bind_[5].is_unsigned = MLM_TRUE;
+ // cancelled: TINYINT(1) NOT NULL DEFAULT 0
+ cancelled_ = opt_desc.cancelled_;
+ bind_[6].buffer_type = MYSQL_TYPE_TINY;
+ bind_[6].buffer = reinterpret_cast<char*>(&cancelled_);
+ bind_[6].is_unsigned = MLM_TRUE;
+
// user_context: TEST NULL,
ConstElementPtr ctx = opt_desc.getContext();
if (ctx) {
user_context_ = ctx->str();
user_context_len_ = user_context_.size();
- bind_[6].buffer_type = MYSQL_TYPE_STRING;
- bind_[6].buffer = const_cast<char*>(user_context_.c_str());
- bind_[6].buffer_length = user_context_len_;
- bind_[6].length = &user_context_len_;
+ bind_[7].buffer_type = MYSQL_TYPE_STRING;
+ bind_[7].buffer = const_cast<char*>(user_context_.c_str());
+ bind_[7].buffer_length = user_context_len_;
+ bind_[7].length = &user_context_len_;
} else {
- bind_[6].buffer_type = MYSQL_TYPE_NULL;
+ bind_[7].buffer_type = MYSQL_TYPE_NULL;
}
// dhcp4_subnet_id: INT UNSIGNED NULL
if (!subnet_id.unspecified()) {
subnet_id_ = subnet_id;
- bind_[7].buffer_type = MYSQL_TYPE_LONG;
- bind_[7].buffer = reinterpret_cast<char*>(subnet_id_);
- bind_[7].is_unsigned = MLM_TRUE;
+ bind_[8].buffer_type = MYSQL_TYPE_LONG;
+ bind_[8].buffer = reinterpret_cast<char*>(subnet_id_);
+ bind_[8].is_unsigned = MLM_TRUE;
} else {
- bind_[7].buffer_type = MYSQL_TYPE_NULL;
+ bind_[8].buffer_type = MYSQL_TYPE_NULL;
}
// host_id: INT UNSIGNED NOT NULL
host_id_ = host_id;
- bind_[8].buffer_type = MYSQL_TYPE_LONG;
- bind_[8].buffer = reinterpret_cast<char*>(&host_id_);
- bind_[8].is_unsigned = MLM_TRUE;
+ bind_[9].buffer_type = MYSQL_TYPE_LONG;
+ bind_[9].buffer = reinterpret_cast<char*>(&host_id_);
+ bind_[9].is_unsigned = MLM_TRUE;
} catch (const std::exception& ex) {
isc_throw(DbOperationError,
/// a client or only when requested.
bool persistent_;
+ /// @brief Boolean flag indicating if the option must be never returned
+ /// to a client.
+ bool cancelled_;
+
/// @brief User context.
std::string user_context_;
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
- "o4.persistent, o4.user_context, "
+ "o4.persistent, o4.cancelled, o4.user_context, "
"o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
- "o6.persistent, o6.user_context, "
+ "o6.persistent, o6.cancelled, o6.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o "
"ON h.host_id = o.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o "
"ON h.host_id = o.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context, "
+ "o.persistent, o.cancelled, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o "
"ON h.host_id = o.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context,"
+ "o.persistent, o.cancelled, o.user_context,"
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context, "
+ "o.persistent, o.cancelled, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o "
"ON h.host_id = o.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context, "
+ "o.persistent, o.cancelled, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
- "o4.persistent, o4.user_context, "
+ "o4.persistent, o4.cancelled, o4.user_context, "
"o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
- "o6.persistent, o6.user_context, "
+ "o6.persistent, o6.cancelled, o6.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o "
"ON h.host_id = o.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context, "
+ "o.persistent, o.cancelled, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM ( SELECT * FROM hosts AS h "
"WHERE h.dhcp4_subnet_id = ? AND h.host_id > ? "
"ORDER BY h.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context, "
+ "o.persistent, o.cancelled, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM ( SELECT * FROM hosts AS h "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context "
+ "o.persistent, o.cancelled, o.user_context "
"FROM ( SELECT * FROM hosts AS h "
"WHERE h.host_id > ? "
"ORDER BY h.host_id "
"h.dhcp4_next_server, h.dhcp4_server_hostname, "
"h.dhcp4_boot_file_name, h.auth_key, "
"o.option_id, o.code, o.value, o.formatted_value, o.space, "
- "o.persistent, o.user_context, "
+ "o.persistent, o.cancelled, o.user_context, "
"r.reservation_id, r.address, r.prefix_len, r.type, "
"r.dhcp6_iaid "
"FROM ( SELECT * FROM hosts AS h "
// Using fixed scope_id = 3, which associates an option with host.
{MySqlHostDataSourceImpl::INSERT_V4_HOST_OPTION,
"INSERT INTO dhcp4_options(option_id, code, value, formatted_value, space, "
- "persistent, user_context, dhcp4_subnet_id, host_id, scope_id) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
+ "persistent, cancelled, user_context, dhcp4_subnet_id, host_id, scope_id) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
// Inserts a single DHCPv6 option into 'dhcp6_options' table.
// Using fixed scope_id = 3, which associates an option with host.
{MySqlHostDataSourceImpl::INSERT_V6_HOST_OPTION,
"INSERT INTO dhcp6_options(option_id, code, value, formatted_value, space, "
- "persistent, user_context, dhcp6_subnet_id, host_id, scope_id) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
+ "persistent, cancelled, user_context, dhcp6_subnet_id, host_id, scope_id) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
// Delete IPv4 reservations by subnet id and reserved address.
{MySqlHostDataSourceImpl::DEL_HOST_ADDR4,
return (Optional<std::string>(name));
}
-std::string
+Optional<std::string>
OptionDataParser::extractData(ConstElementPtr parent) const {
std::string data;
try {
} catch (...) {
// The "data" parameter was not found. Return an empty value.
- return (data);
+ return (Optional<std::string>());
}
- return (data);
+ return (Optional<std::string>(data));
}
Optional<bool>
return (Optional<bool>(persist));
}
+Optional<bool>
+OptionDataParser::extractCancelled(ConstElementPtr parent) const {
+ bool cancel = false;
+ try {
+ cancel = getBoolean(parent, "never-send");
+
+ } catch (...) {
+ return (Optional<bool>());
+ }
+
+ return (Optional<bool>(cancel));
+}
+
OptionDefinitionPtr
OptionDataParser::findOptionDefinition(const std::string& option_space,
const Optional<uint32_t>& option_code,
Optional<std::string> name_param = extractName(option_data);
Optional<bool> csv_format_param = extractCSVFormat(option_data);
Optional<bool> persist_param = extractPersistent(option_data);
- std::string data_param = extractData(option_data);
+ Optional<bool> cancel_param = extractCancelled(option_data);
+ Optional<std::string> data_param = extractData(option_data);
std::string space_param = extractSpace(option_data);
ConstElementPtr user_context = option_data->get("user-context");
<< getPosition("name", option_data)
<< ")");
}
+ } else {
+ // Option name is specified it should match the name in the definition.
+ if (!name_param.unspecified() && (def->getName() != name_param.get())) {
+ isc_throw(DhcpConfigError, "specified option name '"
+ << name_param << "' does not match the "
+ << "option definition: '" << space_param
+ << "." << def->getName() << "' ("
+ << getPosition("name", option_data)
+ << ")");
+ }
+ }
+
+ // No data and cancelled is a supported special case.
+ if (!cancel_param.unspecified() && cancel_param &&
+ data_param.unspecified()) {
+ uint16_t code;
+ if (def) {
+ code = def->getCode();
+ } else {
+ code = static_cast<uint16_t>(code_param);
+ }
+ OptionPtr option(new Option(universe, code));
+ bool persistent = !persist_param.unspecified() && persist_param;
+ OptionDescriptor desc(option, persistent, true, "", user_context);
+ return (make_pair(desc, space_param));
}
// Transform string of hexadecimal digits into binary format.
}
}
- OptionDescriptor desc(false);
+ OptionDescriptor desc(false, false);
if (!def) {
// @todo We have a limited set of option definitions initialized at
desc.option_ = option;
desc.persistent_ = !persist_param.unspecified() && persist_param;
+ desc.cancelled_ = !cancel_param.unspecified() && cancel_param;
} else {
-
- // Option name is specified it should match the name in the definition.
- if (!name_param.unspecified() && (def->getName() != name_param.get())) {
- isc_throw(DhcpConfigError, "specified option name '"
- << name_param << "' does not match the "
- << "option definition: '" << space_param
- << "." << def->getName() << "' ("
- << getPosition("name", option_data)
- << ")");
- }
-
// Option definition has been found so let's use it to create
// an instance of our option.
try {
def->optionFactory(universe, def->getCode(), binary);
desc.option_ = option;
desc.persistent_ = !persist_param.unspecified() && persist_param;
+ desc.cancelled_ = !cancel_param.unspecified() && cancel_param;
if (use_csv) {
desc.formatted_value_ = data_param;
}
}
// All went good, so we can set the option space name.
- return make_pair(desc, space_param);
+ return (make_pair(desc, space_param));
}
// **************************** OptionDataListParser *************************
/// @param parent A data element holding full option data configuration.
/// @return Option data as a string. It will return empty string if
/// option data is unspecified.
- std::string extractData(data::ConstElementPtr parent) const;
+ util::Optional<std::string>
+ extractData(data::ConstElementPtr parent) const;
/// @brief Retrieves option space name.
///
/// @return Value of the persistent parameter, possibly unspecified.
util::Optional<bool> extractPersistent(data::ConstElementPtr parent) const;
+ /// @brief Retrieves cancelled/never-send parameter as an optional value.
+ ///
+ /// @return Value of the cancelled parameter, possibly unspecified.
+ util::Optional<bool> extractCancelled(data::ConstElementPtr parent) const;
+
/// @brief Address family: @c AF_INET or @c AF_INET6.
uint16_t address_family_;
{ "space", Element::string },
{ "csv-format", Element::boolean },
{ "always-send", Element::boolean },
+ { "never-send", Element::boolean },
{ "user-context", Element::map },
{ "comment", Element::string },
{ "metadata", Element::map }
const SimpleDefaults SimpleParser4::OPTION4_DEFAULTS = {
{ "space", Element::string, "dhcp4"}, // DHCP4_OPTION_SPACE
{ "csv-format", Element::boolean, "true"},
- { "always-send", Element::boolean, "false"}
+ { "always-send", Element::boolean, "false"},
+ { "never-send", Element::boolean, "false"}
};
/// @brief This table defines all subnet parameters for DHCPv4.
{ "space", Element::string },
{ "csv-format", Element::boolean },
{ "always-send", Element::boolean },
+ { "never-send", Element::boolean },
{ "user-context", Element::map },
{ "comment", Element::string },
{ "metadata", Element::map }
const SimpleDefaults SimpleParser6::OPTION6_DEFAULTS = {
{ "space", Element::string, "dhcp6"}, // DHCP6_OPTION_SPACE
{ "csv-format", Element::boolean, "true"},
- { "always-send", Element::boolean, "false"}
+ { "always-send", Element::boolean, "false"},
+ { "never-send", Element::boolean, "false"}
};
/// @brief This table defines all subnet parameters for DHCPv6.
private:
/// @brief Number of columns holding DHCPv4 or DHCPv6 option information.
- static const size_t OPTION_COLUMNS = 7;
+ static const size_t OPTION_COLUMNS = 8;
/// @brief Receives DHCPv4 or DHCPv6 options information from the
/// dhcp4_options or dhcp6_options tables respectively.
formatted_value_index_(start_column_ + 3),
space_index_(start_column_ + 4),
persistent_index_(start_column_ + 5),
- user_context_index_(start_column_ + 6),
+ cancelled_index_(start_column_ + 6),
+ user_context_index_(start_column_ + 7),
most_recent_option_id_(0) {
}
PgSqlExchange::getColumnValue(r, row, persistent_index_,
persistent);
+ // cancelled: BOOL default false
+ bool cancelled;
+ PgSqlExchange::getColumnValue(r, row, cancelled_index_,
+ cancelled);
+
// user_context: TEXT
std::string user_context;
if (!isColumnNull(r, row, user_context_index_)) {
}
}
- OptionDescriptor desc(option, persistent, formatted_value);
+ OptionDescriptor desc(option, persistent, cancelled,
+ formatted_value);
// Set the user context if there is one into the option descriptor.
if (!user_context.empty()) {
columns[formatted_value_index_] = "formatted_value";
columns[space_index_] = "space";
columns[persistent_index_] = "persistent";
+ columns[cancelled_index_] = "cancelled";
columns[user_context_index_] = "user_context";
}
/// @brief Persistent
size_t persistent_index_;
+
+ /// @brief Cancelled
+ size_t cancelled_index_;
//@}
/// @brief User context
static const int FORMATTED_VALUE_COL = 3;
static const int SPACE_COL = 4;
static const int PERSISTENT_COL = 5;
- static const int USER_CONTEXT_COL = 6;
- static const int DHCP_CLIENT_CLASS_COL = 7;
- static const int DHCP_SUBNET_ID_COL = 8;
- static const int HOST_ID_COL = 9;
- static const int SCOPE_ID_COL = 10;
+ static const int CANCELLED_COL = 6;
+ static const int USER_CONTEXT_COL = 7;
+ static const int DHCP_CLIENT_CLASS_COL = 8;
+ static const int DHCP_SUBNET_ID_COL = 9;
+ static const int HOST_ID_COL = 10;
+ static const int SCOPE_ID_COL = 11;
/// @brief Number of columns in the tables holding options.
- static const size_t OPTION_COLUMNS = 11;
+ static const size_t OPTION_COLUMNS = 12;
public:
columns_[FORMATTED_VALUE_COL] = "formatted_value";
columns_[SPACE_COL] = "space";
columns_[PERSISTENT_COL] = "persistent";
+ columns_[CANCELLED_COL] = "cancelled";
columns_[USER_CONTEXT_COL] = "user_context";
columns_[DHCP_CLIENT_CLASS_COL] = "dhcp_client_class";
columns_[DHCP_SUBNET_ID_COL] = "dhcp_subnet_id";
columns_[HOST_ID_COL] = "host_id";
columns_[SCOPE_ID_COL] = "scope_id";
- BOOST_STATIC_ASSERT(10 < OPTION_COLUMNS);
+ BOOST_STATIC_ASSERT(11 < OPTION_COLUMNS);
}
/// @brief Creates binding array to insert option data into database.
// persistent: BOOLEAN DEFAULT false
bind_array->add(opt_desc.persistent_);
+ // cancelled: BOOLEAN DEFAULT false
+ bind_array->add(opt_desc.cancelled_);
+
// user_context: TEXT NULL,
ConstElementPtr ctx = opt_desc.getContext();
if (ctx) {
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
- " o4.persistent, o4.user_context, "
+ " o4.persistent, o4.cancelled, o4.user_context, "
" o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
- " o6.persistent, o6.user_context, "
+ " o6.persistent, o6.cancelled, o6.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o4 ON h.host_id = o4.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
"WHERE ipv4_address = $1 "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
"WHERE h.dhcp4_subnet_id = $1 AND h.dhcp_identifier_type = $2 "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
"WHERE h.dhcp4_subnet_id = $1 AND h.ipv4_address = $2 "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, "
" r.dhcp6_iaid "
"FROM hosts AS h "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, "
" r.dhcp6_iaid "
"FROM hosts AS h "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
"WHERE h.dhcp4_subnet_id = $1 "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o4.option_id, o4.code, o4.value, o4.formatted_value, o4.space, "
- " o4.persistent, o4.user_context, "
+ " o4.persistent, o4.cancelled, o4.user_context, "
" o6.option_id, o6.code, o6.value, o6.formatted_value, o6.space, "
- " o6.persistent, o6.user_context, "
+ " o6.persistent, o6.cancelled, o6.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o4 ON h.host_id = o4.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM hosts AS h "
"LEFT JOIN dhcp4_options AS o ON h.host_id = o.host_id "
"WHERE lower(h.hostname) = $1 AND h.dhcp4_subnet_id = $2 "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM hosts AS h "
"LEFT JOIN dhcp6_options AS o ON h.host_id = o.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM ( SELECT * FROM hosts AS h "
" WHERE h.dhcp4_subnet_id = $1 AND h.host_id > $2 "
" ORDER BY h.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM ( SELECT * FROM hosts AS h "
" WHERE h.dhcp6_subnet_id = $1 AND h.host_id > $2 "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context "
+ " o.persistent, o.cancelled, o.user_context "
"FROM ( SELECT * FROM hosts AS h "
" WHERE h.host_id > $1 "
" ORDER BY h.host_id "
" h.dhcp4_next_server, h.dhcp4_server_hostname, "
" h.dhcp4_boot_file_name, h.auth_key, "
" o.option_id, o.code, o.value, o.formatted_value, o.space, "
- " o.persistent, o.user_context, "
+ " o.persistent, o.cancelled, o.user_context, "
" r.reservation_id, r.address, r.prefix_len, r.type, r.dhcp6_iaid "
"FROM ( SELECT * FROM hosts AS h "
" WHERE h.host_id > $1 "
// PgSqlHostDataSourceImpl::INSERT_V4_HOST_OPTION
// Inserts a single DHCPv4 option into 'dhcp4_options' table.
// Using fixed scope_id = 3, which associates an option with host.
- {7,
+ {8,
{ OID_INT2, OID_BYTEA, OID_TEXT,
- OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8 },
+ OID_VARCHAR, OID_BOOL, OID_BOOL, OID_TEXT, OID_INT8 },
"insert_v4_host_option",
"INSERT INTO dhcp4_options(code, value, formatted_value, space, "
- " persistent, user_context, host_id, scope_id) "
- "VALUES ($1, $2, $3, $4, $5, $6, $7, 3)"
+ " persistent, cancelled, user_context, host_id, scope_id) "
+ "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, 3)"
},
// PgSqlHostDataSourceImpl::INSERT_V6_HOST_OPTION
// Inserts a single DHCPv6 option into 'dhcp6_options' table.
// Using fixed scope_id = 3, which associates an option with host.
- {7,
+ {8,
{ OID_INT2, OID_BYTEA, OID_TEXT,
- OID_VARCHAR, OID_BOOL, OID_TEXT, OID_INT8 },
+ OID_VARCHAR, OID_BOOL, OID_BOOL, OID_TEXT, OID_INT8 },
"insert_v6_host_option",
"INSERT INTO dhcp6_options(code, value, formatted_value, space, "
- " persistent, user_context, host_id, scope_id) "
- "VALUES ($1, $2, $3, $4, $5, $6, $7, 3)"
+ " persistent, cancelled, user_context, host_id, scope_id) "
+ "VALUES ($1, $2, $3, $4, $5, $6, $7, $8, 3)"
},
// PgSqlHostDataSourceImpl::DEL_HOST_ADDR4
// Insert global options into the database.
OptionDescriptorPtr opt(new OptionDescriptor(createOption<OptionString>
(Option::V4, DHO_HOST_NAME,
- true, false, "new.example.com")));
+ true, false, false,
+ "new.example.com")));
opt->setId(1);
opt->space_name_ = DHCP4_OPTION_SPACE;
opt->setModificationTime(getTimestamp("dhcp4_options"));
opt.reset(new OptionDescriptor(createOption<OptionString>
(Option::V4, DHO_TFTP_SERVER_NAME,
- true, false, "tftp-my")));
+ true, false, false, "tftp-my")));
opt->setId(2);
opt->space_name_ = DHCP4_OPTION_SPACE;
opt->setModificationTime(getTimestamp("dhcp4_options"));
// Add a standard option to the class.
OptionPtr option = Option::create(Option::V4, DHO_BOOT_FILE_NAME);
- OptionDescriptorPtr desc = OptionDescriptor::create(option, true, "bogus-file.txt");
+ OptionDescriptorPtr desc = OptionDescriptor::create(option,
+ true,
+ false,
+ "bogus-file.txt");
desc->space_name_ = DHCP4_OPTION_SPACE;
desc->setModificationTime(getTimestamp("dhcp4_client_class"));
client_class->getCfgOption()->add(*desc, desc->space_name_);
// Add a custom option to the class.
option = Option::create(Option::V4, 201);
- desc = OptionDescriptor::create(option, true, "custom-stuff");
+ desc = OptionDescriptor::create(option, true, false, "custom-stuff");
desc->space_name_ = "isc";
desc->setModificationTime(getTimestamp("dhcp4_client_class"));
client_class->getCfgOption()->add(*desc, desc->space_name_);
// Insert global options into the database.
OptionDescriptorPtr opt(new OptionDescriptor(createOption<OptionString>
(Option::V6, D6O_BOOTFILE_URL,
- true, false, "some.bootfile")));
+ true, false, false,
+ "some.bootfile")));
opt->setId(1);
opt->space_name_ = DHCP6_OPTION_SPACE;
opt->setModificationTime(getTimestamp("dhcp6_options"));
opt.reset(new OptionDescriptor(createOption<OptionString>
(Option::V6, D6O_AFTR_NAME,
- true, true, "some.example.com")));
+ true, true, true,
+ "some.example.com")));
opt->setId(2);
opt->space_name_ = DHCP6_OPTION_SPACE;
opt->setModificationTime(getTimestamp("dhcp6_options"));
// Add an option to the class.
OptionPtr option = Option::create(Option::V6, D6O_BOOTFILE_URL);
- OptionDescriptorPtr desc = OptionDescriptor::create(option, true, "client.boot.url");
+ OptionDescriptorPtr desc = OptionDescriptor::create(option, true,
+ false,
+ "client.boot.url");
desc->space_name_ = DHCP6_OPTION_SPACE;
desc->setModificationTime(getTimestamp("dhcp6_client_class"));
client_class->getCfgOption()->add(*desc, desc->space_name_);
OptionPtr option = Option::create(Option::V4, 234);
ElementPtr context = Element::createMap();
context->set("name", Element::create("value"));
- auto desc = OptionDescriptor::create(option, true, "value", context);
+ auto desc = OptionDescriptor::create(option, true, true, "value", context);
ASSERT_TRUE(desc);
EXPECT_EQ(option, desc->option_);
EXPECT_TRUE(desc->persistent_);
+ EXPECT_TRUE(desc->cancelled_);
EXPECT_EQ("value", desc->formatted_value_);
EXPECT_EQ(context, desc->getContext());
}
// This test verifies that the OptionDescriptor factory function variant
// taking persistent flag as an argument creates valid instance.
TEST(OptionDescriptorTest, createPersistent) {
- auto desc = OptionDescriptor::create(true);
+ auto desc = OptionDescriptor::create(true, true);
ASSERT_TRUE(desc);
EXPECT_FALSE(desc->option_);
EXPECT_TRUE(desc->persistent_);
+ EXPECT_TRUE(desc->cancelled_);
EXPECT_TRUE(desc->formatted_value_.empty());
EXPECT_FALSE(desc->getContext());
}
OptionPtr option = Option::create(Option::V4, 234);
ElementPtr context = Element::createMap();
context->set("name", Element::create("value"));
- auto desc = OptionDescriptor::create(option, true, "value", context);
+ auto desc = OptionDescriptor::create(option, true, true, "value", context);
auto desc_copy = OptionDescriptor::create(*desc);
ASSERT_TRUE(desc_copy);
ASSERT_TRUE(desc_copy);
EXPECT_EQ(option, desc_copy->option_);
EXPECT_TRUE(desc_copy->persistent_);
+ EXPECT_TRUE(desc_copy->cancelled_);
EXPECT_EQ("value", desc_copy->formatted_value_);
EXPECT_EQ(context, desc_copy->getContext());
}
// does the shallow copy.
TEST(OptionDescriptorTest, assign) {
// Create a persistent option descriptor.
- auto desc = OptionDescriptor::create(true);
+ auto desc = OptionDescriptor::create(true, true);
ASSERT_TRUE(desc);
// Create another option descriptor.
OptionPtr option = Option::create(Option::V4, 234);
ElementPtr context = Element::createMap();
context->set("name", Element::create("value"));
- auto desc1 = OptionDescriptor::create(option, true, "value", context);
+ auto desc1 = OptionDescriptor::create(option, false, false, "value",
+ context);
ASSERT_TRUE(desc1);
// Assign the option descriptor.
// Check it.
ASSERT_TRUE(desc);
EXPECT_EQ(option, desc->option_);
- EXPECT_TRUE(desc->persistent_);
+ EXPECT_FALSE(desc->persistent_);
+ EXPECT_FALSE(desc->cancelled_);
EXPECT_EQ("value", desc->formatted_value_);
EXPECT_EQ(context, desc->getContext());
}
// In order to easier identify the options by id, let's use the option
// code as the id.
- ASSERT_NO_THROW(cfg.add(option, false, DHCP6_OPTION_SPACE,
+ ASSERT_NO_THROW(cfg.add(option, false, false, DHCP6_OPTION_SPACE,
static_cast<uint64_t>(code)));
}
OptionUint16Ptr option = OptionUint16Ptr(new OptionUint16(Option::V6,
code, 2345));
option->setEncapsulatedSpace("bar");
- ASSERT_NO_THROW(cfg.add(option, false, DHCP6_OPTION_SPACE,
+ ASSERT_NO_THROW(cfg.add(option, false, false, DHCP6_OPTION_SPACE,
static_cast<uint64_t>(code)));
}
OptionUint8Ptr option = OptionUint8Ptr(new OptionUint8(Option::V6, code,
0x01));
option->setEncapsulatedSpace("foo-subs");
- ASSERT_NO_THROW(cfg.add(option, false, "foo", static_cast<uint64_t>(code)));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "foo",
+ static_cast<uint64_t>(code)));
}
// Create sub-options belonging to "bar" option space and encapsulating
OptionUint8Ptr option = OptionUint8Ptr(new OptionUint8(Option::V6,
code, 0x02));
option->setEncapsulatedSpace("bar-subs");
- ASSERT_NO_THROW(cfg.add(option, false, "bar", static_cast<uint64_t>(code)));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "bar",
+ static_cast<uint64_t>(code)));
}
// Create sub-options belonging to "foo-subs" option space.
for (uint16_t code = 1; code < 10; ++code) {
OptionUint8Ptr option = OptionUint8Ptr(new OptionUint8(Option::V6, code,
0x03));
- ASSERT_NO_THROW(cfg.add(option, false, "foo-subs",
+ ASSERT_NO_THROW(cfg.add(option, false, false, "foo-subs",
static_cast<uint64_t>(code)));
}
for (uint16_t code = 501; code < 510; ++code) {
OptionUint8Ptr option = OptionUint8Ptr(new OptionUint8(Option::V6,
code, 0x04));
- ASSERT_NO_THROW(cfg.add(option, false, "bar-subs",
+ ASSERT_NO_THROW(cfg.add(option, false, false, "bar-subs",
static_cast<uint64_t>(code)));
}
}
// Add an option to each configuration
OptionPtr option(new Option(Option::V6, 1));
- ASSERT_NO_THROW(cfg1.add(option, false, DHCP6_OPTION_SPACE));
- ASSERT_NO_THROW(cfg2.add(option, true, "isc"));
+ ASSERT_NO_THROW(cfg1.add(option, false, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg2.add(option, true, true, "isc"));
// The first option configuration has an option
ASSERT_FALSE(cfg1.empty());
// option code and content.
for (uint16_t code = 1; code < 10; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, code)));
- ASSERT_NO_THROW(cfg1.add(option, false, "isc"));
- ASSERT_NO_THROW(cfg1.add(option, true, "vendor-123"));
+ ASSERT_NO_THROW(cfg1.add(option, false, false, "isc"));
+ ASSERT_NO_THROW(cfg1.add(option, true, true, "vendor-123"));
}
// Configurations should now be different.
// spaces.
for (uint16_t code = 2; code < 10; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, code)));
- ASSERT_NO_THROW(cfg2.add(option, false, "isc"));
- ASSERT_NO_THROW(cfg2.add(option, true, "vendor-123"));
+ ASSERT_NO_THROW(cfg2.add(option, false, false, "isc"));
+ ASSERT_NO_THROW(cfg2.add(option, true, true, "vendor-123"));
}
// Configurations should still be unequal.
// Add missing option to the option space isc.
ASSERT_NO_THROW(cfg2.add(OptionPtr(new Option(Option::V6, 1,
OptionBuffer(10, 0x01))),
- false, "isc"));
+ false, false, "isc"));
// Configurations should still be unequal because option with code 1
// is missing in the option space vendor-123.
ASSERT_FALSE(cfg1 == cfg2);
// Add missing option.
ASSERT_NO_THROW(cfg2.add(OptionPtr(new Option(Option::V6, 1,
OptionBuffer(10, 0x01))),
- true, "vendor-123"));
+ true, true, "vendor-123"));
// Configurations should now be equal.
ASSERT_TRUE(cfg1 == cfg2);
ASSERT_FALSE(cfg1 != cfg2);
-
}
// This test verifies that multiple options can be added to the configuration
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg.add(option, false, false, DHCP6_OPTION_SPACE));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp6 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "isc"));
}
// Get options from the Subnet and check if all 10 are there.
// Let's add some options to the config to the config.
OptionStringPtr option(new OptionString(Option::V6, 1, "one"));
- ASSERT_NO_THROW(cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "isc"));
option.reset(new OptionString(Option::V6, 2, "two"));
- ASSERT_NO_THROW(cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "isc"));
option.reset(new OptionString(Option::V6, 3, "three"));
- ASSERT_NO_THROW(cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "isc"));
// Now let's make sure we can find them and they are as expected.
OptionDescriptor desc = cfg.get("isc", 1);
// from the range of 100 to 109 and holding one byte of data equal to 0xFF.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0xFF)));
- ASSERT_NO_THROW(cfg_src.add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg_src.add(option, false, false, DHCP6_OPTION_SPACE));
}
// Create collection of options in vendor space 123, with option codes
// from the range of 100 to 109 and holding one byte of data equal to 0xFF.
for (uint16_t code = 100; code < 110; code += 2) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0xFF)));
- ASSERT_NO_THROW(cfg_src.add(option, false, "vendor-123"));
+ ASSERT_NO_THROW(cfg_src.add(option, false, false, "vendor-123"));
}
// Create destination configuration (configuration that we merge the
// 100 to 108.
for (uint16_t code = 100; code < 110; code += 2) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0x01)));
- ASSERT_NO_THROW(cfg_dst.add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg_dst.add(option, false, false, DHCP6_OPTION_SPACE));
}
// Create collection of options having odd option codes in the range of
// 101 to 109.
for (uint16_t code = 101; code < 110; code += 2) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0x01)));
- ASSERT_NO_THROW(cfg_dst.add(option, false, "vendor-123"));
+ ASSERT_NO_THROW(cfg_dst.add(option, false, false, "vendor-123"));
}
// Merge source configuration to the destination configuration. The options
// Add 10 options to the custom option space in the source configuration.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0x01)));
- ASSERT_NO_THROW(cfg_src.add(option, false, "foo"));
+ ASSERT_NO_THROW(cfg_src.add(option, false, false, "foo"));
}
CfgOption cfg_dst;
// Add 20 options to the custom option space in destination configuration.
for (uint16_t code = 100; code < 120; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0xFF)));
- ASSERT_NO_THROW(cfg_dst.add(option, false, "isc"));
+ ASSERT_NO_THROW(cfg_dst.add(option, false, false, "isc"));
}
// Copy entire configuration to the destination. This should override any
// Create our existing config, that gets merged into.
OptionPtr option(new Option(Option::V4, 1, OptionBuffer(1, 0x01)));
- ASSERT_NO_THROW(this_cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(this_cfg.add(option, false, false, "isc"));
// Add option 3 to "fluff"
option.reset(new Option(Option::V4, 3, OptionBuffer(1, 0x03)));
- ASSERT_NO_THROW(this_cfg.add(option, false, "fluff"));
+ ASSERT_NO_THROW(this_cfg.add(option, false, false, "fluff"));
// Add option 4 to "fluff".
option.reset(new Option(Option::V4, 4, OptionBuffer(1, 0x04)));
- ASSERT_NO_THROW(this_cfg.add(option, false, "fluff"));
+ ASSERT_NO_THROW(this_cfg.add(option, false, false, "fluff"));
// Create our other config that will be merged from.
// Add Option 1 to "isc", this should "overwrite" the original.
option.reset(new Option(Option::V4, 1, OptionBuffer(1, 0x10)));
- ASSERT_NO_THROW(other_cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(other_cfg.add(option, false, false, "isc"));
// Add option 2 to "isc".
option.reset(new Option(Option::V4, 2, OptionBuffer(1, 0x20)));
- ASSERT_NO_THROW(other_cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(other_cfg.add(option, false, false, "isc"));
// Add option 4 to "isc".
option.reset(new Option(Option::V4, 4, OptionBuffer(1, 0x40)));
- ASSERT_NO_THROW(other_cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(other_cfg.add(option, false, false, "isc"));
// Merge source configuration to the destination configuration. The options
// in the destination should be preserved. The options from the source
// Create our other config that will be merged from.
// Add an option without a formatted value.
OptionPtr option(new Option(Option::V4, 1, OptionBuffer(1, 0x01)));
- ASSERT_NO_THROW(other_cfg.add(option, false, "isc"));
+ ASSERT_NO_THROW(other_cfg.add(option, false, false, "isc"));
// Add an option with a formatted value.
option.reset(new Option(Option::V4, 2));
- OptionDescriptor desc(option, false, "one,two,three");
+ OptionDescriptor desc(option, false, false, "one,two,three");
ASSERT_NO_THROW(other_cfg.add(desc, "isc"));
// When we attempt to merge, it should fail, recognizing that
std::string value = "v4.example.com";
OptionPtr option(new Option(Option::V6, DHO_HOST_NAME));
option->setData(value.begin(), value.end());
- OptionDescriptorPtr desc(new OptionDescriptor(option, false));
+ OptionDescriptorPtr desc(new OptionDescriptor(option, false, false));
bool updated = false;
ASSERT_NO_THROW(updated = CfgOption::createDescriptorOption(defs, space, *desc));
{ 2, 'v', '6', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
option.reset(new Option(Option::V6, D6O_AFTR_NAME));
option->setData(fqdn.begin(), fqdn.end());
- desc.reset(new OptionDescriptor(option, false));
+ desc.reset(new OptionDescriptor(option, false, false));
ASSERT_NO_THROW(updated = CfgOption::createDescriptorOption(defs, space, *desc));
ASSERT_TRUE(updated);
space = "vendor-4491";
value = "192.0.2.1, 192.0.2.2";
option.reset(new Option(Option::V4, 2));
- desc.reset(new OptionDescriptor(option, false, value));
+ desc.reset(new OptionDescriptor(option, false, false, value));
ASSERT_NO_THROW(updated = CfgOption::createDescriptorOption(defs, space, *desc));
ASSERT_TRUE(updated);
// Now, a user defined uint8 option
space = "isc";
option.reset(new Option(Option::V4, 1, OptionBuffer(1, 0x77)));
- desc.reset(new OptionDescriptor(option, false));
+ desc.reset(new OptionDescriptor(option, false, false));
ASSERT_NO_THROW(updated = CfgOption::createDescriptorOption(defs, space, *desc));
ASSERT_TRUE(updated);
// Now, a user defined array of ints from a formatted value
option.reset(new Option(Option::V4, 2));
- desc.reset(new OptionDescriptor(option, false, "1,2,3"));
+ desc.reset(new OptionDescriptor(option, false, false, "1,2,3"));
ASSERT_NO_THROW(updated = CfgOption::createDescriptorOption(defs, space, *desc));
ASSERT_TRUE(updated);
// Finally, a generic, undefined option
option.reset(new Option(Option::V4, 199, OptionBuffer(1, 0x77)));
- desc.reset(new OptionDescriptor(option, false));
+ desc.reset(new OptionDescriptor(option, false, false));
ASSERT_NO_THROW(updated = CfgOption::createDescriptorOption(defs, space, *desc));
ASSERT_FALSE(updated);
// Because we called "encapsulate", this option should have been
// propagated to the options encapsulating option space "foo".
for (uint16_t code = 1000; code < 1020; ++code) {
- OptionDescriptor top_level_option(false);
+ OptionDescriptor top_level_option(false, false);
ASSERT_NO_THROW(top_level_option = cfg.get(DHCP6_OPTION_SPACE, code));
// Make sure that the option with code 5 is there.
ASSERT_TRUE(top_level_option.option_);
// Iterate over the options encapsulating "foo" option space. Make sure
// that the option with code 5 is no longer encapsulated by these options.
for (uint16_t code = 1000; code < 1020; ++code) {
- OptionDescriptor top_level_option(false);
+ OptionDescriptor top_level_option(false, false);
ASSERT_NO_THROW(top_level_option = cfg.get(DHCP6_OPTION_SPACE, code));
ASSERT_TRUE(top_level_option.option_);
EXPECT_FALSE(top_level_option.option_->getOption(5));
// Create multiple vendor options for vendor id 123.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, "vendor-123", static_cast<uint64_t>(code)));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "vendor-123",
+ static_cast<uint64_t>(code)));
}
// Delete options with id of 100. It includes both regular options and
// Create multiple vendor options for vendor id 123.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, "vendor-123"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "vendor-123"));
}
// Create multiple vendor options for vendor id 234.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(1, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, "vendor-234"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "vendor-234"));
}
// Make sure that the option we're trying to delete is there.
// Add 10 options to a "dhcp6" option space in the subnet.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg.add(option, false, false, DHCP6_OPTION_SPACE));
}
// Check that we can get each added option descriptor using
// Add twice 10 options to a "dhcp4" option space in the subnet.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg.add(option, false, false, DHCP4_OPTION_SPACE));
OptionPtr option2(new Option(Option::V4, code, OptionBuffer(10, 0xEE)));
- ASSERT_NO_THROW(cfg.add(option2, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg.add(option2, false, false, DHCP4_OPTION_SPACE));
}
// Check that we can get each added option descriptors.
// Add twice 10 options to a "dhcp4" option space in the subnet.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, vendor_space));
+ ASSERT_NO_THROW(cfg.add(option, false, false, vendor_space));
OptionPtr option2(new Option(Option::V4, code, OptionBuffer(10, 0xEE)));
- ASSERT_NO_THROW(cfg.add(option2, false, vendor_space));
+ ASSERT_NO_THROW(cfg.add(option2, false, false, vendor_space));
}
// Check that we can get each added option descriptors.
// In the inner loop we create options with unique codes (100-109).
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg.add(option, false, false, DHCP6_OPTION_SPACE));
}
}
// and options with these codes will be flagged non-persistent.
// Options with other codes will be flagged persistent.
bool persistent = (code % 3) ? true : false;
- ASSERT_NO_THROW(cfg.add(option, persistent, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(cfg.add(option, persistent, true, DHCP6_OPTION_SPACE));
}
// Get added options from the subnet.
ASSERT_EQ(3, distance(range_non_persistent.first, range_non_persistent.second));
}
+// This test verifies that the option with the cancellation flag can be
+// added to the configuration and that options with the cancellation flags
+// can be retrieved.
+TEST(Subnet6Test, addCancelledOption) {
+ CfgOption cfg;
+
+ // Add 10 options to the subnet with option codes 100 - 109.
+ for (uint16_t code = 100; code < 110; ++code) {
+ OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
+ // We create 10 options and want some of them to be flagged
+ // cancelled and some non-cancelled. Cancelled options are
+ // those that server must never send to clients.
+ // We pick 3 out of 10 options and mark them
+ // non-cancelled and 7 other options cancelled.
+ // Code values: 102, 105 and 108 are divisible by 3
+ // and options with these codes will be flagged non-cancelled.
+ // Options with other codes will be flagged cancelled.
+ bool cancelled = (code % 3) ? true : false;
+ ASSERT_NO_THROW(cfg.add(option, true, cancelled, DHCP6_OPTION_SPACE));
+ }
+
+ // Get added options from the subnet.
+ OptionContainerPtr options = cfg.getAll(DHCP6_OPTION_SPACE);
+
+ // options->get<2> returns reference to container index #5. This
+ // index is used to access options by the 'cancelled' flag.
+ OptionContainerCancelIndex& idx = options->get<5>();
+
+ // Get all cancelled options->
+ OptionContainerCancelRange range_cancelled = idx.equal_range(true);
+ // 7 out of 10 options have been flagged cancelled.
+ ASSERT_EQ(7, distance(range_cancelled.first, range_cancelled.second));
+
+ // Get all non-cancelled options->
+ OptionContainerCancelRange range_non_cancelled = idx.equal_range(false);
+ // 3 out of 10 options have been flagged not cancelled.
+ ASSERT_EQ(3, distance(range_non_cancelled.first, range_non_cancelled.second));
+}
+
// This test verifies that the vendor option can be added to the configuration.
TEST_F(CfgOptionTest, addVendorOptions) {
CfgOption cfg;
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, "vendor-12345678"));
+ ASSERT_NO_THROW(cfg.add(option, false, false, "vendor-12345678"));
}
// Second option space uses corner case value for vendor id = max uint8.
// with option codes that we have added to dhcp6 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(cfg.add(option, false, option_space.str()));
+ ASSERT_NO_THROW(cfg.add(option, false, false, option_space.str()));
}
// Get options from the Subnet and check if all 10 are there.
// Generate space name for a unique vendor id.
std::ostringstream s;
s << "vendor-" << code;
- ASSERT_NO_THROW(cfg.add(option, false, s.str()));
+ ASSERT_NO_THROW(cfg.add(option, false, false, s.str()));
}
// We should now have 10 different vendor ids.
// Add some options.
OptionPtr opt1(new Option(Option::V6, 100, OptionBuffer(4, 0x12)));
- cfg.add(opt1, false, "dns");
+ cfg.add(opt1, false, true, "dns");
OptionPtr opt2(new Option(Option::V6, 101, OptionBuffer(4, 12)));
- OptionDescriptor desc2(opt2, false, "12, 12, 12, 12");
+ OptionDescriptor desc2(opt2, false, true, "12, 12, 12, 12");
std::string ctx = "{ \"comment\": \"foo\", \"bar\": 1 }";
desc2.setContext(data::Element::fromJSON(ctx));
cfg.add(desc2, "dns");
OptionPtr opt3(new Option(Option::V6, D6O_STATUS_CODE, OptionBuffer(2, 0)));
- cfg.add(opt3, false, DHCP6_OPTION_SPACE);
+ cfg.add(opt3, false, false, DHCP6_OPTION_SPACE);
OptionPtr opt4(new Option(Option::V6, 100, OptionBuffer(4, 0x21)));
- cfg.add(opt4, true, "vendor-1234");
+ cfg.add(opt4, true, true, "vendor-1234");
+ OptionPtr opt5(new Option(Option::V6, 111));
+ cfg.add(opt5, false, true, "vendor-5678");
// Unparse
std::string expected = "[\n"
" \"space\": \"dns\",\n"
" \"csv-format\": false,\n"
" \"data\": \"12121212\",\n"
- " \"always-send\": false\n"
+ " \"always-send\": false,\n"
+ " \"never-send\": true\n"
"},{\n"
" \"code\": 101,\n"
" \"space\": \"dns\",\n"
" \"csv-format\": true,\n"
" \"data\": \"12, 12, 12, 12\",\n"
" \"always-send\": false,\n"
+ " \"never-send\": true,\n"
" \"user-context\": { \"comment\": \"foo\", \"bar\": 1 }\n"
"},{\n"
" \"code\": 13,\n"
" \"space\": \"dhcp6\",\n"
" \"csv-format\": false,\n"
" \"data\": \"0000\",\n"
- " \"always-send\": false\n"
+ " \"always-send\": false,\n"
+ " \"never-send\": false\n"
"},{\n"
" \"code\": 100,\n"
" \"space\": \"vendor-1234\",\n"
" \"csv-format\": false,\n"
" \"data\": \"21212121\",\n"
- " \"always-send\": true\n"
+ " \"always-send\": true,\n"
+ " \"never-send\": true\n"
+ "},{\n"
+ " \"code\": 111,\n"
+ " \"space\": \"vendor-5678\",\n"
+ " \"always-send\": false,\n"
+ " \"never-send\": true\n"
"}]\n";
isc::test::runToElementTest<CfgOption>(expected, cfg);
}
std::string value("Yay!");
OptionPtr option(new Option(Option::V4, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(network1b->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(network1b->getCfgOption()->add(option, false, false, "isc"));
ASSERT_NO_THROW(network1b->add(subnet4));
// Network2 we will not touch.
std::string value("Yay!");
OptionPtr option(new Option(Option::V6, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(network1b->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(network1b->getCfgOption()->add(option, false, false, "isc"));
ASSERT_NO_THROW(network1b->add(subnet4));
// Network2 we will not touch.
std::string value("Yay!");
OptionPtr option(new Option(Option::V4, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(subnet1b->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(subnet1b->getCfgOption()->add(option, false, false, "isc"));
// subnet 3b updates subnet 3 with different ID and removes it
// from network 2
value = "Team!";
option.reset(new Option(Option::V4, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(subnet3b->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(subnet3b->getCfgOption()->add(option, false, false, "isc"));
// subnet 4b updates subnet 4 and moves it from network2 to network 1
Subnet4Ptr subnet4b(new Subnet4(IOAddress("192.0.4.0"),
value = "POOLS";
option.reset(new Option(Option::V4, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false, "isc"));
subnet5->addPool(pool);
// Add pool 2
value ="RULE!";
option.reset(new Option(Option::V4, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false, "isc"));
subnet5->addPool(pool);
// Add subnets to the merge from config.
OptionCustomPtr opt_server_id(new OptionCustom(*def, Option::V4));
opt_server_id->writeAddress(IOAddress("1.2.3.4"));
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3, 100));
- subnet->getCfgOption()->add(opt_server_id, false, DHCP4_OPTION_SPACE);
+ subnet->getCfgOption()->add(opt_server_id, false, false,
+ DHCP4_OPTION_SPACE);
cfg.add(subnet);
EXPECT_TRUE(cfg.hasSubnetWithServerId(IOAddress("1.2.3.4")));
std::string value("Yay!");
OptionPtr option(new Option(Option::V6, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(subnet1b->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(subnet1b->getCfgOption()->add(option, false, false, "isc"));
// subnet 3b updates subnet 3 with different UD and removes it
// from network 2
value = "Team!";
option.reset(new Option(Option::V6, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(subnet3b->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(subnet3b->getCfgOption()->add(option, false, false, "isc"));
// subnet 4b updates subnet 4 and moves it from network2 to network 1
Subnet6Ptr subnet4b(new Subnet6(IOAddress("2001:4::"),
value = "POOLS";
option.reset(new Option(Option::V6, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false, "isc"));
subnet5->addPool(pool);
// Add pool 2
value ="RULE!";
option.reset(new Option(Option::V6, 1));
option->setData(value.begin(), value.end());
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false, "isc"));
subnet5->addPool(pool);
// Add subnets to the merge from config.
auto cfg_option = boost::make_shared<CfgOption>();
auto option = boost::make_shared<Option>(Option::V6, 1024);
- cfg_option->add(option, false, DHCP6_OPTION_SPACE);
+ cfg_option->add(option, false, false, DHCP6_OPTION_SPACE);
auto option_def = boost::make_shared<OptionDefinition>("foo", 1024, "dhcp6", "empty");
CfgOptionDefPtr cfg_option_def = boost::make_shared<CfgOptionDef>();
OptionPtr option;
test_options.reset(new CfgOption());
option.reset(new Option(Option::V4, 17, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP4_OPTION_SPACE));
option.reset(new Option(Option::V6, 101, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, "isc"));
+ ASSERT_NO_THROW(test_options->add(option, false, false, "isc"));
option.reset(new Option(Option::V6, 100, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP6_OPTION_SPACE));
// Now remake the client class with cfg_option
ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr, test_options)));
OptionPtr option;
test_options.reset(new CfgOption());
option.reset(new Option(Option::V4, 17, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP4_OPTION_SPACE));
// Now remake the client class with cfg_option
ASSERT_NO_THROW(cclass.reset(new ClientClassDef("class_one", expr,
// Make a class that with same name and expression, but different options
// verify that the equality tools reflect that the classes are not equal.
option.reset(new Option(Option::V4, 20, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP4_OPTION_SPACE));
ASSERT_NO_THROW(cclass2.reset(new ClientClassDef("class_one", expr,
test_options)));
EXPECT_FALSE(cclass->equals(*cclass2));
// Make some options for the second class.
cfg_option.reset(new CfgOption());
OptionPtr option = Option::create(Option::V4, DHO_BOOT_FILE_NAME);
- OptionDescriptorPtr desc = OptionDescriptor::create(option, true, "bogus-file.txt");
+ OptionDescriptorPtr desc = OptionDescriptor::create(option, true, false,
+ "bogus-file.txt");
desc->space_name_ = DHCP4_OPTION_SPACE;
cfg_option->add(*desc, desc->space_name_);
option = Option::create(Option::V4, DHO_TFTP_SERVER_NAME);
- desc = OptionDescriptor::create(option, true, "bogus-tftp-server");
+ desc = OptionDescriptor::create(option, true, false, "bogus-tftp-server");
desc->space_name_ = DHCP4_OPTION_SPACE;
cfg_option->add(*desc, desc->space_name_);
auto cfg_option = boost::make_shared<CfgOption>();
auto option = boost::make_shared<Option>(Option::V6, 1024);
- cfg_option->add(option, false, DHCP6_OPTION_SPACE);
+ cfg_option->add(option, false, false, DHCP6_OPTION_SPACE);
auto option_def = boost::make_shared<OptionDefinition>("foo", 1024, "dhcp6", "empty");
CfgOptionDefPtr cfg_option_def = boost::make_shared<CfgOptionDef>();
OptionPtr option;
test_options.reset(new CfgOption());
option.reset(new Option(Option::V4, 17, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP4_OPTION_SPACE));
option.reset(new Option(Option::V6, 101, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, "isc"));
+ ASSERT_NO_THROW(test_options->add(option, false, false, "isc"));
option.reset(new Option(Option::V6, 100, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP6_OPTION_SPACE));
// Now remake the client class with cfg_option
ASSERT_NO_THROW(cclass.reset(new ClientClassDef(name, expr, test_options)));
OptionPtr option;
test_options.reset(new CfgOption());
option.reset(new Option(Option::V4, 17, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP4_OPTION_SPACE));
// Now remake the client class with cfg_option
ASSERT_NO_THROW(cclass.reset(new TemplateClientClassDef("class_one", expr,
// Make a class that with same name and expression, but different options
// verify that the equality tools reflect that the classes are not equal.
option.reset(new Option(Option::V4, 20, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(test_options->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(test_options->add(option, false, false,
+ DHCP4_OPTION_SPACE));
ASSERT_NO_THROW(cclass2.reset(new TemplateClientClassDef("class_one", expr,
test_options)));
EXPECT_FALSE(cclass->equals(*cclass2));
// Make some options for the second class.
cfg_option.reset(new CfgOption());
OptionPtr option = Option::create(Option::V4, DHO_BOOT_FILE_NAME);
- OptionDescriptorPtr desc = OptionDescriptor::create(option, true, "bogus-file.txt");
+ OptionDescriptorPtr desc = OptionDescriptor::create(option, true, false,
+ "bogus-file.txt");
desc->space_name_ = DHCP4_OPTION_SPACE;
cfg_option->add(*desc, desc->space_name_);
option = Option::create(Option::V4, DHO_TFTP_SERVER_NAME);
- desc = OptionDescriptor::create(option, true, "bogus-tftp-server");
+ desc = OptionDescriptor::create(option, true, false, "bogus-tftp-server");
desc->space_name_ = DHCP4_OPTION_SPACE;
cfg_option->add(*desc, desc->space_name_);
const SimpleDefaults ParseConfigTest::OPTION6_DEFAULTS = {
{ "space", Element::string, "dhcp6"},
{ "csv-format", Element::boolean, "true"},
- { "always-send", Element::boolean,"false"}
+ { "always-send", Element::boolean,"false"},
+ { "never-send", Element::boolean,"false"}
};
/// This table defines default values for options in DHCPv4
const SimpleDefaults ParseConfigTest::OPTION4_DEFAULTS = {
{ "space", Element::string, "dhcp4"},
{ "csv-format", Element::boolean, "true"},
- { "always-send", Element::boolean, "false"}
+ { "always-send", Element::boolean, "false"},
+ { "never-send", Element::boolean, "false"}
};
/// This table defines default values for both DHCPv4 and DHCPv6
"\"csv-format\": true,"
"\"space\": \"dhcp4\","
"\"data\": \"172.16.15.23\","
- "\"always-send\": false"
+ "\"always-send\": false,"
+ "\"never-send\": false"
"},"
"{"
"\"name\": \"default-ip-ttl\","
option->set("space", Element::create(std::string(DHCP4_OPTION_SPACE)));
option->set("csv-format", Element::create(true));
option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
option = config_element->get("option-data")->getNonConst(1);
option = config_element->get("option-data")->getNonConst(2);
option->set("code", Element::create(DHO_DEFAULT_IP_TTL));
option->set("space", Element::create(std::string(DHCP4_OPTION_SPACE)));
option->set("csv-format", Element::create(true));
option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
ElementPtr expected = Element::createList();
expected->add(config_element);
"\"csv-format\": true,"
"\"space\": \"dhcp6\","
"\"data\": \"2001:db8:1::1204\","
- "\"always-send\": true"
+ "\"always-send\": true,"
+ "\"never-send\": true"
"},"
"{"
"\"name\": \"preference\","
option->set("space", Element::create(std::string(DHCP6_OPTION_SPACE)));
option->set("csv-format", Element::create(true));
option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
option = config_element->get("option-data")->getNonConst(1);
option = config_element->get("option-data")->getNonConst(2);
option->set("code", Element::create(D6O_PREFERENCE));
option->set("space", Element::create(std::string(DHCP6_OPTION_SPACE)));
option->set("csv-format", Element::create(true));
option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
config = prettyPrint(config_element);
boost::algorithm::to_lower(config);
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(host.getCfgOption4()->add(option, false, DHCP4_OPTION_SPACE));
+ ASSERT_NO_THROW(host.getCfgOption4()->add(option, false, false,
+ DHCP4_OPTION_SPACE));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp4 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(host.getCfgOption4()->add(option, false, "isc"));
+ ASSERT_NO_THROW(host.getCfgOption4()->add(option, false, false, "isc"));
}
// Get options from the Subnet and check if all 10 are there.
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(host.getCfgOption6()->add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(host.getCfgOption6()->add(option, false, false,
+ DHCP6_OPTION_SPACE));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp6 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(host.getCfgOption6()->add(option, false, "isc"));
+ ASSERT_NO_THROW(host.getCfgOption6()->add(option, false, false, "isc"));
}
// Get options from the Subnet and check if all 10 are there.
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "dhcp4"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false,
+ "dhcp4"));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp4 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V4, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false, "isc"));
}
// Get options from the pool and check if all 10 are there.
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "dhcp6"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false,
+ "dhcp6"));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp6 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(pool->getCfgOption()->add(option, false, false, "isc"));
}
// Get options from the pool and check if all 10 are there.
// Add an option.
OptionPtr option(new Option(Option::V6, 1000, OptionBuffer(10, 0xFF)));
- conf1.getCfgOption()->add(option, true, DHCP6_OPTION_SPACE);
+ conf1.getCfgOption()->add(option, true, false, DHCP6_OPTION_SPACE);
// Add a class dictionary
conf1.setClientClassDictionary(ref_dictionary_);
// Differ by option data.
OptionPtr option(new Option(Option::V6, 1000, OptionBuffer(1, 0xFF)));
- conf1.getCfgOption()->add(option, false, "isc");
+ conf1.getCfgOption()->add(option, false, false, "isc");
EXPECT_FALSE(conf1 == conf2);
EXPECT_TRUE(conf1 != conf2);
- conf2.getCfgOption()->add(option, false, "isc");
+ conf2.getCfgOption()->add(option, false, false, "isc");
EXPECT_TRUE(conf1 == conf2);
EXPECT_FALSE(conf1 != conf2);
// should result in exception.
OptionPtr option2;
ASSERT_FALSE(option2);
- EXPECT_THROW(subnet->getCfgOption()->add(option2, false, DHCP4_OPTION_SPACE),
+ EXPECT_THROW(subnet->getCfgOption()->add(option2, false, false,
+ DHCP4_OPTION_SPACE),
isc::BadValue);
}
// No slash sign.
EXPECT_THROW(Subnet4::parsePrefix("10.0.0.1"), BadValue);
-
- // IPv6 is not allowed here.
+ // IPv6 is not allowed here.
EXPECT_THROW(Subnet4::parsePrefix("3000::/24"), BadValue);
}
option_server_id->writeAddress(IOAddress("1.2.3.4"));
CfgOptionPtr cfg_option = subnet.getCfgOption();
- cfg_option->add(option_server_id, false, DHCP4_OPTION_SPACE);
+ cfg_option->add(option_server_id, false, false, DHCP4_OPTION_SPACE);
// Verify that the server identifier returned by the Subnet4 object is
// correct.
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, false,
+ DHCP6_OPTION_SPACE));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp6 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "isc"));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, false,
+ "isc"));
}
// Get options from the Subnet and check if all 10 are there.
// In the inner loop we create options with unique codes (100-109).
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, false,
+ DHCP6_OPTION_SPACE));
}
}
// and options with these codes will be flagged non-persistent.
// Options with other codes will be flagged persistent.
bool persistent = (code % 3) ? true : false;
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, persistent, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, persistent,
+ false,
+ DHCP6_OPTION_SPACE));
}
// Get added options from the subnet.
// Add 10 options to a "dhcp6" option space in the subnet.
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, DHCP6_OPTION_SPACE));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, false,
+ DHCP6_OPTION_SPACE));
}
// Check that we can get each added option descriptor using
// Differentiate options by their codes (100-109)
for (uint16_t code = 100; code < 110; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "vendor-12345678"));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, false,
+ "vendor-12345678"));
}
// Add 7 options to another option space. The option codes partially overlap
// with option codes that we have added to dhcp6 option space.
for (uint16_t code = 105; code < 112; ++code) {
OptionPtr option(new Option(Option::V6, code, OptionBuffer(10, 0xFF)));
- ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, "vendor-87654321"));
+ ASSERT_NO_THROW(subnet->getCfgOption()->add(option, false, false,
+ "vendor-87654321"));
}
// Get options from the Subnet and check if all 10 are there.
OptionDescriptor
GenericBackendTest::createEmptyOption(const Option::Universe& universe,
const uint16_t option_type,
- const bool persist) const {
+ const bool persist,
+ const bool cancel) const {
OptionPtr option(new Option(universe, option_type));
- OptionDescriptor desc(option, persist);
+ OptionDescriptor desc(option, persist, cancel);
return (desc);
}
OptionDescriptor
GenericBackendTest::createVendorOption(const Option::Universe& universe,
const bool persist,
+ const bool cancel,
const bool formatted,
const uint32_t vendor_id) const {
OptionVendorPtr option(new OptionVendor(universe, vendor_id));
s << vendor_id;
}
- OptionDescriptor desc(option, persist, s.str());
+ OptionDescriptor desc(option, persist, cancel, s.str());
return (desc);
}
// option when an option definition is available.
EXPECT_EQ(ref_option.formatted_value_, tested_option.formatted_value_);
EXPECT_EQ(ref_option.persistent_, tested_option.persistent_);
+ EXPECT_EQ(ref_option.cancelled_, tested_option.cancelled_);
EXPECT_EQ(ref_option.space_name_, tested_option.space_name_);
}
/// @param option_type Option type.
/// @param persist A boolean flag indicating if the option is always
/// returned to the client or only when requested.
+ /// @param cancel A boolean flag indicating if the option must never
+ /// be returned to the client,
///
/// @return Descriptor holding an empty option.
OptionDescriptor createEmptyOption(const Option::Universe& universe,
const uint16_t option_type,
- const bool persist) const;
+ const bool persist,
+ const bool cancel) const;
/// @brief Creates an instance of the option for which it is possible to
/// specify universe, option type, persistence flag and value in
/// @param option_type Option type.
/// @param persist A boolean flag indicating if the option is always
/// returned to the client or only when requested.
+ /// @param cancel A boolean flag indicating if the option must never
+ /// be returned to the client,
/// @param formatted A boolean value selecting if the formatted option
/// value should be used (if true), or binary value (if false).
/// @param value Option value to be assigned to the option.
OptionDescriptor createOption(const Option::Universe& universe,
const uint16_t option_type,
const bool persist,
+ const bool cancel,
const bool formatted,
const DataType& value) const {
boost::shared_ptr<OptionType> option(new OptionType(universe, option_type,
// textual format.
s << value;
}
- OptionDescriptor desc(option, persist, s.str());
+ OptionDescriptor desc(option, persist, cancel, s.str());
return (desc);
}
/// @param option_type Option type.
/// @param persist A boolean flag indicating if the option is always
/// returned to the client or only when requested.
+ /// @param cancel A boolean flag indicating if the option must never
+ /// be returned to the client,
/// @param formatted A boolean value selecting if the formatted option
/// value should be used (if true), or binary value (if false).
/// @param value Option value to be assigned to the option.
template<typename OptionType, typename DataType>
OptionDescriptor createOption(const uint16_t option_type,
const bool persist,
+ const bool cancel,
const bool formatted,
const DataType& value) const {
boost::shared_ptr<OptionType> option(new OptionType(option_type, value));
s << value;
}
- OptionDescriptor desc(option, persist, s.str());
+ OptionDescriptor desc(option, persist, cancel, s.str());
return (desc);
}
/// @param option_type Option type.
/// @param persist A boolean flag indicating if the option is always
/// returned to the client or only when requested.
+ /// @param cancel A boolean flag indicating if the option must never
+ /// be returned to the client,
/// @param formatted A boolean value selecting if the formatted option
/// value should be used (if true), or binary value (if false).
/// @param address1 First address to be included. If address is empty, it is
OptionDescriptor
createAddressOption(const uint16_t option_type,
const bool persist,
+ const bool cancel,
const bool formatted,
const std::string& address1 = "",
const std::string& address2 = "",
boost::shared_ptr<OptionType> option(new OptionType(option_type,
addresses));
- OptionDescriptor desc(option, persist, s.str());
+ OptionDescriptor desc(option, persist, cancel, s.str());
return (desc);
}
/// @param universe V4 or V6.
/// @param persist A boolean flag indicating if the option is always
/// returned to the client or only when requested.
+ /// @param cancel A boolean flag indicating if the option must never
+ /// be returned to the client,
/// @param formatted A boolean value selecting if the formatted option
/// value should be used (if true), or binary value (if false).
/// @param vendor_id Vendor identifier.
/// @return Descriptor holding an instance of the option created.
OptionDescriptor createVendorOption(const Option::Universe& universe,
const bool persist,
+ const bool cancel,
const bool formatted,
const uint32_t vendor_id) const;
} // end of namespace isc
#endif
-
// Add several options to the subnet.
subnet->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_);
subnet->getCfgOption()->add(test_options_[1]->option_,
test_options_[1]->persistent_,
+ test_options_[1]->cancelled_,
test_options_[1]->space_name_);
subnet->getCfgOption()->add(test_options_[2]->option_,
test_options_[2]->persistent_,
+ test_options_[2]->cancelled_,
test_options_[2]->space_name_);
test_subnets_.push_back(subnet);
pool1->getCfgOption()->add(test_options_[3]->option_,
test_options_[3]->persistent_,
+ test_options_[3]->cancelled_,
test_options_[3]->space_name_);
pool1->getCfgOption()->add(test_options_[4]->option_,
test_options_[4]->persistent_,
+ test_options_[4]->cancelled_,
test_options_[4]->space_name_);
pool2.reset(new Pool4(IOAddress("10.0.0.50"),
subnet->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_);
test_subnets_.push_back(subnet);
// Add several options to the shared network.
shared_network->getCfgOption()->add(test_options_[2]->option_,
test_options_[2]->persistent_,
+ test_options_[2]->cancelled_,
test_options_[2]->space_name_);
shared_network->getCfgOption()->add(test_options_[3]->option_,
test_options_[3]->persistent_,
+ test_options_[3]->cancelled_,
test_options_[3]->space_name_);
shared_network->getCfgOption()->add(test_options_[4]->option_,
test_options_[4]->persistent_,
+ test_options_[4]->cancelled_,
test_options_[4]->space_name_);
test_networks_.push_back(shared_network);
shared_network->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_);
test_networks_.push_back(shared_network);
OptionDescriptor desc =
createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "my-boot-file");
+ true, false, false, "my-boot-file");
desc.space_name_ = DHCP4_OPTION_SPACE;
desc.setContext(user_context);
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
desc = createOption<OptionUint8>(Option::V4, DHO_DEFAULT_IP_TTL,
- false, true, 64);
+ false, true, true, 64);
desc.space_name_ = DHCP4_OPTION_SPACE;
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createOption<OptionUint32>(Option::V4, 1, false, false, 312131),
+ desc = createOption<OptionUint32>(Option::V4, 1, false, false, false, 312131),
desc.space_name_ = "vendor-encapsulated-options";
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createAddressOption<Option4AddrLst>(254, true, true,
+ desc = createAddressOption<Option4AddrLst>(254, true, true, true,
"192.0.2.3");
desc.space_name_ = DHCP4_OPTION_SPACE;
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createEmptyOption(Option::V4, 1, true);
+ desc = createEmptyOption(Option::V4, 1, true, true);
desc.space_name_ = "isc";
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createAddressOption<Option4AddrLst>(2, false, true,
+ desc = createAddressOption<Option4AddrLst>(2, false, false, true,
"10.0.0.5",
"10.0.0.3",
"10.0.3.4");
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
desc = createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "my-boot-file-2");
+ true, false, false, "my-boot-file-2");
desc.space_name_ = DHCP4_OPTION_SPACE;
desc.setContext(user_context);
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
desc = createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "my-boot-file-3");
+ true, true, false, "my-boot-file-3");
desc.space_name_ = DHCP4_OPTION_SPACE;
desc.setContext(user_context);
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
// Modify option and update it in the database.
opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
+ opt_boot_file_name->cancelled_ = !opt_boot_file_name->cancelled_;
cbptr_->createUpdateOption4(ServerSelector::ALL(),
opt_boot_file_name);
ASSERT_EQ(3, countRows("dhcp4_options"));
opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
+ opt_boot_file_name->cancelled_ = !opt_boot_file_name->cancelled_;
cbptr_->createUpdateOption4(ServerSelector::ANY(), subnet->getID(),
opt_boot_file_name);
// Modify the option and update it in the database.
opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
+ opt_boot_file_name->cancelled_ = !opt_boot_file_name->cancelled_;
cbptr_->createUpdateOption4(ServerSelector::ANY(),
pool->getFirstAddress(),
pool->getLastAddress(),
ASSERT_EQ(1, countRows("dhcp4_options"));
opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
+ opt_boot_file_name->cancelled_ = !opt_boot_file_name->cancelled_;
cbptr_->createUpdateOption4(ServerSelector::ANY(),
shared_network->getName(),
opt_boot_file_name);
auto class1 = test_client_classes_[0];
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_));
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[1]->option_,
test_options_[1]->persistent_,
+ test_options_[1]->cancelled_,
test_options_[1]->space_name_));
ASSERT_NO_THROW_LOG(cbptr_->createUpdateClientClass4(ServerSelector::ALL(), class1, ""));
auto class1 = test_client_classes_[0];
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_));
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[1]->option_,
test_options_[1]->persistent_,
+ test_options_[1]->cancelled_,
test_options_[1]->space_name_));
auto cfg_option_def = boost::make_shared<CfgOptionDef>();
class1->setCfgOptionDef(cfg_option_def);
// Add several options to the subnet.
subnet->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_);
subnet->getCfgOption()->add(test_options_[1]->option_,
test_options_[1]->persistent_,
+ test_options_[1]->cancelled_,
test_options_[1]->space_name_);
subnet->getCfgOption()->add(test_options_[2]->option_,
test_options_[2]->persistent_,
+ test_options_[2]->cancelled_,
test_options_[2]->space_name_);
test_subnets_.push_back(subnet);
pool1->getCfgOption()->add(test_options_[3]->option_,
test_options_[3]->persistent_,
+ test_options_[3]->cancelled_,
test_options_[3]->space_name_);
pool1->getCfgOption()->add(test_options_[4]->option_,
test_options_[4]->persistent_,
+ test_options_[4]->cancelled_,
test_options_[4]->space_name_);
pool2.reset(new Pool6(Lease::TYPE_NA,
pdpool1->getCfgOption()->add(test_options_[3]->option_,
test_options_[3]->persistent_,
+ test_options_[3]->cancelled_,
test_options_[3]->space_name_);
pdpool1->getCfgOption()->add(test_options_[4]->option_,
test_options_[4]->persistent_,
+ test_options_[4]->cancelled_,
test_options_[4]->space_name_);
// Create the prefix delegation pool with an excluded prefix.
subnet->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_);
test_subnets_.push_back(subnet);
// Add several options to the shared network.
shared_network->getCfgOption()->add(test_options_[2]->option_,
test_options_[2]->persistent_,
+ test_options_[2]->cancelled_,
test_options_[2]->space_name_);
shared_network->getCfgOption()->add(test_options_[3]->option_,
test_options_[3]->persistent_,
+ test_options_[3]->cancelled_,
test_options_[3]->space_name_);
shared_network->getCfgOption()->add(test_options_[4]->option_,
test_options_[4]->persistent_,
+ test_options_[4]->cancelled_,
test_options_[4]->space_name_);
test_networks_.push_back(shared_network);
shared_network->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_);
test_networks_.push_back(shared_network);
OptionDescriptor desc =
createOption<OptionString>(Option::V6, D6O_NEW_POSIX_TIMEZONE,
- true, false, "my-timezone");
+ true, false, false, "my-timezone");
desc.space_name_ = DHCP6_OPTION_SPACE;
desc.setContext(user_context);
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
desc = createOption<OptionUint8>(Option::V6, D6O_PREFERENCE,
- false, true, 64);
+ false, false, true, 64);
desc.space_name_ = DHCP6_OPTION_SPACE;
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createOption<OptionUint32>(Option::V6, 1, false, false, 312131),
+ desc = createOption<OptionUint32>(Option::V6, 1, false, false, false, 312131),
desc.space_name_ = "vendor-encapsulated-options";
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createAddressOption<Option6AddrLst>(1254, true, true,
+ desc = createAddressOption<Option6AddrLst>(1254, true, true, true,
"2001:db8::3");
desc.space_name_ = DHCP6_OPTION_SPACE;
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createEmptyOption(Option::V6, 1, true);
+ desc = createEmptyOption(Option::V6, 1, true, false);
desc.space_name_ = "isc";
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
- desc = createAddressOption<Option6AddrLst>(2, false, true,
+ desc = createAddressOption<Option6AddrLst>(2, false, false, true,
"2001:db8:1::5",
"2001:db8:1::3",
"2001:db8:3::4");
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
desc = createOption<OptionString>(Option::V6, D6O_NEW_POSIX_TIMEZONE,
- true, false, "my-timezone-2");
+ true, false, false, "my-timezone-2");
desc.space_name_ = DHCP6_OPTION_SPACE;
desc.setContext(user_context);
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
desc = createOption<OptionString>(Option::V6, D6O_NEW_POSIX_TIMEZONE,
- true, false, "my-timezone-3");
+ true, true, false, "my-timezone-3");
desc.space_name_ = DHCP6_OPTION_SPACE;
desc.setContext(user_context);
test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
// Modify option and update it in the database.
opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_;
+ opt_posix_timezone->cancelled_ = !opt_posix_timezone->cancelled_;
cbptr_->createUpdateOption6(ServerSelector::ALL(),
opt_posix_timezone);
ASSERT_EQ(5, countRows("dhcp6_options"));
opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_;
+ opt_posix_timezone->cancelled_ = !opt_posix_timezone->cancelled_;
cbptr_->createUpdateOption6(ServerSelector::ANY(), subnet->getID(),
opt_posix_timezone);
// Modify the option and update it in the database.
opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_;
+ opt_posix_timezone->cancelled_ = !opt_posix_timezone->cancelled_;
cbptr_->createUpdateOption6(ServerSelector::ANY(),
pool->getFirstAddress(),
pool->getLastAddress(),
// Modify the option and update it in the database.
opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_;
+ opt_posix_timezone->cancelled_ = !opt_posix_timezone->cancelled_;
cbptr_->createUpdateOption6(ServerSelector::ANY(),
pd_pool->getFirstAddress(),
static_cast<uint8_t>(pd_pool_len),
ASSERT_EQ(1, countRows("dhcp6_options"));
opt_posix_timezone->persistent_ = !opt_posix_timezone->persistent_;
+ opt_posix_timezone->cancelled_ = !opt_posix_timezone->cancelled_;
cbptr_->createUpdateOption6(ServerSelector::ANY(),
shared_network->getName(),
opt_posix_timezone);
auto class1 = test_client_classes_[0];
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_));
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[1]->option_,
test_options_[1]->persistent_,
+ test_options_[1]->cancelled_,
test_options_[1]->space_name_));
ASSERT_NO_THROW_LOG(cbptr_->createUpdateClientClass6(ServerSelector::ALL(), class1, ""));
auto class1 = test_client_classes_[0];
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[0]->option_,
test_options_[0]->persistent_,
+ test_options_[0]->cancelled_,
test_options_[0]->space_name_));
ASSERT_NO_THROW_LOG(class1->getCfgOption()->add(test_options_[1]->option_,
test_options_[1]->persistent_,
+ test_options_[1]->cancelled_,
test_options_[1]->space_name_));
auto cfg_option_def = boost::make_shared<CfgOptionDef>();
class1->setCfgOptionDef(cfg_option_def);
CfgOptionPtr opts = host->getCfgOption4();
OptionDescriptor desc =
createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, formatted, "my-boot-file");
+ true, false, formatted, "my-boot-file");
desc.setContext(user_context);
opts->add(desc, DHCP4_OPTION_SPACE);
opts->add(createOption<OptionUint8>(Option::V4, DHO_DEFAULT_IP_TTL,
- false, formatted, 64),
+ false, false, formatted, 64),
DHCP4_OPTION_SPACE);
- opts->add(createOption<OptionUint32>(Option::V4, 1, false, formatted, 312131),
+ opts->add(createOption<OptionUint32>(Option::V4, 1, false, false,
+ formatted, 312131),
"vendor-encapsulated-options");
- opts->add(createAddressOption<Option4AddrLst>(254, false, formatted,
- "192.0.2.3"), DHCP4_OPTION_SPACE);
- opts->add(createEmptyOption(Option::V4, 1, true), "isc");
- opts->add(createAddressOption<Option4AddrLst>(2, false, formatted, "10.0.0.5",
- "10.0.0.3", "10.0.3.4"), "isc");
+ opts->add(createAddressOption<Option4AddrLst>(254, false, false,
+ formatted, "192.0.2.3"),
+ DHCP4_OPTION_SPACE);
+ opts->add(createEmptyOption(Option::V4, 1, true, false), "isc");
+ opts->add(createAddressOption<Option4AddrLst>(2, false, false,
+ formatted, "10.0.0.5",
+ "10.0.0.3", "10.0.3.4"),
+ "isc");
// Add definitions for DHCPv4 non-standard options.
defs.addItem(OptionDefinitionPtr(new OptionDefinition(
CfgOptionPtr opts = host->getCfgOption6();
OptionDescriptor desc =
createOption<OptionString>(Option::V6, D6O_BOOTFILE_URL,
- true, formatted, "my-boot-file");
+ true, false, formatted, "my-boot-file");
desc.setContext(user_context);
opts->add(desc, DHCP6_OPTION_SPACE);
opts->add(createOption<OptionUint32>(Option::V6, D6O_INFORMATION_REFRESH_TIME,
- false, formatted, 3600),
+ false, false, formatted, 3600),
DHCP6_OPTION_SPACE);
- opts->add(createVendorOption(Option::V6, false, formatted, 2495),
+ opts->add(createVendorOption(Option::V6, false, false, formatted, 2495),
DHCP6_OPTION_SPACE);
- opts->add(createAddressOption<Option6AddrLst>(1024, false, formatted,
- "2001:db8:1::1"),
+ opts->add(createAddressOption<Option6AddrLst>(1024, false, false,
+ formatted, "2001:db8:1::1"),
DHCP6_OPTION_SPACE);
- opts->add(createEmptyOption(Option::V6, 1, true), "isc2");
- opts->add(createAddressOption<Option6AddrLst>(2, false, formatted, "3000::1",
- "3000::2", "3000::3"), "isc2");
+ opts->add(createEmptyOption(Option::V6, 1, true, false), "isc2");
+ opts->add(createAddressOption<Option6AddrLst>(2, false, false,
+ formatted, "3000::1",
+ "3000::2", "3000::3"),
+ "isc2");
// Add definitions for DHCPv6 non-standard options.
defs.addItem(OptionDefinitionPtr(new OptionDefinition(
CfgOptionPtr opts = host2->getCfgOption4();
OptionDescriptor desc =
createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "my-boot-file");
+ true, false, false, "my-boot-file");
opts->add(desc, DHCP4_OPTION_SPACE);
HostPtr host3 = HostDataSourceUtils::initializeHost4("192.0.2.3", id);
CfgOptionPtr opts = host2->getCfgOption6();
OptionDescriptor desc =
createOption<OptionString>(Option::V6, D6O_BOOTFILE_URL,
- true, true, "my-boot-file");
+ true, false, true, "my-boot-file");
opts->add(desc, DHCP6_OPTION_SPACE);
HostPtr host3 = HostDataSourceUtils::initializeHost6("2001:db8::3", id, false);
CfgOptionPtr opts = host->getCfgOption4();
OptionDescriptor desc =
createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, false, "my-boot-file");
+ true, false, false, "my-boot-file");
opts->add(desc, DHCP4_OPTION_SPACE);
opts->add(createOption<OptionUint8>(Option::V4, DHO_DEFAULT_IP_TTL,
- false, false, 64 + i),
+ false, true, false, 64 + i),
DHCP4_OPTION_SPACE);
- opts->add(createEmptyOption(Option::V4, 1, true), "isc");
+ opts->add(createEmptyOption(Option::V4, 1, true, true), "isc");
ASSERT_NO_THROW(hdsptr_->add(host));
}
CfgOptionPtr opts = host->getCfgOption6();
OptionDescriptor desc =
createOption<OptionString>(Option::V6, D6O_BOOTFILE_URL,
- true, false, "my-boot-file");
+ true, false, false, "my-boot-file");
opts->add(desc, DHCP6_OPTION_SPACE);
opts->add(createOption<OptionUint32>(Option::V6,
D6O_INFORMATION_REFRESH_TIME,
- false, false, 3600 + i),
+ false, true, false, 3600 + i),
DHCP6_OPTION_SPACE);
opts->add(createAddressOption<Option6AddrLst>(D6O_SIP_SERVERS_ADDR,
- false, false,
+ false, false, false,
addr.toText()),
DHCP6_OPTION_SPACE);
/// @name Current database schema version values.
//@{
-const uint32_t MYSQL_SCHEMA_VERSION_MAJOR = 14;
+const uint32_t MYSQL_SCHEMA_VERSION_MAJOR = 15;
const uint32_t MYSQL_SCHEMA_VERSION_MINOR = 0;
//@}
namespace db {
/// @brief Define the PostgreSQL backend version.
-const uint32_t PGSQL_SCHEMA_VERSION_MAJOR = 13;
+const uint32_t PGSQL_SCHEMA_VERSION_MAJOR = 14;
const uint32_t PGSQL_SCHEMA_VERSION_MINOR = 0;
// Maximum number of parameters that can be used a statement
" \"space\": \"dns\",\n"
" \"csv-format\": false,\n"
" \"data\": \"12121212\",\n"
- " \"always-send\": false\n"
+ " \"always-send\": false,\n"
+ " \"never-send\": false\n"
" }\n"
" ],\n"
" \"pools\": [\n"
" \"space\": \"dns\",\n"
" \"csv-format\": false,\n"
" \"data\": \"12121212\",\n"
- " \"always-send\": false\n"
+ " \"always-send\": false,\n"
+ " \"never-send\": false\n"
" }\n"
" ],\n"
" \"pool\": \"2001:db8::1:0/112\"\n"
const string& xoption = xpath + "/option-data[code='100'][space='dns']";
const string& xformat = xoption + "/csv-format";
const string& xdata = xoption + "/data";
- const string& xsend = xoption + "/always-send";
+ const string& xalways = xoption + "/always-send";
+ const string& xnever = xoption + "/never-send";
string const s_false("false");
ASSERT_NO_THROW_LOG(sess_->setItem(xformat, s_false));
string const s_data("12121212");
ASSERT_NO_THROW_LOG(sess_->setItem(xdata, s_data));
- ASSERT_NO_THROW_LOG(sess_->setItem(xsend, s_false));
+ ASSERT_NO_THROW_LOG(sess_->setItem(xalways, s_false));
+ ASSERT_NO_THROW_LOG(sess_->setItem(xnever, s_false));
sess_->applyChanges();
// Get the option data.
" \"code\": 100,"
" \"csv-format\": false,"
" \"data\": \"12121212\","
+ " \"never-send\": false,"
" \"space\": \"dns\""
" }",
option->str());
option->set("csv-format", Element::create(false));
option->set("data", Element::create("12121212"));
option->set("always-send", Element::create(false));
+ option->set("never-send", Element::create(false));
options->add(option);
EXPECT_NO_THROW_LOG(translator_->setOptionDataList(xpath, options));
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
"option-data[code='100'][space='dns']/always-send",
"false", libyang::LeafBaseType::Bool, true },
+ { "/kea-dhcp4-server:config/subnet4[id='111']/"
+ "option-data[code='100'][space='dns']/never-send",
+ "false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp4-server:config/subnet4[id='111']/"
"pool[start-address='10.0.1.0'][end-address='10.0.1.255']",
std::nullopt, libyang::LeafBaseType::Unknown, false },
"pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
"option-data[code='100'][space='dns']/always-send",
"false", libyang::LeafBaseType::Bool, true },
+ { "/kea-dhcp6-server:config/subnet6[id='111']/"
+ "pool[start-address='2001:db8::1:0'][end-address='2001:db8::1:ffff']/"
+ "option-data[code='100'][space='dns']/never-send",
+ "false", libyang::LeafBaseType::Bool, true },
{ "/kea-dhcp6-server:config/subnet6[id='111']/subnet",
"2001:db8::/48", libyang::LeafBaseType::String, true },
{ "/kea-dhcp6-server:config/expired-leases-processing",
checkAndGetLeaf(result, data_node, "csv-format");
checkAndGetLeaf(result, data_node, "data");
checkAndGetLeaf(result, data_node, "name");
+ checkAndGetLeaf(result, data_node, "never-send");
checkAndGetAndJsonifyLeaf(result, data_node, "user-context");
checkAndSetLeaf(elem, xpath, "csv-format", LeafBaseType::Bool);
checkAndSetLeaf(elem, xpath, "data", LeafBaseType::String);
checkAndSetLeaf(elem, xpath, "name", LeafBaseType::String);
+ checkAndSetLeaf(elem, xpath, "never-send", LeafBaseType::Bool);
checkAndSetUserContext(elem, xpath);
}
/// "csv-format": <csv format flag>,
/// "data": <value>,
/// "always-send": <always send flag>,
+/// "never-send": <never send flag>,
/// "user-context": { <json map> },
/// "comment": "<comment>"
/// }
/// +--rw data? string
/// +--rw csv-format? boolean
/// +--rw always-send? boolean
+/// +--rw never-send? boolean
/// +--rw user-context? user-context
/// @endcode
///
/// "space": "dns",
/// "csv-format": false,
/// "data": "12121212",
-/// "always-send": false
+/// "always-send": false,
+/// "never-send": false
/// }
/// ]
/// @endcode
/// option-data[code='100'][space='dns']/csv-format = false
/// /kea-dhcp6-server:config/
/// option-data[code='100'][space='dns']/always-send = false
+/// /kea-dhcp6-server:config/
+/// option-data[code='100'][space='dns']/never-send = false
/// @endcode
/// @brief A translator class for converting an option data between
{ "ietf-dhcpv6-options", "2018-09-04" },
{ "ietf-dhcpv6-server", "2018-09-04" },
{ "kea-types", "2019-08-12" },
- { "kea-dhcp-types", "2022-11-30" },
- { "kea-dhcp4-server", "2022-11-30" },
- { "kea-dhcp6-server", "2022-11-30" },
+ { "kea-dhcp-types", "2022-12-27" },
+ { "kea-dhcp4-server", "2022-12-27" },
+ { "kea-dhcp6-server", "2022-12-27" },
{ "kea-ctrl-agent", "2019-08-12" },
{ "kea-dhcp-ddns", "2022-07-27" }
}; // YANG_REVISIONS
mysql_SCRIPTS += upgrade_011_to_012.sh
mysql_SCRIPTS += upgrade_012_to_013.sh
mysql_SCRIPTS += upgrade_013_to_014.sh
+mysql_SCRIPTS += upgrade_014_to_015.sh
mysql_SCRIPTS += wipe_data.sh
DISTCLEANFILES = ${mysql_SCRIPTS}
-- This line concludes the schema upgrade to version 14.
+-- This line starts the schema upgrade to version 15.
+
+-- Add cancelled (aka never-send) column to option tables.
+
+ALTER TABLE dhcp4_options
+ ADD COLUMN cancelled TINYINT(1) NOT NULL DEFAULT 0;
+
+ALTER TABLE dhcp6_options
+ ADD COLUMN cancelled TINYINT(1) NOT NULL DEFAULT 0;
+
+-- Update the schema version number.
+UPDATE schema_version
+ SET version = '15', minor = '0';
+
+-- This line concludes the schema upgrade to version 15.
+
# Notes:
#
# Indexes
pgsql_SCRIPTS += upgrade_010_to_011.sh
pgsql_SCRIPTS += upgrade_011_to_012.sh
pgsql_SCRIPTS += upgrade_012_to_013.sh
+pgsql_SCRIPTS += upgrade_013_to_014.sh
pgsql_SCRIPTS += wipe_data.sh
DISTCLEANFILES = ${pgsql_SCRIPTS}
-- This line concludes the schema upgrade to version 13.
+-- This line starts the schema upgrade to version 14.
+
+-- Add cancelled (aka never-send) column to option tables.
+
+ALTER TABLE dhcp4_options ADD COLUMN cancelled BOOLEAN NOT NULL DEFAULT 'f';
+ALTER TABLE dhcp6_options ADD COLUMN cancelled BOOLEAN NOT NULL DEFAULT 'f';
+
+-- Update the schema version number.
+UPDATE schema_version
+ SET version = '14', minor = '0';
+
+-- This line concludes the schema upgrade to version 14.
+
-- Commit the script transaction.
COMMIT;