opt != question->options_.end(); ++opt) {
switch (opt->second->getType()) {
case D6O_IA_NA: {
- OptionPtr answer_opt = assignIA_NA(question, answer, ctx,
+ OptionPtr answer_opt = assignIA_NA(question, ctx,
boost::dynamic_pointer_cast<
Option6IA>(opt->second));
if (answer_opt) {
break;
}
case D6O_IA_PD: {
- OptionPtr answer_opt = assignIA_PD(question, answer, ctx,
+ OptionPtr answer_opt = assignIA_PD(question, ctx,
boost::dynamic_pointer_cast<
Option6IA>(opt->second));
if (answer_opt) {
// current configuration.
d2_mgr.adjustFqdnFlags<Option6ClientFqdn>(*fqdn, *fqdn_resp, *ddns_params);
+ // Get DDNS update direction flags
+ CfgMgr::instance().getD2ClientMgr().getUpdateDirections(*fqdn_resp, ctx.fwd_dns_update_,
+ ctx.rev_dns_update_);
+
// If there's a reservation and it has a hostname specified, use it!
if (ctx.currentHost() && !ctx.currentHost()->getHostname().empty()) {
// Add the qualifying suffix.
}
OptionPtr
-Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
+Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query,
AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) {
return (ia_rsp);
}
- // Get DDNS update direction flags
- bool do_fwd = false;
- bool do_rev = false;
- Option6ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
- Option6ClientFqdn>(answer->getOption(D6O_CLIENT_FQDN));
- if (fqdn) {
- CfgMgr::instance().getD2ClientMgr().getUpdateDirections(*fqdn, do_fwd,
- do_rev);
- }
-
- // Update per-packet context values.
- ctx.fwd_dns_update_ = do_fwd;
- ctx.rev_dns_update_ = do_rev;
-
// Set per-IA context values.
ctx.createIAContext();
ctx.currentIA().iaid_ = ia->getIAID();
}
OptionPtr
-Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& /*answer*/,
+Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query,
AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) {
}
OptionPtr
-Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
+Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query,
AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia) {
return (ia_rsp);
}
- // Get DDNS update directions
- bool do_fwd = false;
- bool do_rev = false;
- Option6ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
- Option6ClientFqdn>(answer->getOption(D6O_CLIENT_FQDN));
- if (fqdn) {
- CfgMgr::instance().getD2ClientMgr().getUpdateDirections(*fqdn,
- do_fwd, do_rev);
- }
-
- // Set per-packet context values.
- ctx.fwd_dns_update_ = do_fwd;
- ctx.rev_dns_update_ = do_rev;
-
// Set per-IA context values.
ctx.createIAContext();
ctx.currentIA().iaid_ = ia->getIAID();
// If the new FQDN settings have changed for the lease, we need to
// delete any existing FQDN records for this lease.
- if (((*l)->hostname_ != ctx.hostname_) || ((*l)->fqdn_fwd_ != do_fwd) ||
- ((*l)->fqdn_rev_ != do_rev)) {
+ if (((*l)->hostname_ != ctx.hostname_) || ((*l)->fqdn_fwd_ != ctx.fwd_dns_update_) ||
+ ((*l)->fqdn_rev_ != ctx.rev_dns_update_)) {
LOG_DEBUG(ddns6_logger, DBG_DHCP6_DETAIL,
DHCP6_DDNS_REMOVE_OLD_LEASE_FQDN)
.arg(query->getLabel())
.arg((*l)->toText())
.arg(ctx.hostname_)
- .arg(do_rev ? "true" : "false")
- .arg(do_fwd ? "true" : "false");
+ .arg(ctx.rev_dns_update_ ? "true" : "false")
+ .arg(ctx.fwd_dns_update_ ? "true" : "false");
queueNCR(CHG_REMOVE, *l);
}
opt != query->options_.end(); ++opt) {
switch (opt->second->getType()) {
case D6O_IA_NA: {
- OptionPtr answer_opt = extendIA_NA(query, reply, ctx,
+ OptionPtr answer_opt = extendIA_NA(query, ctx,
boost::dynamic_pointer_cast<
Option6IA>(opt->second));
if (answer_opt) {
/// allocation failure.
///
/// @param query client's message (typically SOLICIT or REQUEST)
- /// @param answer server's response to the client's message. This
- /// message should contain Client FQDN option being sent by the server
/// to the client (if the client sent this option to the server).
/// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia pointer to client's IA_NA option (client's request)
///
/// @return IA_NA option (server's response)
OptionPtr assignIA_NA(const isc::dhcp::Pkt6Ptr& query,
- const isc::dhcp::Pkt6Ptr& answer,
AllocEngine::ClientContext6& ctx,
Option6IAPtr ia);
/// allocation failure.
///
/// @param query client's message (typically SOLICIT or REQUEST)
- /// @param answer server's response to the client's message (unused).
/// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia pointer to client's IA_PD option (client's request)
/// @return IA_PD option (server's response)
OptionPtr assignIA_PD(const Pkt6Ptr& query,
- const isc::dhcp::Pkt6Ptr& answer,
AllocEngine::ClientContext6& ctx,
boost::shared_ptr<Option6IA> ia);
/// status code.
///
/// @param query client's message (Renew or Rebind)
- /// @param answer server's response to the client's message. This
- /// message should contain Client FQDN option being sent by the server
/// to the client (if the client sent this option to the server).
/// @param ctx client context (contains subnet, duid and other parameters)
/// @param ia IA_NA option which carries address for which lease lifetime
/// will be extended.
/// @return IA_NA option (server's response)
- OptionPtr extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
+ OptionPtr extendIA_NA(const Pkt6Ptr& query,
AllocEngine::ClientContext6& ctx,
Option6IAPtr ia);
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true, "2001:db8:1::1",
"", 0, 4000, "client1.one.example.com.");
- // Make sure the lease hostname is correct.
+ // Make sure the lease hostname and fqdn flags are correct.
Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
IOAddress("2001:db8:1::1"));
ASSERT_TRUE(lease);
EXPECT_EQ("client1.one.example.com.", lease->hostname_);
+ EXPECT_TRUE(lease->fqdn_fwd_);
+ EXPECT_TRUE(lease->fqdn_rev_);
// Now let's try with a different client. Subnet 1 is full so we should get an
// address from subnet 2.
verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true, "2001:db8:2::1",
"", 0, 4000, "client2.two.example.com.");
- // Make sure the lease hostname is correct.
+ // Make sure the lease hostname and fqdn flags are correct.
lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::1"));
ASSERT_TRUE(lease);
EXPECT_EQ("client2.two.example.com.", lease->hostname_);
+ EXPECT_TRUE(lease->fqdn_fwd_);
+ EXPECT_TRUE(lease->fqdn_rev_);
// Now let's check Renewals
// First we'll renew a client2.
// not update, unless the FQDN or flags change.
ASSERT_EQ(0, CfgMgr::instance().getD2ClientMgr().getQueueSize());
- // Make sure the lease hostname is correct.
+ // Make sure the lease hostname and fqdn flags are correct.
lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::1"));
ASSERT_TRUE(lease);
EXPECT_EQ("client1.one.example.com.", lease->hostname_);
+ EXPECT_TRUE(lease->fqdn_fwd_);
+ EXPECT_TRUE(lease->fqdn_rev_);
+}
+
+// Verifies lease and NCR content (or lack of NCRs) are correct when
+// subnets in a shared-network define different values for send-ddns-updates
+// This checks that we get the right results even when the allocation engine
+// changes the subnet chosen. The configuration is two 1-address pool subnets in
+// a shared-network. The first client will do a SARR, which consumes the first
+// pool. This should cause the allocation engine to dynamically select
+// the second subnet for the second client.
+TEST_F(FqdnDhcpv6SrvTest, ddnsSharedNetworkTest2) {
+ std::string config_str =
+ "{ \"interfaces-config\": { \n"
+ " \"interfaces\": [ \"*\" ] \n"
+ "}, \n"
+ "\"preferred-lifetime\": 3000, \n"
+ "\"rebind-timer\": 2000, \n"
+ "\"renew-timer\": 1000, \n"
+ "\"valid-lifetime\": 4000, \n"
+ "\"shared-networks\": [ \n"
+ "{ \n"
+ "\"name\": \"frog\", \n"
+ "\"interface\": \"eth0\", \n"
+ "\"subnet6\": [ { \n"
+ "\"subnet\": \"2001:db8:1::/64\", \n"
+ "\"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::1\" } ], \n"
+ "\"interface\": \"eth0\", \n"
+ "\"ddns-qualifying-suffix\": \"one.example.com.\", \n"
+ "\"ddns-send-updates\": true \n"
+ " }, \n"
+ " { \n"
+ "\"subnet\": \"2001:db8:2::/64\", \n"
+ "\"pools\": [ { \"pool\": \"2001:db8:2::1 - 2001:db8:2::1\" } ], \n"
+ "\"interface\": \"eth0\", \n"
+ "\"ddns-qualifying-suffix\": \"two.example.com.\", \n"
+ "\"ddns-send-updates\": false \n"
+ " } ] \n"
+ "} ], \n"
+ "\"dhcp-ddns\" : { \n"
+ " \"enable-updates\" : true \n"
+ " } \n"
+ "}";
+
+ Dhcp6Client client1;
+ client1.setInterface("eth0");
+ client1.requestAddress();
+
+ // Load a configuration with D2 enabled
+ ASSERT_NO_FATAL_FAILURE(configure(config_str, *client1.getServer()));
+ ASSERT_TRUE(CfgMgr::instance().ddnsEnabled());
+ ASSERT_NO_THROW(client1.getServer()->startD2());
+
+ // Include the Client FQDN option.
+ ASSERT_NO_THROW(client1.useFQDN(Option6ClientFqdn::FLAG_S, "client1",
+ Option6ClientFqdn::PARTIAL));
+
+ // Now do a SARR.
+ ASSERT_NO_THROW(client1.doSARR());
+ Pkt6Ptr resp = client1.getContext().response_;
+ ASSERT_TRUE(resp);
+ ASSERT_EQ(DHCPV6_REPLY, static_cast<int>(resp->getType()));
+
+ // Check that the response FQDN is as expected.
+ Option6ClientFqdnPtr fqdn;
+ fqdn = boost::dynamic_pointer_cast<Option6ClientFqdn>(resp->getOption(D6O_CLIENT_FQDN));
+ ASSERT_TRUE(fqdn);
+ EXPECT_EQ("client1.one.example.com.", fqdn->getDomainName());
+
+ // ddns-send-updates for subnet 1 are enabled, verify the NCR is correct.
+ ASSERT_EQ(1, CfgMgr::instance().getD2ClientMgr().getQueueSize());
+ verifyNameChangeRequest(isc::dhcp_ddns::CHG_ADD, true, true, "2001:db8:1::1",
+ "", 0, 4000, "client1.one.example.com.");
+
+ // Make sure the lease hostname and fdqn flags are correct.
+ Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA,
+ IOAddress("2001:db8:1::1"));
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("client1.one.example.com.", lease->hostname_);
+ EXPECT_TRUE(lease->fqdn_fwd_);
+ EXPECT_TRUE(lease->fqdn_rev_);
+
+ // Now let's try with a different client. Subnet 1 is full so we should get an
+ // address from subnet 2.
+ Dhcp6Client client2(client1.getServer());
+ client2.setInterface("eth0");
+ client2.requestAddress();
+
+ // Include the Client FQDN option.
+ ASSERT_NO_THROW(client2.useFQDN(Option6ClientFqdn::FLAG_S, "client2",
+ Option6ClientFqdn::PARTIAL));
+
+ // Do a SARR.
+ ASSERT_NO_THROW(client2.doSARR());
+ resp = client2.getContext().response_;
+ ASSERT_TRUE(resp);
+ ASSERT_EQ(DHCPV6_REPLY, static_cast<int>(resp->getType()));
+
+ // Check that the response FQDN is as expected.
+ fqdn = boost::dynamic_pointer_cast<Option6ClientFqdn>(resp->getOption(D6O_CLIENT_FQDN));
+ ASSERT_TRUE(fqdn);
+ EXPECT_EQ("client2.two.example.com.", fqdn->getDomainName());
+
+ // ddns-send-updates for subnet 2 are disabled, verify there is no NCR.
+ ASSERT_EQ(0, CfgMgr::instance().getD2ClientMgr().getQueueSize());
+
+ // Make sure the lease hostname and fdqn flags are correct.
+ lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, IOAddress("2001:db8:2::1"));
+ ASSERT_TRUE(lease);
+ EXPECT_EQ("client2.two.example.com.", lease->hostname_);
+ EXPECT_FALSE(lease->fqdn_fwd_);
+ EXPECT_FALSE(lease->fqdn_rev_);
}
// Verifies that renews only generate NCRs if the situation dictates